Scopes
A scope is the dial that decides which of the framework's 33 stages run for a given kind of work, and which sit out. A bugfix doesn't need market research or environment provisioning, but it still runs the deployment pipeline and execution stages; a regulated enterprise feature needs the full lifecycle. Rather than asking the user to hand-pick stages every time, AI-DLC ships eleven named scopes — each one a curated EXECUTE/SKIP verdict over the full stage set, paired with workflow defaults such as depth, test strategy, and an optional review ceiling. Pick the scope and the rest cascades.
For a harness engineer, a scope is pure data, authored the same way every other primitive is — as a file. It is two halves: one core/scopes/aidlc-<name>.md file (its identity, routing metadata, and workflow defaults) plus a per-stage membership tag (each stage's frontmatter scopes: list naming the scopes it runs under). Adding or tuning a scope requires no TypeScript. This chapter walks the workflow: what a scope is made of, how to add a team scope, how to tune an existing one, and what the tooling checks for you versus what it leaves to you.
For the full eleven-scope catalog with use cases and the routing table users read, see Scopes, Depth, and Test Strategy in the User Guide. This chapter is the authoring side of that same data.
What a scope is made of
A scope is authored in two places, and the split is the whole idea: the scope's identity lives in its own file, and its membership (which stages run under it) lives transposed onto the stages.
1. The scope file — core/scopes/aidlc-<name>.md. One file per scope, mirroring core/sensors/. The feature scope's frontmatter looks like this:
---
name: feature
depth: Standard
keywords: []
description: Full lifecycle for new features, practical depth
skeleton: on
runner: true
guard_policy: off
sensors: on
learnings: on
summary_confirmation: on
plan_approval: on
collaborators: off
---
# feature scope
The full-lifecycle scope for new feature work at practical depth. ...
The scope frontmatter fields are:
| Field | Required | What it does |
|---|---|---|
name |
Yes | The scope name. Core files use aidlc-<name>.md; plugin scope files use a stem equal to name. |
depth |
Yes | The default detail level — Minimal, Standard, or Comprehensive. |
testStrategy |
No | Overrides test volume independent of depth. Defaults to matching depth. |
review_cap |
No | Maximum review class under this scope: adversarial, advisory, or none. Absence means no scope-level lowering. A cap can lower but never raise a stage's review_class; a per-work --review level replaces the cap for that piece of work; autonomous swarm reviews retain the stage's declared class. |
keywords |
No | Hint words the agent reads when it proposes a plan for /aidlc <freeform text> (no tool matches them). Flat string lists may use block (- item) or flow ([item, item]) form; an empty list opts out. |
description |
No | The one-liner rendered in /aidlc --help. (The compiled scope table in tables.md, beside the orchestrator skill, shows only Scope / Depth / TestStrategy / EXECUTE / Total, leaving the description out.) |
skeleton |
No | on opts the scope into the walking-skeleton ceremony when practices are scope-dependent; off or absence opts out. |
existing_code |
No | true marks a scope that changes code that already exists, so a new project's custom plan runs on another scope when one fits; false or absence means the scope suits new work too. Any other value is rejected. |
runner |
No | true includes the scope in the default generated scope-runner set. |
freeform_default |
No | true nominates this scope as the selection-aware fallback when the preferred core default (classic) is not enabled. |
include_stages |
No | Plugin scopes only: the stages of the one base plugin the plugin builds on that this scope runs, as a block or flow list ([acme-1-intent-capture, acme-3-code-generation]). Compile puts each one in this scope's column; the stage and every other scope stay as they are. The plugin's own stages join through their scopes: list and a core stage through a contribution's adds.scopes, so validate refuses either here. See Authoring a Plugin. |
guard_policy |
No | The scope's Guard Policy default, strict, relaxed, or off: how far the guards stand aside for work on this scope. It decides what happens when an input changes after a human approved or confirmed something (strict reopens the approval; relaxed and off record the change once, tell the human in one line, and continue; workspace source that moved after a plan was approved is recorded and continued under every value) and which authority fences hold (strict lowers none; relaxed lowers plan-approval and review-freeze; off lowers those two plus state-transition and reviewer-scope; human-presence is never lowered by the word). Absence means off, so a plugin or composed scope that wants strict declares it. The shipped defaults are strict on enterprise and off on the rest. A memory layer's ## Guard Policy section (Mode: strict) wins over every scope default and every per-intent flip, and its Mode: relaxed or Mode: off replaces a scope default; see Guard Policy. change_control is the retired spelling, read for one release; a file naming both keys with different values is rejected. |
sensors |
No | on or off; controls sensor execution and sensor gate checks. Absence means on. Per-intent override: /aidlc --sensors on\|off; global kill switch: AIDLC_DISABLE_SENSORS=1. |
learnings |
No | on or off; controls the stage learnings read/write ritual. Absence means on. Per-intent override: /aidlc --learnings on\|off; global kill switch: AIDLC_DISABLE_LEARNINGS=1. |
summary_confirmation |
No | on or off; controls the separate pre-output summary confirmation, not stage approval. Absence means on. Per-intent override: /aidlc --summary-confirmation on\|off; global kill switch: AIDLC_DISABLE_SUMMARY_CONFIRMATION=1. This scope scalar is distinct from a stage's required / if-present declaration. |
plan_approval |
No | on or off; whether the person is asked to approve each code plan before Code Generation builds it. off builds the plan as written after one line naming it and records PLAN_APPROVAL_SKIPPED; the line asks the person whether they want to look at the plan first. Absence means on. The shipped defaults are off on express and poc and on elsewhere. Per-intent override: /aidlc --plan-approval on\|off, where only the person turns it off; global kill switch: AIDLC_DISABLE_PLAN_APPROVAL_GUARD=1. A memory ## Guard Policy section holding Mode: strict keeps it on over this key, and the kill switch wins over that lock; see Plan approval. |
collaborators |
No | on or off; whether a stage runs with its support agents (collaborators) or lead-only. off makes the engine hand every stage an empty effective support_agents, so on every topology the lead runs alone — no mutually-blind subagent spokes, no mob round, and a pipeline's lead becomes its sole and final link (it authors the artifacts the chain would otherwise split). The stage's authored support_agents list is untouched, so flipping back on re-enables the full ensemble. The reviewer mechanism is independent and unaffected. Absence means on. The shipped defaults are on on enterprise and off on the other ten, so a first run is lean and a team re-enables collaborators deliberately. Per-intent override: /aidlc --collaborators on\|off; global kill switch: AIDLC_DISABLE_COLLABORATORS=1. |
The loader rejects duplicate scope name values across files and names both
files in the error. Invalid ceremony values are rejected with the file, key,
and the two allowed values. Resolution is kill switch (1) → valid intent
line → scope default → on. Every shipped scope declares all five ceremony keys
explicitly rather than leaning on the default: classic declares sensors,
learnings, and plan approval on and summary confirmation off, bugfix declares
sensors and plan approval on and learnings and summary confirmation off,
express declares all four of those off, poc declares plan approval off and the
other three on, and the other seven declare those four on; collaborators is
on only on enterprise and off on every other scope. Classic's gated flow also
caps reviews to one advisory pass and disables walking-skeleton ceremony, while
explicit autonomy keeps the single pre-merge review.
Express turns sensors, learnings, and summary confirmation off; override them
per intent with /aidlc --sensors on|off,
/aidlc --learnings on|off,
or /aidlc --summary-confirmation on|off.
Freeform default
freeform_default: true lets an install nominate the scope used when the
internal classic default is unavailable after plugin
selection. The nomination is checked before the sole-enabled-plugin fallback,
so a plugin with several scopes can choose its lean default instead of accepting
the alphabetically first scope.
At most one enabled scope may declare freeform_default: true. Graph
compilation fails and names every claimant when the selected core/plugin set
contains more than one. Claims on disabled plugins do not conflict until those
plugins are enabled together. The field does not repair explicit typos:
an unknown AWS_AIDLC_DEFAULT_SCOPE value still fails validation.
Walking-skeleton default
The optional skeleton: field controls the scope-dependent walking-skeleton
stance. skeleton: on means that when the team's ## Walking Skeleton
practices resolve to scope-dependent, Construction opens with the
walking-skeleton ceremony for this scope. skeleton: off means the first Bolt
runs as a regular Bolt. Absence defaults to off, so composed/runtime-approved
scopes and plugin scopes do not conjure a skeleton Bolt unless they opt in
explicitly.
Scopes for existing code
The optional existing_code: true field marks a scope that changes code that
already exists (bugfix, refactor, and security-patch ship with it). A
plan the composer tailors for a new project does not run on such a scope when
a scope meant for new work fits, so new work is not recorded as a fix; and
creating work on one in a folder that scans as a new project, which drops its
Reverse Engineering, prints a note that the scope usually targets existing code. Absence means the scope suits new
work too.
Guard Policy default
The optional guard_policy: field is the value a new intent on this scope
starts with, written to its state file at creation as
- **Guard Policy**: <value> (from scope <name>). The human can change it for
that one intent by typing /aidlc --guard-policy <value> or by asking in their
own words; either way the agent runs the setter, and lowering it to relaxed
or off takes a message from the person since the last decision. An older intent without this line remains strict
until explicitly set, while
the next new intent starts from the scope default again. To hold a value for
everyone on the repo, do not edit eleven scope files: declare it once in memory
(## Guard Policy with Mode: strict in aidlc/spaces/<space>/memory/org.md,
team.md, or project.md). A memory strict wins over every scope default and
refuses chat or flag flips by naming the file. A memory relaxed or off
(the narrowest layer that declares one) replaces a value that came from the
scope, while a value the person set for one intent stays; an absent or empty
section changes nothing. The validation error for anything other than the
three values names the file and the allowed values; the per-intent command
repairs an invalid state line.
A scope word is a product statement about how much ceremony this kind of work
deserves. It is not the only control: a human can lower one of the four switchable
fences for one piece of work with /aidlc config set guard.<fence> off, which
writes the Guards Off state line and one GUARD_DISABLED audit row. Setting
on can raise a policy-lowered fence, writing Guards On and GUARD_RESTORED.
Setting the Guard Policy word clears the line that goes against it: off clears Guards On, strict clears Guards Off, and relaxed clears neither.
Human presence is the key holder and has no per-work switch; only
AIDLC_SKIP_HUMAN_PRESENCE_GUARD=1 lowers it. Environment kill switches remain
the machine-wide override. Declare off in a scope only when every piece of work
on it should run with those four fences lowered, as every shipped scope except
enterprise does. To spare people a fence they meet only occasionally, use the per-work switch
instead; the next piece of work starts from its own scope default.
change_control: is the retired spelling of this key. It is read for one release
and never written; a scope file that names both keys with the same value is
accepted, and one that names them with different values is rejected naming the
file and both values.
2. The membership tag — each stage's scopes: frontmatter. A stage names the scopes it runs under in its own frontmatter, in core/aidlc-common/stages/<phase>/<slug>.md:
scopes:
- enterprise
- feature
- mvp
A stage that names a scope is EXECUTE under it; absence is SKIP. Packaging transposes every stage's scopes: list into the compiled EXECUTE/SKIP grid at <harness-dir>/tools/data/scope-grid.json. The grid is an ignored generated projection that the runtime reads; you never hand-edit or commit it. The 3 initialization stages name every scope (they always run).
That transpose is the mechanism for authored scopes, which is what this chapter is about. A scope saved at runtime from a composed plan (scope save) has no stage declaring it, so it cannot be transposed: its durable definition lives in the user's own tree at aidlc/scopes/<name>.md and compile projects it into the harness grid. You do not author those, and they are not part of this workflow; see Where a saved scope is stored. A composed plan the person does not save writes no scope at all: it runs on a stock scope with its own stage changes recorded in that piece of work's state.
The one judgment call worth understanding is the relationship between depth and testStrategy. Depth controls how much detail each stage's artifacts carry; test strategy controls how many tests get generated. They're independent on purpose. Most shipped scopes leave testStrategy off so it inherits from depth — classic is Standard/Standard and express is Minimal/Minimal. workshop demonstrates the explicit split with Standard depth and Minimal testing. If your scope wants a split, declare both. For what each level means, see The 3 Depth Levels and The 3 Test Strategy Levels in the User Guide.
The exhaustive field-by-field contract lives in Contributing: Adding a Scope in the Developer Reference. keywords are only hints the agent reads when it proposes a plan; no tool matches them against the request. This chapter summarizes the decisions; that section is the normative spec.
How scopes relate to stages
A scope and a stage point at each other from opposite ends, and it helps to hold both directions in view.
A stage declares its own identity — its phase, its lead agent, the artifacts it consumes and produces, and now the scopes it runs under (its scopes: list). A scope declares its identity, routing metadata, and workflow defaults in its own .md file, with no per-stage membership inside it; membership lives on the stages. The binding between them is the scope name. When you add a new stage (see Adding a Stage), you put the scope membership on that stage — its scopes: list names every scope that should run it. A stage that names no scope is SKIP everywhere. The transpose at compile turns those per-stage lists into the grid, so membership is authored once, on the stage, rather than re-declared in eleven separate scope blocks.
The one exception is a plugin scope's include_stages, which names stages of the base plugin it builds on: files that plugin cannot edit.
That separation is the same data-versus-code line the rest of this guide rests on (see Harness Engineer Guide). The scope file is data about identity; the stage's scopes: list is data about membership; the compiled grid is the transpose of the two.
Adding a team scope
Suppose your team wants a hotfix scope — leaner than bugfix, for the urgent production patch where you want a regression test and a deploy, nothing else. The change is a new scope file, a scopes: tag on each stage that should run, and regenerated local projections. Mirror the discipline below; the verification steps and the full command lines are in Contributing § Adding a Scope.
Steps
-
Drop
core/scopes/aidlc-hotfix.md. Copyaidlc-bugfix.md(the closest existing scope) and edit the frontmatter: setname: hotfix, pickdepth, addkeywordsas hints the agent reads when proposing a plan for freeform text ([hotfix, urgent]), adescriptionfor the help text,skeleton: on|offfor the scope-dependent Construction ceremony default, keepexisting_code: truefromaidlc-bugfix.md, since a hotfix changes code that already exists,freeform_default: trueonly if this is the selected install's unique fallback nomination,testStrategyonly if it should diverge fromdepth, andreview_caponly if the scope should lower stage reviews. Write a short prose body explaining the intent. Setsensors,learnings, andsummary_confirmationtooffonly for ceremonies the scope should omit; absent keys stay on. Intent overrides and global kill switches use the table above. -
Tag the stages that should run under
hotfix. In each stage you wantEXECUTE(undercore/aidlc-common/stages/<phase>/), addhotfixto its frontmatterscopes:list. A stage you don't tag isSKIPfor the scope. The 3 initialization stages must include it (they always run). -
Regenerate. Run
bun scripts/package.tsto rebuild the ignored harness projections, includingscope-grid.jsonand the compiled scope table. Runbun scripts/package.ts --checkto confirm two independent source-only builds are byte-identical. -
Verify the scope resolves and is accepted. Run
/aidlc --doctor. Then confirm an init under the new scope produces a state file with the rightScope:line, and that it's accepted as an env default and as a mid-workflow--scopechange. -
Check the plan's hints (only if you populated
keywords; the agent reads them in the plan proposal step, no tool matches them). Confirm the plan proposal step for a freeform phrase lists your scope with those hints, so the agent can propose it. -
Update the scope-aware docs and add a routing test. Several docs enumerate scopes by hand — the User Guide's scope reference and routing table, the customization chapter's valid-values list, and the orchestrator reference's scope-to-stage mapping. Update them in the same change. If your scope skips stages in a pattern no existing scope uses, add a workflow test modeled on the existing per-scope tests.
-
(Optional) Generate a typeable runner. A scope is fully usable via
/aidlc --scope <name>the moment its file lands; no runner is needed. If you want a one-word command (/aidlc-hotfix), addrunner: trueto the scope frontmatter and runaidlc engine gen runner-scopes;aidlc engine gen runner-scopes --allemitsskills/aidlc-<scope>/SKILL.mdfor every scope file regardless of that flag. Each runner is a thin shell that drivesaidlc-orchestrate next --scope <name>todonewith the scope baked in, plus a "Starting unrelated new work?" section carrying the same recognize, offer (AskUserQuestion, never auto-create), andnext --new-intent --scope <name>guidance the/aidlcorchestrator has. The runner packages an already-runnable scope, and the scope file is its definition. It carries nohooks:block: the deterministic spine (audit, sensors, rebuild-stage-graph, state validation) is registered project-wide insettings.json, so every runner inherits it for free. Re-run the generator (oraidlc engine gen runner-scopes --check) whenever you add or rename a scope file.
What validates automatically
This implementation derives the valid-scope list from .claude/scopes/*.md presence at runtime through validScopes(), so a lot falls into place the moment the file lands:
- The scope is valid everywhere at once —
init,--scopechange, env-default resolution, anddoctorall consult the same helper, so none of them needs a code edit. - Error messages list your scope in alphabetical order with no change.
- If you gave it
keywords, they appear as hints in the plan proposal step the agent reads for freeform/aidlc <text>as soon as the frontmatter list is populated — no SKILL.md prose edit, just the table regeneration. - Packaging always derives the grid from the current stage YAML, so stale local generated bytes are not release inputs.
What does NOT validate automatically
- A
scopes:tag with a typo'd scope name still parses. A stage frontmatter that nameshotfxinstead ofhotfixcompiles cleanly — it just produces a grid column nobody asks for. The catch is thatvalidScopes()derives from the.mdfiles, so a scope with no file is rejected at invocation; but a mistyped tag on a stage silently drops that stage from the real scope./aidlc --doctorand a per-scope test are the guardrails. - A stale local projection can mislead manual inspection. If you edit a stage's
scopes:and keep using an old ignoreddist/tree, that local runtime still contains the old grid. Regenerate before local runtime checks; CI and release assembly always rebuild from source. - Per-scope phase-sequence coverage. The shipped phase-sequence test iterates a hardcoded list of the known scope names; a new scope isn't exercised by it until you extend that list. Add your scope to it in the same change.
- The hand-maintained docs. The User Guide's stage-by-scope matrix and scope routing table are checked against the compiled grid (
t244-scope-matrix-doc-sync), so a new scope fails that test until its column and row are there. The rest is prose nothing checks, such as the customization chapter's valid-values list and the scope descriptions; keep it in step with the scope files yourself.
Tuning an existing scope
Tuning is a smaller edit, but it lands on the stage, not the scope. Two changes come up often:
- Flip a stage in or out. Add or remove the scope name from a stage's
scopes:list. This is how you'd, say, addmvptoobservability-setup'sscopes:because your team always wires monitoring even for a first cut. One tag, then regenerate withbun scripts/package.tsand run--doctor. - Change a default depth, test strategy, or review ceiling. Adjust
depth, add/removetestStrategy, or add/removereview_capin the scope'score/scopes/aidlc-<name>.mdfrontmatter. The first two recalibrate artifact and test volume;review_caplowers stage review classes toadversarial,advisory, ornonewithout ever raising them. Because each scope carries its own defaults, the change applies to every workflow that selects the scope. Per-run--depth,--test-strategy, and--reviewcan lower the corresponding behavior further. - Change a ceremony default. Set
sensors,learnings,summary_confirmation,plan_approval, orcollaboratorstoonoroffin the scope file. Existing intent lines retain their choice; a scope change refreshes scope-sourced lines but preserves per-intent overrides. Apart fromplan_approval: off, which builds each code plan without asking, andcollaborators: off, which runs every stage lead-only, no ceremony switch removes stage approval, human-turn authority, audit, team write protection, or the reviewer.
Either way, the regenerate-and-doctor pair from step 3 above applies. The edit is small; the verification is the same.
A note on layering: tuning the shipped scopes edits framework-shipped files directly — a stage's scopes: tag or a shipped core/scopes/aidlc-*.md. That's legitimate for a fork that wants different defaults, but be aware you're changing files that carry the aidlc- lineage and a framework upgrade may want to reconcile them. Adding a net-new scope file alongside the shipped eleven is the cleaner path when you want a team-specific behavior without touching the defaults everyone else relies on.
Next
Rules and the Learning Loop — author the standing decisions that travel into every workflow, and let the loop promote a one-time correction into a durable rule.
For the normative scope-shape and runner contract — how a .claude/scopes/ file drives which stages a workflow visits, and how the generator turns it into a typeable /aidlc-<scope> skill — see Skill System §5 (scope shape) and §4 (runners) in the Developer Reference.