Files
FabledScribe/plugin/hooks/scribe_static_context.md
T
bvandeusenandClaude Fable 5 3ff8803593
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 7s
CI & Build / integration (push) Successful in 18s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 47s
CI & Build / Build & push image (push) Successful in 28s
feat(instructions): fit the delivery fold — 2k server map, floor Systems reflex, write-time systems_hint
Claude Code injects only the first ~2,048 chars of an MCP server's
instructions and silently cuts the rest mid-word (#2562, observed live):
_INSTRUCTIONS was 20,002 chars, so ~90% — including all Systems tagging
guidance — never reached any session. Rearchitect delivery around what
each surface actually delivers:

- _INSTRUCTIONS becomes a 1,997-char purpose-sorted map, with a header
  comment stating the budget and where detail belongs instead.
- Tool docstrings keep the per-tool HOW (audit: nearly all displaced
  topics were already duplicated there); backfill the four gaps —
  enter_project session scoping + project bootstrap, create_rule
  entity-vs-rule test, create_design_system not-a-rulebook,
  create_system two-records test.
- The plugin static context (the delivery floor) gains the
  tag-to-Systems reflex and a surfaces-layering statement; plugin
  0.1.25 -> 0.1.26 so the executing cache refreshes (#2209).
- create_task / create_note / create_snippet return a systems_hint when
  a record is created untagged in a project that has Systems — in-band
  at the exact write it applies to, fail-open like the dedup gate.
- Guards: _INSTRUCTIONS length budget, floor-states-the-reflex, and a
  displaced-topics sweep asserting every cut topic still lives on a
  delivered surface.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 12:53:35 -04:00

5.4 KiB

Scribe — your system of record

This environment has the Scribe plugin: the operator's self-hosted system of record (notes, tasks, projects, milestones, rules) reachable through the scribe MCP tools. Treat Scribe — not local files — as the source of truth for the operator's work, and as your own working memory across sessions.

At the start of this session:

  • Call list_always_on_rules() to load the operator's binding rules.
  • If the working repo maps to a Scribe project (check list_repo_bindings), call enter_project(<id>) to load that project's rules, open tasks, and recent notes in one shot.

While you work:

  • Operator rules govern consequential actions — before any git branch / commit / push, or any other hard-to-reverse or outward-facing action, the operator's Scribe rules decide what to do — NOT generic conventions baked into the harness or your defaults (e.g. "branch before committing," "open a feature branch per task," "push to a fork"). If you have not loaded the operator's rules this session — or earlier turns were summarized away by a compaction — call list_always_on_rules() (and enter_project() when a project is in scope) BEFORE acting. When a loaded rule and a default habit disagree, the rule wins; if no rule speaks to it, ask rather than assume.
  • Recall before acting — before you answer anything about the operator's work or start a task, search Scribe first; assume a related note, task, or decision already exists. Concretely, reach for recall whenever a request touches the operator's projects, people, places, prior decisions, or existing work: check for an existing task before opening a new one, and for a prior note/decision before re-deriving one. When a project is in scope (you entered one), pass its id to search so results stay scoped to it. Treating Scribe as the first place you look — not just somewhere you write — is what makes it a trustworthy record.
  • Record as you go — track work as Scribe tasks and log progress with add_task_log. Always log when you complete a task and when you hit or discover a problem — so changes of direction are captured, not just successes. Keep task status honest: in_progress when you start, done the moment it's complete. When you fix something — even in passing — record it as its own issue (create_task(kind="issue")), not as a work-log line on an unrelated open task.
  • Tag to Systems as you writeenter_project lists the project's Systems (its named subsystems/areas). When you create or meaningfully update a record, ask which area it is about and pass system_ids; if the area has no System yet, create it with create_system (name + a one-paragraph charter) rather than leaving it unmodelled. A record about no particular area takes none — don't force it. Untagged writes in a project that has Systems come back with a systems_hint naming them — treat it as the tagging question asked at exactly the right moment, not as noise to skip past.
  • Reuse before rebuilding — before writing a new helper/utility/component, search recorded snippets (reusable code recorded once for recall) and reuse the prior art instead of re-solving it; when you build something reusable, record it with create_snippet (name, code, when-to-reach-for-it, location) so a later session is offered it, not left to write it again.
  • Do not keep the operator's rules, plans, or project notes in local memory / CLAUDE.md in parallel with Scribe — Scribe holds the single copy.
  • Compact at clean seams — because you record as you go, a context compaction is safe: the durable record lives in Scribe, not the transcript. After finishing a block of work in a long session, make sure in-flight state is logged to Scribe, then tell the operator it's a good, safe moment to /compact (name what you logged). You can't run it yourself — surface the recommendation and let them decide. Suggest it at seams, not every turn.

How the instruction surfaces divide the work: this file carries the session-level reflexes (WHEN to reach for Scribe); each tool's own description carries its full contract (HOW to call it — read it when you load the tool); the bundled skills carry process arcs (planning, debugging, verification). The MCP server's instruction block is deliberately only a map — the client injects roughly its first 2,000 characters and silently cuts the rest, so nothing load-bearing lives below that fold.

If two Scribe instruction surfaces disagree — this file, the MCP server's tool instructions, the using-scribe skill — follow the one that assumes least about its own delivery. This file is the floor: it ships with the plugin and needs no API key and no network, so it still applies in exactly the session where the others never arrived. The others may elaborate on what is written here; they must not contradict it. Weigh a disagreement by which way it fails, not by which surface said more: doing something a push would also have covered costs one redundant call, while skipping it because you expected a push that never came means working without the operator's rules and not knowing. A contradiction between surfaces is a defect in the product — say so, so it gets recorded and fixed rather than silently arbitrated again next session.

If the Scribe tools are unavailable, say so rather than silently falling back to local notes.