Repository navigation
feat(workflow): require plan presentation before approval on planning 4 - #48
Merged
Merged
Conversation
In real /man runs, agents self-recorded `plan confirm --plan-decision governed_execution` from an earlier generic "go with your recommendations" without ever showing the plan. Add a CLI gate for new tasks (planning policy 4); planning 1-3 tasks keep their confirm semantics and metadata bytes. - `workflow plan <ref> present`: journalled `plan_present` operation bound to (planVersion, plan digest, scope digest, requirementsDigest); prints a plan summary and "Show this plan to the operator and wait for their reply before running plan confirm." Idempotent for an unchanged tuple, owner-only, validates the bound plan file before writing. - `plan confirm` on planning 4 needs a current, unconsumed presentation plus exactly one of `--operator-reply` or `--unattended-waiver`, and records `planApproval.approvalSource`. - Close bypasses: `revise --plan-decision`, solo handoff start, plan_only -> governed_execution resumption, and confirm after reframe all go through the gate. The metadata parser rejects a planning-4 decision without an approval record, covering non-CLI writers. - Project config `unattendedWaiver: allowed|forbidden` (absent: allowed for local single tasks, forbidden for manteam/shared). Waivers and approvals whose scope changed later are flagged in delivery inspect/check, the context index and the progress page. - Reply reuse is checked against human-authored task text only, after normalising case, whitespace and trailing punctuation. The gate cannot prove a reply came from the operator; it guarantees the plan is presented before approval, stale presentations are rejected, and the approval basis is auditable. Docs say so explicitly. New man/manteam tasks use planning 4; older CLIs fail closed on them with MANCODE_POLICY_VERSION_UNSUPPORTED, so teams must upgrade together.
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.
Stacked on #46. The base will be retargeted to
mainonce #46 merges.Why
In a real
/mantest onunjs/ufo#297, agents on both the baseline and the slimmed guidance self-recordedplan confirm --plan-decision governed_execution. They never showed the plan to the operator. The basis they cited was an earlier generic "Go with your recommendations", given in reply to requirement questions. Prompt text alone does not stop a strong model from reading broad authorization as plan approval.What
This applies to new tasks only, which use
policyVersions.planning = 4. Planning 1–3 tasks keep today's confirm behaviour, and their metadata round-trips byte-identically.workflow plan <ref> presentplan_presentoperation, bound to(planVersion, plan digest, scope digest, requirementsDigest).plan confirmon planning 4--operator-replyor--unattended-waiver.planApproval.approvalSource.revise --plan-decision.plan_only→governed_executionresumption.unattendedWaiver: allowed | forbiddenin.mancode/shared/config.json.PLAN_APPROVAL_SCOPE_CHANGED).What it does not do
The CLI cannot prove a reply came from the operator. A model can still run
presentand thenconfirmwith an invented reply. What the gate guarantees:The docs state this. Terminal approval was considered and declined because of operator friction.
Compatibility
MANCODE_POLICY_VERSION_UNSUPPORTED), so teams must upgrade together.manentry grows by 135 tokens. The guidance budget fixture is updated.Review
Implemented by a Sonnet subagent and reviewed adversarially by an independent Opus subagent. There were no blocking findings. All 7 should-fix items and the minor items are addressed, each with a regression test.
tests/plan-gate-contracts.test.tshas 30 tests.Test plan
tsc --noEmitandbiome checkpass.npm run check: 1788 passed.tests/secrets.test.ts"handles output without retries", is the pre-existing macOS-onlyEPERMbug insrc/secrets/run.ts. It is fixed separately, and CI skips it on ubuntu.