feat(fable-5): route the context-budget menu to the operator and seed check I23 - #2031
Conversation
… check I23 Two follow-ups from the Fable 5 prompting-guide alignment audit share one decision, so they land together: whether a continuation trigger may be self-judged from the remaining window at all. It may not. Three signals license a surface to route into a handoff, a fork, or a new session — the user's own report, an instrument that measures the window, and visible decay in the model's own output. A self-estimated budget is none of the three. context-guard now splits its zone-crossing report by audience. The four-option continuation menu renders to the operator on systemMessage, whose whole content is a human's choice; the model's channel carries the zone determination plus the counter-steer that a zone word is a measurement and not a decay signal. An exit menu injected into model context manufactures the model's own initiative to stop — the measurement decides only when to ask, while the model still decides whether to stop — which is the shape check I23 detects. The counter-steer is stated inline rather than delegated to the playbooks doctrine that also carries it, because the two plugins are independently installable. session-flow's handoff and implementation's implement lose their self-estimated-budget triggers on the same rule. Both stay model-invocable; only the budget clause is gone. With the policy settled, I23's pre-scan pattern is seedable and is seeded. It marks budget phrasing alone, never the verb it licenses, and is not anchored to the bare term "context window" — 20 rows across the marketplace's 193 skills. Closes #2009 Closes #2011 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NNmc2T3y81efZTaDZHerWo
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4986665344
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
# Conflicts: # plugins/claude-config/CHANGELOG.md # plugins/claude-config/skills/audit-instructions/SKILL.md # plugins/claude-config/skills/audit-instructions/scripts/instruction-scan.sh # plugins/claude-config/skills/audit-instructions/scripts/instruction-scan.test.sh
|
Claude finished @kyle-sexton's task in 4m 25s —— View job Code Review
SummaryReviewed the diff against I concur with the existing Codex review comment on I posted one additional inline finding building on that same line: in a headless/non-interactive session (batch Minor, non-blocking: the PR description's parenthetical for I23 pattern / Verification note: this review lane's sandbox declined to run shell scripts ( No issues found in the |
|
Claude finished @kyle-sexton's task in 1m 44s —— View job Security Review — Complete
Reviewed the full diff ( No security vulnerabilities found in this PR. Reasoning, so the "no findings" isn't a rubber stamp:
One non-security note for completeness: Codex's review comment on |
|
Claude has reviewed this PR 3 times. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
…rigger The residency clause and the remediation that rests on it turn on one fact from the Skills page — that disable-model-invocation: true also suppresses the description from context. The row's existing Verified/Recheck trailer is scoped to the prompting guide, so that second source carried a verification date and no trigger. It now names the change that would invalidate it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NNmc2T3y81efZTaDZHerWo
|
Claude finished @kyle-sexton's task in 2m 19s —— View job Code Review
SummaryThis lane already reviewed the PR at commit
That's the only genuinely new content in this PR versus the last review — confirmed via The new commit (criteria.md:1368-1375) adds a "Second-source recheck trigger" clause to I23's residency bullet, naming what would invalidate the
I found no defect in this addition — it's small, internally consistent with the row it amends, and consistent with the file-wide recheck-trigger convention. No new inline comments filed. Still open from the prior pass (unaddressed by this commit, since it only touches Not independently verified this pass (sandbox declined non-interactive script execution again): |
|
Claude finished @kyle-sexton's task in 1m 15s —— View job Security Review — Complete
Reviewed the full diff at HEAD No security vulnerabilities found in this PR. Reasoning:
This confirms the same conclusion as the prior security pass on this PR (commit |
…vention its predicate Two independent reviewers landed on the same line from different angles, and the findings turned out to be separate defects rather than one. The model channel said "The operator has been shown the continuation options and owns that choice." A hook cannot know that. systemMessage is documented only as a message shown to the user, and nothing upstream describes its behavior in non-interactive runs, so the claim is unknowable in every mode rather than only headless ones. It now states ownership without delivery: continuation is the operator's call, and nothing is being asked of the model. A regression assertion rejects "has been shown" so the sentence cannot creep back. The routing finding is real against the hook-observability convention's text but not against its reasoning. That convention excludes advisory findings from systemMessage because misrouting AGENT-ACTIONABLE content to the user channel is the harm — and check I23 forbids the model to act on a continuation menu, so the antecedent is false here. The exclusion now names its own predicate, who can act, and admits a carve-out on three conditions together: the payload is a choice whose only legitimate actor is the human, the model channel separately carries the determination the model does need, and the emission is keyed to a state transition. The convention also now forbids any model-channel text from asserting operator presence, fleet-wide. The carve-out is written as a property rather than as a reference to I23, so a consumer without that plugin still has a rule that means something. It creates an exception rather than codifying practice — every other systemMessage site in the fleet is a prerequisite skip or a formatter's content-mutation notice — and the conformance section says so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NNmc2T3y81efZTaDZHerWo
|
Claude finished @kyle-sexton's task in 2m 22s —— View job Code Review
SummaryThis lane already reviewed the PR through commit
A regression test is added ( No new correctness issues found in Not independently verified this pass: sandbox again declined non-interactive script execution ( |
|
Claude finished @kyle-sexton's task in 52s —— View job Security Review — Complete
No security vulnerabilities found in this PR. What's new since the last security pass on this PRThe last security review on this PR covered up through commit
This commit is a direct, substantive response to the observability-channel concern raised in the prior review round (the Codex comment and this lane's own earlier finding on Confirmation of prior analysis (unchanged)
|
Both findings addressed in b79a2ff — and they are two defects, not oneAdjudicated by two independent verifiers with my reasoning withheld. They converged on the shape and split on the remedy's form; I took the narrower one. The Claude finding is real, and worse than reported. The Codex finding is real against the convention's text but not against its reasoning. So the convention gives, by amendment on its own principle:
Two things stated rather than left for a reviewer to find:
The carve-out is phrased as a property rather than as a reference to I23, so a consumer without Ownership checked before editing: One correction to a claim made during adjudication, since it nearly became a constraint in the convention: this hook does not fire at most twice per session. The gate is |
…ontract (#2032) Closes #2010 ## Summary The third follow-up from the Fable 5 prompting-guide alignment audit (#2000). The issue named the real remainder plainly: nothing shipped the autonomous-pipeline reminder as a reusable artifact for a consumer's *own* pipeline — it existed only hand-authored inline in two of this repository's three lane launch prompts, which is a launch surface for these lanes and not something anyone else can use. The issue left one shape to decide first: whether a pointer plus a locally-authored equivalent earns its place, or whether the doctrine surface already suffices. **It earns its place.** `autonomy` is the consumer-facing autonomous-pipeline seam an adopting org installs and binds; `playbooks:fable-5` is a separately installable doctrine plugin with no dependency wiring between them. An org that installs `autonomy` to run a governed pipeline should not have to also install and arm a second plugin to learn that its pipeline must not end a turn on unexecuted intent. This is the same composition reasoning applied to `context-guard` in #2031. ## Fix **New: `plugins/autonomy/reference/autonomous-pipeline-reminder.md`** (`0.12.3` → `0.13.0`). The file states the two stopping failures a pipeline cannot recover from — a turn ending on unexecuted intent, and a turn stopping to ask permission nobody is there to give — notes that both are *stopping* failures rather than *doing* failures (which is why review catches them late: the artifact looks reasonable and only the absent effect gives it away), then gives the paste-ready clause set: - proceed without asking on anything reversible that follows from the original request; - pause only for a destructive or irreversible action, one that leaves the working environment, a real change of scope, or input only the launcher can supply; - ask once and never re-ask what is already settled — offering follow-ups once done is a report, not a request; - read the final paragraph back before ending a turn, and if it describes an action rather than reporting one, do it now with tool calls; - an enumeration of the shapes that are work orders to act on rather than messages to end on; - end the turn only on completion or a genuine block, and say what the block is. The companion checkpoint instruction the source guide asks to be paired with this reminder is folded into the pause clause, so a consumer pastes one block instead of noticing a cross-reference and assembling two. **Locally authored, not reproduced.** Copying the upstream text would have violated this repository's own rule against hand-copying upstream content — which is exactly why the issue was filed rather than fixed in #2000. The wording is this repository's own; the citation, the exact section, and the recheck trigger are recorded in the plugin README. **Two boundaries ship with it**, because an artifact that reads as universally applicable gets applied where it does damage: - **An attended lane deliberately does not carry it.** "Recommend, then wait for my direction" is the opposite posture, and pasting the block into one converts a working human-in-the-loop review into an agent acting on its own recommendations. So the two-of-three split the issue observed is the contract, not an inconsistency — this repository's attended-queue prompt opens with "I am present. Recommend, then wait for my direction before mutating." - **The `lane-stop-gate` hook mechanizes exactly one clause.** It performs no content classification beyond its literal sentinel check, so it cannot tell a blocked-on-user stop from a lazy one; both get the same single nudge. That over-blocking stays benign — a genuinely blocked lane costs one wasted nudge and then stops with the operator alerted — but it is over-blocking, not classification. The scope is now stated in the gate's **own header**, so a reader of the hook does not infer coverage it does not have. **Also changed:** `docs/conventions/loop-lane/README.md` now points at the reference for the clause set rather than leaving it implicit in the launch prompts, keeping only the two boundaries that are lane-topology facts rather than reminder content. ## Verification - `scripts/validate-plugins.sh` — passes. This caught a real contract violation on the first run: `autonomy reference/ contracts must use surface classes, never vendor names` (`scripts/validate-plugin-contracts.mjs:236`). The provenance citation moved to the plugin `README.md`, which is the surface that may name a vendor, and `reference/` points at it. Grepped the new file for every banned token — clean. - `python3 scripts/check-contract-clause-coverage.py` — passes; 4 canonical surfaces, 14 tagged restatements, 10 surfaces that point rather than restate. - `scripts/check-changelog-parity.sh --check-bump origin/main` and `--check-order` — the version bump carries its `## [0.13.0]` entry; 72 changelogs read newest-first. - `shellcheck plugins/autonomy/hooks/lane-stop-gate.sh` — clean. The hook edit is comment-only; no executable line changed. - `markdownlint-cli2` over the four changed/added markdown files — 0 issues. - `node scripts/generate-catalog.mjs` — catalog already in sync (no manifest description change). - **Clause coverage checked against the source, not from recall.** The guide page was fetched this session and its "Rare cases of early stopping" snippet read verbatim; the local wording was then revised to cover two clauses an earlier draft had missed (a plan or list of remaining steps, and an analysis standing in place of acting on it) and to add the scope-change pause condition from the companion checkpoint instruction. ## Related - Refs #2000 — the alignment PR that filed this follow-up. - Refs #2031 — the sibling PR closing #2009 and #2011. No file overlap; kept separate because it turns on a different decision. - <https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5> — fetched this session for the "Rare cases of early stopping" clause set and the "Strong instruction following" checkpoint instruction it pairs with. ### Scope note The issue judged the gate's partial coverage low priority rather than a defect, and this PR does not change that judgement or the gate's behavior. It closes the documentation half — the reusable artifact, and an honest statement of what the mechanism covers — and leaves the gate's classification limits as they are, now stated rather than implicit. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Post-merge note: an independent fresh-context calibration study of the I23 pre-scan question ran in parallel with this PR (neither knew of the other) and corroborates its direction. Highlights worth keeping with the record:
Full study is in the work-stream session record; surfacing here so the next I23 calibration round starts from data, not re-derivation. |
Closes #2009
Closes #2011
Summary
Two follow-ups from the Fable 5 prompting-guide alignment audit (#2000) turned out to share a single
open decision, so they land together rather than answering it twice and risking two different
answers. #2011's option 2 was "move the continuation trigger to the measured mechanism — which is
what
context-guardalready is", and #2009 asked whether that mechanism is itself a finding. Ifcontext-guard's injection stayed an exit menu, #2011's option 2 would have moved triggers into asurface check I23 flags. Net zero. So #2009 is answered first and #2011's policy falls out of it.
The decision: three signals license a surface to route into a handoff, a fork, or a new session
— the user's own report, an instrument that measures the window, and visible decay in the model's
own output. A self-estimated budget is none of the three. The third signal stays the model's to
read, because decay shows up in the output and never in a budget number.
Fix
context-guard— the zone-crossing report splits by audience (0.4.9→0.5.0).The hook injected one block into model context naming the zone and then enumerating four
continuation options — continue,
/clear, handoff-then-/clear,/compact— plus the/session-flow:workflowrouter. The menu now renders onsystemMessage, the operator channel,whose whole content is a human's choice to make.
additionalContextcarries the zone determinationplus the counter-steer: this is a measurement and not a decay signal, so do not volunteer to end the
session, summarize, hand off, or trim work on the strength of the reading. The
dumbzone keeps itsextra clause, restated as the model-independent fact it always was — compaction distance is short,
so write expensive conclusions to a durable note as they stabilize.
systemMessageis a universal hook output field documented as "Warning message shown to the user",and
additionalContextis the field that reaches model context; both are available onPostToolBatchandUserPromptSubmit(https://code.claude.com/docs/en/hooks, fetched this session).
Two details worth calling out:
playbooks:fable-5doctrine that alsocarries it. That closes the cross-plugin composition gap context-guard: the zone-crossing injection hands the model an exit menu, and check I23 now flags it #2009 raised as its second decision: the
two plugins are independently installable with no dependency wiring, so a
context-guard-onlyinstall previously received the menu with nothing in context to interpret it against.
four-option exit menu belonged on the
smart → acceptablecrossing was a real question about thepayload, not the trigger; the model-facing payload no longer carries a menu at any zone, and a
budget rendered to a human is outside I23's subject entirely.
session-flow(0.20.0→0.21.0) andimplementation(0.11.0→0.12.0) lose theirself-estimated-budget triggers.
handoff'sdescriptionlisted "context is heavy", and its body repeated it as "Mid-task, contextheavy (check
/contextoutput or user report)". A description is resident in context by default, sothat trigger was live in every session with the plugin installed.
implement's "Mid-phase handoffis still appropriate when context is heavy" is the same shape. Both stay model-invocable and neither
loses a capability beyond the exact behavior the guide counsels against — only the budget clause is
gone.
handoff's "Fork beats compaction" section keeps its window-position threshold and gains aone-line anchor saying what it always meant: it picks between two continuation mechanisms and never
licenses the continuation itself.
The considered alternative — flipping continuation skills to
disable-model-invocation: true— wasrefused. It also suppresses the description from context entirely
(https://code.claude.com/docs/en/skills, fetched this session), so it forfeits every model-side
invocation the skill has, including the ones a user asks for in the words the description exists to
match, to remove one clause.
claude-config— I23 gains a pre-scan pattern (0.24.0→0.25.0, catalog1.18.0→1.19.0).The row shipped unseeded, waiting on calibration. What it was actually waiting on was the policy
above, not a regex: the blast-radius argument (a continuation skill can barely be model-invocable
without naming a context trigger somewhere) was an argument about a population whose disposition was
unsettled. Under the licensing rule its members are true positives, not noise. Two supporting
clauses ship with the row — residency (
descriptionvs body) is a severity input rather than anadmission test, and remediation moves the trigger rather than withdrawing the skill.
The pattern marks budget phrasing alone and never the stop/summarize/hand-off verb it licenses,
because the trigger and the action routinely sit in different sentences; counter-steer text,
documents about the pattern, and operator-facing budgets therefore match too, on the same advisory
over-production contract the I8 families already carry. It is deliberately not anchored to the bare
term "context window".
Verification
bash plugins/context-guard/hooks/zone-crossing-inject.test.sh— 20/20 pass, including twonew cases asserting the channel split: the model channel carries the counter-steer and none of
/compact,/clear,/session-flow:workflow,/session-flow:handoff; the operator channelcarries the menu.
bash plugins/claude-config/skills/audit-instructions/scripts/instruction-scan.test.sh—56/56 pass, including new cases 13 and 14: six I23 positives, a licensed trigger naming no
budget that must not match, the counter-steer that must match (advisory over-production), and two
negatives proving the pattern is not anchored to bare "context window".
the marketplace's 193
SKILL.mdsurfaces. Four are clear false positives the model lane discards(
claude-ops's "remaining tokens are lane names" is an argument-parsing homograph;testing's Playwright CLI-vs-MCP token budget is an operator cost figure;claude-memoryandplaybooks:borisname the topic in a routing table). That rate is the candidate set the pre-scancontract is for, not a corpus.
scripts/validate-plugins.sh— all plugin manifests and the catalog validate.scripts/check-changelog-parity.sh --check,--check-order, and--check-bump origin/main— allfour version bumps carry matching
## [<version>]entries; 72 changelogs read newest-first.scripts/check-silent-skips.sh,scripts/check-shell-portability.sh origin/main,shellcheckonall four changed shell files — clean.
markdownlint-cli2over the nine changed markdown files — 0 issues.node scripts/generate-catalog.mjsre-run after the manifest description change.Related
decision with these two.
docs/adr/0008-admit-only-present-text-defects-to-the-instruction-audit-catalog.md— I23 and itsseeded pattern both satisfy the anchored-to-present-text rule; the pattern marks a passage a
reader can point at.
fetched this session for the
systemMessage/additionalContextcontract and thedescription/disable-model-invocationresidency semantics respectively.Explicitly unverified
#2009 carried a behavioural claim it marked unverified, and this PR does not upgrade it. No
transcript was produced showing a model volunteering an unprompted stop because of the old
injection in a
context-guard-only install. The fix is made on the shape finding, which ispresent in the text whether or not a model has demonstrably acted on it.