Skip to content

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.

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.

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.

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.

  1. Edit the root foundation.json and keep version at 1.
  2. Run claude-foundation doctor --stage change for general policy validation.
  3. If review settings changed, run claude-foundation doctor --stage prove to check the selected reviewer CLI, authentication, and read-only mode.
  4. Inspect model routing with claude-foundation models.
  5. 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": {
"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
{
"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.

{
"review": {
"independence": "required",
"diversity": "single-model",
"defaultReviewer": "claude-opus"
}
}

Use this when one provider is available but self-review is unacceptable.

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-cli or codex-cli with 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" and ephemeral: 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.

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"
}
}
  • grounding accepts required or optional;
  • reviewCircuit accepts full-delta or compatibility value legacy;
  • reviewPolicy accepts risk-tiered or compatibility value legacy.

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.

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
  • 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 deep to fall back to fast or standard. 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:

Terminal window
claude-foundation doctor --stage change
claude-foundation doctor --stage prove
claude-foundation models