Repository navigation
Plan approval is a gate: no worker before the human's typed line (M0.9) - #99
Merged
Merged
Conversation
gate-dispatch now runs `events approval <TASK_ID>` and refuses every execution role of a sprint until the sprint's newest grant holds: the human typed `approve SN <code>` naming exactly the plan as it is now (reviewed), or `autonomous SN <code>` / an approved autonomous mission (autonomy for that sprint, re-plans included). The line must be among the captured prompts and typed after the sprint's last decision (M9.17's mechanism), so a changed plan, a reviewed re-plan, a roll-back, another sprint's line, a negated line and a hand-edited or emitted record all block. plan.approved and human.approval can no longer be emitted by hand. Codex's spawn_agent (agent_type, message) and OpenCode's task now reach gate-dispatch; host sessions started from a tool call are blocked in every aloop project. e2e-live.sh pre-approves with a typed autonomy line. Every dispatching suite approves first (plan fixtures). Test: scripts/test/plan-approval.test.py (13 checks; fails on master at check 1), host suites, conformance 78/78. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
adeelahmad
pushed a commit
that referenced
this pull request
Oct 20, 2026
…M10.1-M10.4 Plan approval as a gate is already M0.9 (#99), so M10 keeps the four containment rows. The project stop reuses the ledgered budget stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QoagJDnsTcVnZvuXwTHTWy
A 4-lens adversarial review, each finding re-verified, found 9 defects: - an approval of one sprint admitted another sprint's or an unplanned STORY_DIR, and tasks the frozen plan lacks: `events approval` now takes the contract's STORY_DIR and role and requires a live story and task of that sprint's ids.json, and RED/SCAFFOLD/GREEN a task id; - a line typed again after a later decision stayed stale forever; - an approved autonomous mission swallowed a non-mission sprint's typed autonomy line; - `transcripts prune` dropped the prompts grants cite (it now keeps every prompt and compacts tool records only); - `codex plugin add` (the documented install) was refused; - a code past column 200 recorded a grant the gate then refused; - a malformed run-log line crashed `events authority`; - intake's own `intent new` made a mission sprint serve no mission intent (the persona now reuses the handed-off intent); - the playbook said a reviewed re-plan never waits for the human. Also covers three test gaps (forged autonomy grants, a replayed approval, one sprint's autonomy over another) and corrects docs that overstated the gate. suppression-contract.test.py no longer writes run data into the checkout. Test: plan-approval.test.py 20 checks (each new one red on the first head); 26/26 mutants of the gate's checks killed; host suite, dsh runtime and conformance 78/78 green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
…l-gate-mbyefz # Conflicts: # CHANGELOG.md # docs/ROADMAP.md # plugin/bin/events # scripts/test/suppression-contract.test.py
mission-doors.test.py (#86) made a sprint live by calling record_authority() with no grant, which emitted plan.approved for any plan. Since M0.9 plan.approved is only the human's typed approval of that sprint's plan, so the test now records it the real way (`events authority --sprint 1`, the human types the line it asks for). ROADMAP: the door gate's live_run should read `events approval` too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
…gate branch Run 49 and run 50 both kept in the evidence ledger. ROADMAP M0.9 records that M10.2's dependency check should also ask `events approval`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
…gate branch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN
adeelahmad
marked this pull request as ready for review
October 20, 2026 13:11
adeelahmad
pushed a commit
that referenced
this pull request
Oct 20, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197nSutKR1QAAqgJhFZ8fPj8000
adeelahmad
pushed a commit
that referenced
this pull request
Oct 20, 2026
…ch; docs for M9.31 Conflicts: the OpenCode plugin's header comment (gate-dispatch on task from master, the door gate last from this branch) and codex-hooks.test.py (both blocks kept). ROADMAP: M9.31 done, new items M9.48, M9.49, M9.54-M9.59, and the M9 row of section 0 brought up to date; TRACKING, CHANGELOG, OVERVIEW. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012rsDo9GYzNx8tXucywZHnA
adeelahmad
pushed a commit
that referenced
this pull request
Oct 20, 2026
…nto the dsh follow-ups Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AiLhAWTRtwbgMCDQNJUbea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Adeel · project thread
Before: "a human approves the plan" was a playbook rule.
events authoritytrusted--initiated-by, and nothing stopped a supervisor from dispatching RED/SCAFFOLD/GREEN before the human said go, after the plan changed, or on work outside the plan.After:
gate-dispatchrefuses every execution role of sprint N (RED, SCAFFOLD, GREEN, structural review, final gate) until the human approved that sprint's plan, as it is now, in a line they typed, and only for that plan's own stories and tasks.events authority --sprint Nexits 3 with the line to relay,approve SN <code>(reviewed) orautonomous SN <code>(autonomy for that sprint, re-plans included). An approved autonomous mission grants autonomy with no line, but only to sprints whose plan serves a mission intent. This works on Claude Code (Task), Codex (spawn_agent), OpenCode (task) and dsh.The code is the first 8 hex of the digest of the sprint's plan files (
stories.md,plan.md,ids.json, and each story'stasks.md,validate.md,plan.md,targets.json). It reuses M9.17's mechanism: the line has to be among the human's captured prompts and typed after the sprint's last decision. So each of these blocks:events emit;How
plugin/bin/_approval.py:grant_forbuilds the grant and asks for the line until the human types it.check8000 is the gate's verdict: the grant holds, then the dispatch is placed in the plan (STORY_DIR is the sprint dir or a live story of itsids.json; anSN-NN-Tkid is a live task of that story; RED/SCAFFOLD/GREEN need a task id).events authority --sprint Nrecords the grant.plan.approvedis now emitted only for a plan grant of that sprint.events approval SPRINT|TASK_ID [--story-dir DIR] [--role ROLE]command: exit 0 if approved, 2 if not.plan.approvedandhuman.approvalcan no longer be created withevents emit.gate-dispatch:agent_type/message;tasktool now runsgate-dispatch.gate-mission-scopeblocksclaude -p,codex execandopencode runfrom a tool call in every aloop project, not only where a mission is set (the prompt log is the approval's evidence).codex plugin …stays allowed.transcripts prunekeeps every human prompt and compacts only tool records, so pruning never takes an approval away.intent check, neverintent new), so the mission's sprint keeps its autonomy.e2e-live.shworks out theautonomous S1 <code>line before the session starts and puts it in the prompt as the human's words.fixtures/plan_fixture.pyandplan-fixture.mjs. The door test (Core agent principles and the one-way / two-way door rule (M9.30, M9.38); hard-lined goals retire (M9.29) #86) now approves with the human's typed line instead of a barerecord_authority.reference.md(the re-plan route), the bin and mission READMEs, and the evidence ledger (run 50).Evidence
scripts/test/plan-approval.test.py: 20 checks.codex pluginblocked, dispatches outside the plan, and intake re-creating a mission's intent._approval.py,gate-dispatch,transcriptsandgate-mission-scope(each patches out one check); the suite killed 26/26, and the unpatched copy passes.make e2e-live YES=1 INTENT=clion 575d95a): 13/13, 2 tasks, 25 supervisor turns, $0.84, 10m17s. The supervisor recorded the autonomy grant citing the human'sautonomous S1 a5e6261aline, andgate-dispatchadmitted every dispatch (S1-01-T1, S1-01-T2, S1-SR-W2, S1-FG) with no dispatch block. Run 48 on master: $0.76, 14m13s.DSH_BIN=… ALOOP_REQUIRE_DSH=1 make test-hosts: exit 0, including the real pinned dsh runtime suite.make conformance: 78/78.make shellcheck,make pycheck, eval-validate, JSON, version check andnode --checkon both host plugins: clean.Open (recorded in the ROADMAP M0.9 row)
python -c) is invisible to the scope gate, as in M9.17.APPROVE_PLANstep counts anyplan.approved. It should askevents approvalinstead.live_run(M9.30) readsplan.approvedor the autonomy env; it should askevents approval.🤖 Generated with Claude Code
https://claude.ai/code/session_01WBVFNrEg85XAnSfHQidCXN