Skip to content

Human approval

Audience: project users. Read this to learn which decisions are yours and what happens if you skip them; the agent handles routine system operations. Command-level detail is collected under For agents and integrators.

Change Loop never decides for you what you wanted. You approve the agreement before anything is built, make a call when a real trade-off appears, say whether the result is the one you wanted when that is required, and give Land authority. The agent and harness record those decisions and carry out everything routine; reviewers and trusted hosts produce their own evidence. Come here when you are asked a question and want to know what it means, or when you want to know what the system will never ask of you.

Where your decisions fall across Change, Build, Prove, Land and after Land, and what never asks you.

Decision When it happens What you say or do If you do not decide
Approve the agreement End of Change, and again after an amendment that removes approved behavior Read the approval package; reply “go ahead” or “approve”, or correct it Build does not start. Silence and urgency never count as approval
Settle a product trade-off Whenever the agreement cannot settle a meaning, a trade-off, or a wider scope Answer the question in plain words The flow waits on that one question; nothing is guessed
Accept the outcome After Prove, only if the change requires human acceptance Say whether the outcome is the one you wanted, with your name Required acceptance stays open and the change waits. An undecided standard change blocks validation
Waive a failed gate A check ran and failed, and you choose not to fix it Give an explicit reason The failure stays a failure and Land refuses it
Decide after exhausted review The allowed review rounds are used and a verdict is still open Choose: a human verdict, one more AI attempt, or pause The change stays paused; exhausted review is never waived
Authorize Land Once the change is proven /land <change>, or “finish it” said up front Nothing is applied to your project. proven is not delivered
Authorize a side effect Commit, push, open a PR, run an external provider, spend beyond budget Say so directly (/deliver, “push it”, “yes”) The action does not run; it is asked, not assumed
Clear what only you can clear A login, the network, or a full disk blocks progress Fix it in your own environment The change keeps its state and resumes when you are done

Everything else stays with the agent or the harness: setup, tool preparation, sandbox repair, sync conflicts, shared-resource waits, and repeated repair.

Your chat reply is the decision. Answering the spec-approval or amendment question with “ลุยเลย”, “ทำเลย”, “ทำไปเลย”, “go ahead”, or “approve” approves it; the agent records it and does not ask again. Saying “ทำจนจบ” or “finish it” up front also authorizes Land for that change. Urgency alone (“ด่วน”, “รีบ demo”) and silence never approve, and a negated request (“don’t push yet”) is never authority.

Commit and push happen only through /deliver or your direct instruction (“commit this”, “push it”). During Build or Prove an uninstructed git commit or git push from the main checkout does not run; it becomes a question, and your yes lets it run. “เปิด PR ให้เลย” or “open a PR” counts as /deliver. The full rule lives in WORKFLOW.md under “Authority from the user’s words”.

Approval package, previews, and role lanes

Section titled “Approval package, previews, and role lanes”

When a change starts, and again when advance asks for spec approval, the agent writes a read-only approval package at .foundation/packages/<change>.html and shows you its path. It summarizes the risk level (Low, Medium, High, or Critical, derived from impact and risk signals), the technical domains touched, and the approval artifacts grouped by approver role (product-owner, tech-lead, qa, devops, security). Each artifact is labeled: proof only when a valid passing receipt backs it, preview, or no evidence yet. The package never changes the change’s state, and if it cannot be written, approval continues from the packet.

The page follows the decision. From top to bottom: the change id with a risk level (a word, a symbol, and a four-step scale, never colour alone) and each reason for it in plain words; the four summary lines, with before and after side by side; a scope strip (files touched, open questions, failure cases; a count the draft cannot give reads unknown, never 0); the decision cards for your kind of work; a checklist of required sections; failure cases as cards (when it happens, what happens, how to recover); the examples, with a prototype first and open; the open questions in full; and a collapsed Reviewer details section (role tables, technical domains, suggested previews). Diagrams sit in the card they explain: the flow chart in card A, a sequence diagram in card D (else F), a state diagram in card F (else E); each is open, can be collapsed, and scrolls sideways when wide. If card A has no prototype it says so; that is a note, never a block. The page has no decision section, button, form, or script beyond the Mermaid loader and records nothing: you decide by replying in the chat. A quiet line under the risk level says when this revision is already approved, or names the approval lanes still missing. Text uses the Thai-capable sans fonts already on your machine and nothing is fetched.

Decision cards. Each kind of work shows one card with the question you are deciding and the fields that answer it. A field the draft does not give reads unknown; nothing is guessed. If a change spans several kinds, each card appears once, hardest-to-undo first (E, G, F, D, A, B, C).

Card Kind of work The question
A feature, ui, client-release, experiment What will users see and do?
B bugfix What is the problem, and how will we know it is fixed?
C refactor, dependency, config, docs, test, chore Is it safe, and what must stay the same?
D api, library, deprecation Who uses this contract, and what happens to them?
E data, migration, data-fix Can data be damaged, and can it be undone?
F async, integration, infra, observability, performance, cicd What happens when it breaks, and what does it cost?
G privacy, ml, security Whose data is used, for how long, and what if it goes wrong?

