Configure foundation.json
Audience: project maintainers and authorized agents configuring an installation. For the everyday workflow, start with Quickstart.
foundation.json is the committed policy for one project. It tells
Change Loop how much autonomous work is allowed, how work maps to model tiers,
when to escalate, who may review, and how a new Build workspace is prepared.
Most projects never change it; this page helps when you want a specific
behavior to be different.
Common goals and the setting to change
Section titled “Common goals and the setting to change”| I want to… | Set in foundation.json |
Notes |
|---|---|---|
| Use a different or cheaper model for some work | models.routing: true, then models.fast/standard/deep .family |
Routing is off by default: every task uses the standard tier. See models |
| Require a reviewer other than the implementer | review.independence: "required" |
Reviewer identity and AI session must differ |
| Require a different AI provider to review | review.diversity: "required" and review.defaultReviewer: "codex-sol" (or claude-opus if Codex implements) |
Fails closed if the reviewer matches the implementer. See review |
| Run a project setup command in every new workspace | sandbox.setupCommand (and sandbox.setupTimeoutMs) |
Dependencies are installed from the lockfile automatically; set sandbox.installDependencies: false to opt out |
| Cap spend on one autonomous run | execution.tokenBudgets.rapid/standard, execution.requestBudgets.rapid/standard |
Ceilings, not targets. Set execution.budgetWatchdog: true for spend warnings and limits in packets |
| Run fewer agents or checks at once | execution.maxParallelAgents, maxParallelProviders, maxParallelSetups |
Integers 1 to 16 |
| Allow slow builds more time | execution.leaseMinutes |
1 to 1440 minutes |
| Require named roles to approve a spec | approval.roles |
For example ["tech-lead", "qa"]. See approval |
| Require coverage and mutation evidence on risky changes | quality.changeGate: "warn" or "enforce-high-risk" |
Needs the quality configuration |
Name the commit and branch for /deliver |
deliver.commitSubject, deliver.branchPattern, deliver.ticketPattern |
Only used by the optional Deliver step |
After any edit, run the checks in Safe editing loop.
Full reference
Section titled “Full reference”The rest of this page documents every supported field. foundation.json does not contain product requirements or live task state:
| Concern | Source of truth |
|---|---|
| What the product should do | openspec/ |
| What implementation remains | tasks.md in the active change |
| Runtime state and receipts | .foundation/ |
| How Change Loop may execute | foundation.json |
The installer copies this file only when it is missing. After that, the file is yours: upgrades do not overwrite it. Commit it so that every developer and reviewer runs under the same visible policy.
Shipped profile
Section titled “Shipped profile”The current profile is optimized for a Claude-Code-only installation. It uses Claude Opus for configured review and permits the same identity/model family:
{ "review": { "independence": "self", "diversity": "single-model", "defaultReviewer": "claude-opus" }, "workflow": { "grounding": "optional", "reviewCircuit": "full-delta", "reviewPolicy": "risk-tiered" }}The complete committed file also contains execution budgets, model tiers, escalation triggers, and both shipped reviewer definitions. Edit the existing object rather than replacing it with the abbreviated example above.
self and single-model are explicit waivers, not claims that a review was
independent or diverse. Review receipts record
independence-waived-self-review and diversity-waived-single-model so the
trade-off remains visible.
Safe editing loop
Section titled “Safe editing loop”- Edit the root
foundation.jsonand keepversionat1. - Run
claude-foundation doctor --stage changefor general policy validation. - If review settings changed, run
claude-foundation doctor --stage proveto check the selected reviewer CLI, authentication, and read-only mode. - Inspect model routing with
claude-foundation models. - Commit the policy change before producing evidence under it.
A policy change can invalidate review or proof created under the old contract. Re-run readiness and Prove rather than editing receipts.
execution: bound the autonomous run
Section titled “execution: bound the autonomous run”{ "execution": { "maxParallelAgents": 3, "maxParallelProviders": 4, "maxParallelSetups": 3, "packetBytes": { "task": 20480, "review": 20480, "repository": 24576, "global": 32768 }, "tokenBudgets": { "rapid": 800000, "standard": 1600000 }, "requestBudgets": { "rapid": 100, "standard": 200 }, "maxContinuationWindows": 3, "planSummaryBytes": 4096, "leaseMinutes": 45 }}| Field | Valid value | What to change it for |
|---|---|---|
maxParallelAgents |
Integer 1..16 |
Lower it for constrained machines or tightly coupled work; raise it only when tasks can be separated safely |
maxParallelProviders |
Integer 1..16 |
Bound independent evidence providers and required service startups |
maxParallelSetups |
Integer 1..16 |
Bound independent repository setup commands during Build preparation |
packetBytes.* |
Integer 2048..65536 bytes |
Increase only when a bounded task, review, repository description, or whole packet is being truncated. Upgrades replace the exact former defaults (8192/8192/12288/16384) with the current ones and keep tuned values |
tokenBudgets.rapid/standard |
Integer 10000..100000000 |
Cap model tokens for one autonomous run; this is a ceiling, not a target |
requestBudgets.rapid/standard |
Integer 10..100000 |
Cap model requests for one autonomous run |
maxContinuationWindows |
Integer 1..20 |
Bound separately approved continuation windows without forcing unfinished in-scope work into another Change |
planSummaryBytes |
Integer 1024..16384 |
Bound the compact plan handed between phases |
leaseMinutes |
Number 1..1440 |
Allow longer workspaces for slow builds or shorten stale-worker recovery |
At 85% of a budget, Change Loop enters completion-only mode. The first time a
change reaches 100%, the harness opens one more same-size window by itself and
records it; this does not count toward maxContinuationWindows. At the next
100%, an operator can approve another audited window while unresolved in-scope
model work remains, up to maxContinuationWindows. Deterministic readiness, receipt
reuse, recovery, and archive operations remain available without an extension.
quality: stage changed-code and mutation gates
Section titled “quality: stage changed-code and mutation gates”quality.changeGate accepts off, warn, or enforce-high-risk. Warning mode
reports missing changed-quality (coverage, complexity, and CRAP) and mutation
providers for high-risk work. Enforce mode requires both capabilities on
high-impact or security-sensitive Changes; a project can use any command
adapter that emits trustworthy evidence for its language.
This field selects when a Change requires quality evidence. The separate
committed file quality/foundation-quality.json defines how each repository
produces and evaluates it: language profiles, commands, built-in normalizers,
thresholds, baselines, and exceptions. Bootstrap that file with quality init,
not by adding provider commands to foundation.json. See
Consumer quality gates.
models: route purpose, not a host-specific command
Section titled “models: route purpose, not a host-specific command”{ "models": { "fast": { "family": "haiku", "fallbackTier": "standard", "purposes": ["inventory", "logs", "mechanical-docs"] }, "standard": { "family": "sonnet", "fallbackTier": "deep", "purposes": ["implementation", "tests", "focused-investigation"] }, "deep": { "family": "opus", "fallbackTier": null, "purposes": ["architecture", "security", "migration", "independent-review"] } }}models.routing is a boolean and defaults to false: until you set it to
true, every task uses the standard tier unless the task itself requests a
tier, and the tier table below has no effect on planning.
The three keys—fast, standard, and deep—are portable tiers. family
describes the preferred family, while the native agent host remains responsible
for actually running it. fallbackTier must name one of the three tiers or be
null. deep cannot fall back to a lower tier.
Keep purpose lists narrow. A high-risk change is escalated by its boundary even
if its diff is small; adding every purpose to fast does not make security or
migration work low risk.
escalation: conditions that need deeper judgment
Section titled “escalation: conditions that need deeper judgment”The shipped triggers are:
ambiguous-contract— the requested behavior or exclusion is unresolved;auth-or-sensitive-data— authorization, secrets, or sensitive data are involved;migration— persistent state or compatibility must move safely;concurrency— ordering, races, retries, or idempotency matter;public-compatibility— a public interface or supported behavior may change;cross-repository-conflict— repository scopes or versions disagree;evidence-anomaly— evidence is missing, contradictory, or unexpectedly stale;two-failed-attempts— the current approach has failed twice.
Escalation selects deeper investigation or review. It does not silently expand write authority, bypass a budget, or turn external credentials into agent permissions.
review: choose convenience or separation of duties
Section titled “review: choose convenience or separation of duties”Two independent axes control review:
| Field | Relaxed | Strict |
|---|---|---|
independence |
self: same identity/session may review |
required: reviewer identity and AI session must differ |
diversity |
single-model: another provider/family is preferred |
required: AI reviewer must use another provider and model family |
Default: one Claude installation
Section titled “Default: one Claude installation”{ "review": { "independence": "self", "diversity": "single-model", "defaultReviewer": "claude-opus" }}This is the lowest-friction profile. Configured authority run review is still
read-only and ephemeral, but policy does not require a distinct identity or
model family.
Same model, separate reviewer session
Section titled “Same model, separate reviewer session”{ "review": { "independence": "required", "diversity": "single-model", "defaultReviewer": "claude-opus" }}Use this when one provider is available but self-review is unacceptable.
Cross-provider review
Section titled “Cross-provider review”For implementation by Claude:
{ "review": { "independence": "required", "diversity": "required", "defaultReviewer": "codex-sol" }}For implementation by Codex, select claude-opus instead. With diversity
required, the default reviewer must actually differ from the implementation
provenance or the receipt fails closed.
Reviewer definitions live under review.reviewers. A configured reviewer must:
- use adapter
claude-cliorcodex-cliwith the matching provider family; - name an installed executable and model ID;
- use
reasoningEffort: "high"(the low-risk fast tier runs at medium); - use
sandbox: "read-only"andephemeral: true.
Do not put credentials, tokens, or login commands in foundation.json. Install
and authenticate the selected CLI through its normal user-level setup, then use
doctor --stage prove to verify readiness.
approval: role approval lanes
Section titled “approval: role approval lanes”Optional. Require separate spec approval from named roles:
{ "approval": { "roles": ["tech-lead", "qa"] }}roles accepts unique values from product-owner, tech-lead, qa,
devops, and security. The default is empty: one spec approval, unchanged.
When set, a change requires the configured roles that its router selects for
that change. Each role approves with
claude-foundation advance <change> --approve-spec --role <role> --decision-ref <ref>
(or change resolve … --approve-spec --role <role>). Until every required lane
has approved the current revision and packet, advance stops with ASK_USER
naming the missing roles, and no sandbox is created. An approval without
--role covers every lane required at that moment, and a later --role
approval adds its lane without revoking it. The harness records the role as
stated and does not verify identity. An additive revision keeps lane
approvals, but if it makes the router select a new role, that role must
approve before Build; a revision that removes a requirement resets every lane.
An unknown role, --role without approval.roles, an approval value that
is not an object, or roles that is not an array is refused.
sandbox: prepare every new Build workspace
Section titled “sandbox: prepare every new Build workspace”A Git worktree contains tracked files but not node_modules. Without a setup
command the harness installs dependencies itself from the workspace lockfile
(npm ci, or the pnpm, yarn, or bun frozen-lockfile install); set
"installDependencies": false to opt out. If setup needs anything else, add a
deterministic setup command:
{ "sandbox": { "setupCommand": "npm ci", "setupTimeoutMs": 600000 }}setupCommand must be a non-empty string. setupTimeoutMs must be an integer
from 1000 to 3600000; installDependencies must be boolean. The command
runs once in every new workspace; a failure keeps the workspace, is retried by
the harness, and is then handed to the agent with its command, directory, and
log instead of continuing with a half-prepared sandbox.
For a multi-repository project, keep the root setup here and place repository-
specific setup commands in openspec/repositories.yaml. Repository topology,
change scope, provider scope, and landing order are separate contracts; configure
them in that order in the multi-repository workflow.
workflow: keep the modern control circuit enabled
Section titled “workflow: keep the modern control circuit enabled”{ "workflow": { "grounding": "optional", "reviewCircuit": "full-delta", "reviewPolicy": "risk-tiered" }}groundingacceptsrequiredoroptional;reviewCircuitacceptsfull-deltaor compatibility valuelegacy;reviewPolicyacceptsrisk-tieredor compatibility valuelegacy.
Use the shipped values for new work. The legacy values exist to read older
projects; they are not the recommended way to weaken review.
optional means the semantic compiler creates grounding.yaml only when a
material non-derived decision exists. Set required when project policy truly
requires a decision ledger for every change; it does not make empty grounding
content useful.
deliver: name the optional pull-request commit and branch
Section titled “deliver: name the optional pull-request commit and branch”Used only by /deliver. Defaults keep feat: <title> (or fix: <title>) and
change/<change-id>:
{ "deliver": { "commitSubject": "{commitType}({ticket}): {title}", "branchPattern": "feature/{ticket}-{title}", "ticketPattern": "[A-Z]+-\\d+" }}Placeholders are {changeId}, {title}, {commitType}, {prType}, and
{ticket}, the first ticketPattern match in the change id, title, or
proposal. An unknown placeholder, an invalid pattern, a missing ticket, or an
invalid subject or branch stops Deliver as a delivery-policy wait before
anything is committed; correct the setting and run /deliver again.
WORKFLOW.md (/deliver <change>) owns the full naming rules.
Other fields
Section titled “Other fields”| Field | Default | Meaning |
|---|---|---|
execution.budgetWatchdog |
false |
Boolean. When false, usage is still recorded but packets carry no spend directives or limits; when true, a budget-warning signal appears at 70% of spend |
review.fallbackReviewers |
["codex-sol", "main-session"] in the shipped file |
Reviewers tried in order only after an infrastructure error; a delivered fail or inconclusive never triggers fallback. Names must exist, must not repeat defaultReviewer, and main-session requires independence: "self" |
review.infraFailureThreshold |
2 in the shipped file |
Integer 1..5 |
telemetry.requireUsage |
true in the shipped file |
Boolean; Land requires a measured usage dimension |
land.riskBasedCi |
false |
Boolean; see the signed CI contract in EVIDENCE.md |
workflow.handoffDefaultOwner |
"devops-team" |
Non-empty team name for permission-bound handoffs |
Common mistakes
Section titled “Common mistakes”- Replacing the whole file with a partial example. Edit the existing object so reviewer definitions and other policy sections remain present.
- Treating budgets as quotas. A small change should finish far below them.
- Requiring diversity while selecting the implementer’s model family. The review receipt will correctly fail.
- Setting
deepto fall back tofastorstandard. Downgrading deep work is rejected. - Adding secrets to setup or reviewer fields. Keep secrets out of committed policy and use normal CLI authentication.
- Expecting upgrades to change project policy. The installer preserves this file after first creation; update it intentionally and review the diff.
After any edit, the shortest reliable check is:
claude-foundation doctor --stage changeclaude-foundation doctor --stage proveclaude-foundation models