feat(rules): the instruction surfaces say to RETRIEVE a rule, not only to receive one (#3523) #140

Merged
bvandeusen merged 1 commits from dev into main 2026-09-03 22:07:11 -04:00
Owner

Every instruction surface told a session to load the always-on rules and stopped there. None said the loaded set is partial — so an empty one read as "no rule applies" when it only ever meant "none was pushed". Different claims, and only one of them has been checked.

That is #2198's asymmetry moved one level in. The earlier defect was trusting the SessionStart push over the explicit pull; this is trusting the resident tier as if it were the whole rulebook.

It is also why the always-on tier was the only one that worked — on any install rather than this one (rule 115). A rule nothing retrieves must be resident to bind at all, and a resident rule costs tokens in every session forever, so a rulebook that only delivers cannot grow past what one session holds. Retrieval lifts that ceiling, and it fires only if something asks. A tool-choice reflex asks least of all (#3476, #161).

What changed

The same obligation on all three session-start surfaces, because rule 119 makes them the specification jointly and a surface stating it differently IS the product behaving differently (#2497):

  • mcp/server.py _INSTRUCTIONS — the HOW bullet
  • plugin/hooks/scribe_static_context.md — a new bullet under "While you work"
  • plugin/skills/using-scribe/SKILL.md — reflex 2, with the two tiers and "ask hardest where you feel most certain"

Pinned by test_every_session_start_surface_states_the_conditional_retrieval, mirroring the pull test beside it.

The budget trade

_INSTRUCTIONS sat at 1978 against a 2000 test budget (~2048 client cap, #2562), and its own comment says an addition there is a trade, never an append. The new clause was bought by trading out "Processes are saved procedures (follow verbatim)" and "Deletes are trash-recoverable" — both already in DISPLACED_TOPICS, both verified still stated on a delivered surface, and both per-tool guidance which by this block's doctrine belongs in the tool docstring. Now 1976. Recorded in the comment above the block so it is not silently reversed.

Why this merges now

The plugin half only ships from main. Two of the three surfaces are plugin content and the marketplace tracks main, so until this merges the MCP block would carry the new instruction while the two plugin surfaces still state the old one — the exact disagreement test_instruction_surfaces_agree.py exists to prevent, split across a deploy boundary instead of across files.

Deploy

Image and /plugin (version minted 2026.09.04.0140 — shipped plugin content moved). No migration.

CI green on dev @ 30d87e4 (run 5487).

🤖 Generated with Claude Code

https://claude.ai/code/session_011cPyzNnegXHr5iRMzzy5KJ

Every instruction surface told a session to load the always-on rules and stopped there. None said the loaded set is partial — so an empty one read as "no rule applies" when it only ever meant "none was pushed". Different claims, and only one of them has been checked. That is #2198's asymmetry moved one level in. The earlier defect was trusting the SessionStart *push* over the explicit *pull*; this is trusting the resident *tier* as if it were the whole rulebook. It is also why the always-on tier was the only one that worked — on any install rather than this one (rule 115). A rule nothing retrieves must be resident to bind at all, and a resident rule costs tokens in every session forever, so a rulebook that only delivers cannot grow past what one session holds. Retrieval lifts that ceiling, and it fires only if something asks. A tool-choice reflex asks least of all (#3476, #161). ## What changed The same obligation on all three session-start surfaces, because rule 119 makes them the specification jointly and a surface stating it differently IS the product behaving differently (#2497): - `mcp/server.py` `_INSTRUCTIONS` — the HOW bullet - `plugin/hooks/scribe_static_context.md` — a new bullet under "While you work" - `plugin/skills/using-scribe/SKILL.md` — reflex 2, with the two tiers and "ask hardest where you feel most certain" Pinned by `test_every_session_start_surface_states_the_conditional_retrieval`, mirroring the pull test beside it. ## The budget trade `_INSTRUCTIONS` sat at 1978 against a 2000 test budget (~2048 client cap, #2562), and its own comment says an addition there is a trade, never an append. The new clause was bought by trading out "Processes are saved procedures (follow verbatim)" and "Deletes are trash-recoverable" — both already in `DISPLACED_TOPICS`, both verified still stated on a delivered surface, and both per-tool guidance which by this block's doctrine belongs in the tool docstring. Now 1976. Recorded in the comment above the block so it is not silently reversed. ## Why this merges now The plugin half only ships from `main`. Two of the three surfaces are plugin content and the marketplace tracks `main`, so until this merges the MCP block would carry the new instruction while the two plugin surfaces still state the old one — the exact disagreement `test_instruction_surfaces_agree.py` exists to prevent, split across a deploy boundary instead of across files. ## Deploy Image **and** `/plugin` (version minted `2026.09.04.0140` — shipped plugin content moved). No migration. CI green on `dev` @ `30d87e4` (run 5487). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_011cPyzNnegXHr5iRMzzy5KJ
bvandeusen added 1 commit 2026-09-03 22:07:06 -04:00
feat(rules): the instruction surfaces say to RETRIEVE a rule, not only to receive one (#3523)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 32s
CI & Build / Python tests (push) Successful in 1m7s
CI & Build / TypeScript typecheck (push) Successful in 4m18s
CI & Build / Build & push image (push) Successful in 25s
30d87e461a
Every instruction surface told a session to load the always-on rules and
stopped there. None said the loaded set is partial, so an empty one read as
"no rule applies" when it only ever meant "none was pushed" — different
claims, and only one of them has been checked.

That is #2198's asymmetry one level in. The earlier defect was trusting the
SessionStart push over the explicit pull; this is trusting the resident TIER
as if it were the whole rulebook.

It is also why the always-on tier was the only one that worked, on any install
rather than this one (rule 115): a rule nothing retrieves must be resident to
bind at all, and a resident rule costs tokens in every session forever — so a
rulebook that only delivers cannot grow past what one session holds.
Retrieval lifts that ceiling, and it fires only if something asks. A
tool-choice reflex asks least of all (#3476, #161).

The same obligation now lands on all three session-start surfaces, because
rule 119 makes them the specification jointly and a surface stating it
differently IS the product behaving differently (#2497). Pinned by
test_every_session_start_surface_states_the_conditional_retrieval, mirroring
the pull test beside it.

THE BUDGET TRADE. _INSTRUCTIONS sat at 1978 against a 2000 test budget, and
its own comment says an addition there is a trade, never an append. Bought the
new clause by trading out "Processes are saved procedures (follow verbatim)"
and "Deletes are trash-recoverable" — both already in DISPLACED_TOPICS and
already stated on a delivered surface, and both per-tool guidance, which by
this block's doctrine belongs in the tool docstring. Now 1976. Recorded in the
comment above the block so it is not silently reversed.

Plugin version minted: shipped plugin content moved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011cPyzNnegXHr5iRMzzy5KJ
bvandeusen merged commit 67df41ae00 into main 2026-09-03 22:07:11 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/FabledScribe#140