Under the cards, two lines say how to undo the change and who it affects. They come from the author’s scratch.undo and scratch.who when written, otherwise from fields the draft already has (named beside the answer), otherwise unknown. The checklist shows each required section as present or missing using the compiler’s own rule; since a standard change cannot start without them, a missing section shows up mainly on rapid-lane or older drafts. A section that must answer fixed fields reads missing and names each field not yet answered. If a card or the checklist cannot be built, the page shows a warning for it and the rest still renders.

Three newer kinds of work, and answers that are always possible. A one-off fix to production data (data-fix) shows its scope, snapshot, dry run, whether it is safe to rerun, and how to roll it back. Security hardening with no single bug (security) shows the threat model, the weakness, the control, and how it is verified. A change to a pipeline or build (cicd) shows what changes, the permissions and secrets it uses, its blast radius, and its rollback. Machine learning work must say how the model is evaluated, an experiment must name guardrails and stop rules, and an infrastructure change must say what it costs. Nothing here ever blocks you or the agent: any of these answers can be none: <reason> or unknown: <reason> when the fact does not exist or is not yet known, and the page shows that word and the reason for you to weigh. A High or Critical change must also say how to undo it, or say plainly that it cannot be and why. These rules apply to a draft that is being started or revised; a change already underway is never held up by them. If a file the change touches points at a risk the draft did not cover, change start prints one advisory note and carries on.

What to read first. The summary at the top of the page answers three plain questions: what you get, what changes (before and after, with a count when known), and what happens if it fails. A medium or high change must have this summary (scratch) before it starts; for low it is optional, and the page warns when it is missing. Below that come concrete examples with real values, chosen for the kind of work: a clickable prototype, API requests and responses for each status, rules with numbers, rows before and after a migration, a permission table, and so on. Each example has an After Build tab: once Build and Prove have run it shows the real result (proof only from a valid passing receipt, failed, or a preview), and before that it says what will be compared. The page uses Thai or English to match the agreement. Diagrams are drawn by a copy of Mermaid shipped with the harness on your machine; nothing is fetched over the network, and the page shows the diagram text if that file is missing. Examples are optional: without them you get only the collapsed reviewer details.

Previews are optional. Before Build, the agent may run one declared provider against a throwaway copy of the target to show early behavior. A High or Critical package lists suggested previews. A preview result is never proof: it cannot satisfy Prove or Land, never blocks approval or Build, and shows as stale once the spec changes. A provider marked external: true (for example a payment sandbox or staging) reaches outside your machine, so it runs only after you authorize that specific run; without your decision it is refused and nothing runs.

Role lanes are opt-in. By default one spec approval covers the change. If the project sets approval.roles in foundation.json (see approval), each selected role approves the current revision separately, and Build does not start until every required lane has approved. You decide which role you are approving as; an approval given without a role covers every lane. The harness records the role as stated and does not verify identity. Adding requirements keeps lane approvals; removing a requirement resets every lane.

Acceptance is a named person saying the outcome is the one they wanted. It is the only boundary about the product rather than the work.

A standard change starts undecided, and undecided blocks. change validate fails until somebody decides, which is deliberate: silence is not consent, and a change cannot drift into being accepted because nobody objected.

You decide it explicitly, one way or the other: either nothing subjective needs a person and the deterministic checks are the whole story, or somebody has to look at it and say yes, with a stated reason. The agent records which (commands are under Recording the acceptance decision).

A rapid change starts at not-required instead, because rapid is reserved for low-impact isolated work. Declaring a claim with the acceptance capability also makes acceptance required, and that declaration outranks a not-required decision.

A passing acceptance receipt needs a named human, an explicit accept decision, at least one distinct acceptance criterion, and a recorded observation. It is re-validated on every read against the workspace hash, the claims currently in scope, and the stated reason — so if any of those move afterward, the acceptance goes invalid rather than silently carrying over.

Review asks whether the implementation is sound. The reviewer may be a human or a different AI — what matters is independence, not species.

With workflow.reviewPolicy: "risk-tiered", every change is reviewed and risk controls the bounded route. The exception is a low-tier rapid change that no security keyword, risk signal, or --review flags: the project’s own tests prove it and no AI review runs.

  • low: one full AI review; a material correction promotes to medium
  • medium: one full AI review, one correction batch, then at most one fresh-session delta that closes the original finding IDs
  • high: material risks are decided in the initial Decision Sheet; one full AI review and at most one post-correction delta; no mandatory human final

Authorization/secrets, public or cross-repository contracts, migrations or destructive state, money, concurrency, replay/idempotency, brokers/real wire, and activation of legacy behavior are high-risk signals.

When the allowed AI rounds are used and a verdict is still open, you choose: a human verdict from a named person, exactly one more AI attempt, or pause. Exhausted review is never waived. Who may review (independence and model diversity) is project policy; see Review independence and diversity.

Decisions belong in the change packet, not in a chat transcript. An acceptance reason lives in the contract, a review verdict lives in a receipt, and a continuation decision is named by its --decision-ref. The rule underneath all four boundaries is the same one: approval is never inferred from silence, and a command being available is never approval to run it.

Everything from here down is mechanism: commands the agent runs for you, project policy keys, and host evidence. Users supply the decisions above; nothing here asks you to run a command. Each boundary has a different owner:

Boundary Owner Question it answers
Acceptance User; agent records the decision Is this the outcome we wanted, and is acceptance required?
Review Configured reviewer; project sets assurance policy Does implementation meet the review criteria? Independence is separately configured
Authority bridge Agent/harness integration How does a decision or verdict become a validated receipt?
Host attestation Trusted host operator/integration Does the execution environment meet the unattended sandbox requirements?
Terminal window
# Nothing subjective to sign off — the deterministic checks are the whole story
claude-foundation change resolve <change> --acceptance-not-required
# Somebody has to look at it and say yes
claude-foundation change resolve <change> \
--acceptance-required --acceptance-reason "<why a person must judge this>"

Two properties govern who may review. Both are waivable, and each waiver is declared the same way: a key in the committed foundation.json, never a command flag — an exemption the reviewed party can write at the moment it is caught is not an exemption.

Independence. The shipped policy uses "review": { "independence": "self" }, allowing the reviewer to share an implementer’s identity and session. It applies at every impact and stamps an independence-waived-self-review trigger on the policy. The receipt records what happened: review.policy.independent stays false, with independenceWaived: true beside it explaining why it passed. Projects that require separation of duties can strengthen the value to required; reviewer identity must then differ from every implementation subject and an AI reviewer must use a different session.

Diversity. The shipped policy uses "review": { "diversity": "single-model" }, so diversity is preferred and a Claude-Code-only installation can review in a fresh Claude session without requiring Codex. This stamps a diversity-waived-single-model trigger on the policy. Teams with both providers can strengthen the value to required; the AI reviewer must then come from a different provider and model family than the implementer.

The shipped default selects claude-opus; select codex-sol instead for a Codex-only team. Configured AI review still runs read-only and ephemeral even though the default policy does not require a distinct identity or session.

Each waiver relaxes only its own axis. A same-model self-review of critical work needs both declared; declaring one leaves the other enforced. Withdrawing either key invalidates the receipts it allowed, because the review policy is part of the contract fingerprint.

When review is exhausted, the options map to authority dispatch --reviewer-type human then authority record (human verdict), authority extend-review <change> --decision-ref <user-decision> (exactly one more AI wave per decision reference), or pause.

Users never construct the Land grant or a decision-reference command. land record requires --decision-ref only as compatibility for an already-active legacy commit-oriented transaction. Other advanced continuations—budget continue, change abandon, change waive, and agents release --force—still record the decision that authorized them.

change waive is the recorded exit for a gate that ran and failed: it withdraws one capability’s enforcement on your explicit decision, travels as a user-waived advisory through proof and into the archive, and --revoke restores the requirement. It refuses a waiver that would leave no required provider. Acceptance is refused there; withdraw that requirement with change resolve --acceptance-not-required instead. Review may use the same waiver route, while independence and diversity are declared in foundation.json as above.

For agent and host integrators. Users supply decisions; the integration records and validates them through this mechanism.

The normal entry point is one resumable command:

Terminal window
claude-foundation advance <change> --through proven

The coordinator invokes the compatible proof primitive, creates or reuses the request, and never polls an unchanged external wait. When the packet is actually handed off, configured Codex or Claude Code review uses authority run. A named-human review must use authority dispatch before authority record. Human acceptance uses request/status/record without a review dispatch.

authority request refuses to open unless the implementation tasks are complete and that authority is genuinely required. The request is bound to the workspace hash, expires after 24 hours, and is single-use. Dispatch records the exact full or delta packet and consumes an attempt even if the reviewer crashes; only a completed response can unlock the next route.

authority record validates the response against the request — version, request ID, change ID, type, and workspace hash must all match — and then runs the ordinary receipt validator. If the response claims a pass but the resulting receipt would not be valid, the previous receipt is restored and the operation fails. A completed request cannot be replayed.

If the workspace changes after a request is opened, the request goes stale and must be reopened. A verdict is bound to the code it was given, not to the change in general.

For trusted host operators. This is environment evidence from the host, not a document the project user signs to approve a feature.

This one is not human approval, despite living near it.

sandbox challenge plus doctor --unattended --attestation <file> is a signed statement from a trusted host that the sandbox boundary is safe enough to run without a person watching. It is Ed25519-signed, the nonce expires in ten minutes, and a consumed nonce is recorded so it cannot be replayed.

Trust roots are root-owned system files only, and Change Loop independently refuses unattended execution when it finds a writable container socket, a mounted Kubernetes service-account token, or a mounted SSH agent socket — the things that would let “sandboxed” work reach outside the sandbox.

Detection is not authorization. Finding that unattended execution is possible never implies permission to use it.