Add `specify` as a third co-equal entry path into the dev cycle: it produces an approved spec from already-settled sources (an exhaustive issue, a long in-context design discussion, or a design brainstorm just ratified) with review but no interview. This is the producing half of a deliberate deciding/producing split — `brainstorm` shrinks to optional discovery, `specify` becomes the sole spec-production gate before `planner`, mirroring the RED->GREEN split that keeps tdd/debug honest. What moved: - brainstorm/SKILL.md: stripped of the hard-gate, the acceptance criterion, write-spec, self-review, grounding-check, user-review, and planner-handoff steps; terminal state is now handing a ratified design narrative to specify. Steps renumbered 1-5 (production steps left). - specify/SKILL.md (new): the production core, with a precondition gate (Step 1.5) that bounces to brainstorm the moment the sources do not resolve a load-bearing decision — the same discipline tdd uses. - The grounding-check agent moved brainstorm/agents/ -> specify/agents/ (no-orphan-agents: it lives under its dispatcher), refs repointed. - boss/SKILL.md: Entry-path reflection is now three-way (tdd / specify / brainstorm). specify dispatches autonomously (bounded, no interview) and pauses at its user-review gate; only a fresh brainstorm cycle stays a pre-dispatch bounce-back. - pipeline.md, README, profile-schema, the profile template, and the migration layout updated so every pipeline rendering agrees; specify is a CORE node (not opt-in, unlike tdd) carrying gates: [planner]. Design alternative rejected: parallel sibling skills sharing a docs/spec-production.md (extract-to-doc). Chosen extract-and-chain instead — the shared surface is ~70%, so a shared doc would either become the skill body or drift; chaining keeps one executed home for the gates. Verification (prose repo, no test suite): the spec's internal- consistency grep suite (no two-path drift, no direct brainstorm->planner edge, specify referenced in every rendering, grounding-check single home under specify, specify structural completeness) all green. Orchestrator inspection additionally fixed two dead step-refs the plan under-scoped (a "(Step 4)" lift-validation pointer and a "Skipping Step 7 self-review" red flag, both pointing at steps brainstorm no longer has) and corrected six pre-existing brainstorm->planner renderings in pipeline.md and tdd that predated this cycle. Known follow-ups (non-blocking): the committed spec writes `skills/specify/` in places (typo; skill dirs are repo-top-level) — to be corrected separately. The grounding-check hard-gate was degenerate for this very cycle (this repo has no profile and no test suite); the skip is documented in the spec and the session.
13 KiB
Profile schema
Location: <project-root>/.claude/dev-cycle-profile.yml
Encoding: YAML. Each top-level key is a section. Keys are lowercase snake_case. Lists are YAML sequences.
paths
| Key | Type | Default | Description |
|---|---|---|---|
spec_dir |
string | docs/specs |
Where the specify skill writes specs. |
plan_dir |
string | docs/plans |
Where the planner skill writes plans. |
glossary |
string | (unset) | Canonical-nomenclature file (optional). If set, it is standing reading for every role — no separate standing_reading.always entry is needed; unset is a documented no-op. See glossary-convention.md. |
design_ledger |
string | docs/design/INDEX.md |
Canonical specification index (optional — projects without a design ledger can omit). |
design_contracts |
string | design/contracts |
Directory of prose-authoritative contracts (optional). |
design_models |
string | design/models |
Directory of onboarding whitepapers (optional). |
code_roots |
list | [src] |
Code directories the architect / quality reviewer walk. |
bench_dir |
string | bench |
Where regression harnesses live (optional). |
public_interface |
list | [README.md, docs] |
Directories and files the fieldtester may read — the project's outward-facing surface (READMEs, design ledger, examples, public API docs). Everything else (especially code_roots and bench_dir) is forbidden to the fieldtester. |
fieldtest_examples |
string | examples/fieldtest |
Where the fieldtester agent writes its fixtures. |
Omitted optional keys signal that the feature is unused in this project; skills that depend on them either short-circuit or skip the corresponding step.
Aspirational-source marker (recommendation)
Files under design_models (or an equivalent RFCs /
proposals directory) commonly carry aspirational code —
constructs written before the surface that would parse them
exists. To let a later brainstorm tell aspirational content from
validated contract, projects are encouraged (not required) to
give each such file a frontmatter marker:
---
status: aspirational
validated-against: <commit-sha | "no validation">
---
status: aspirational says "the code here is a target, not a
verified fact"; validated-against records the last commit at
which someone actually ran the code through the live tool (or
"no validation"). A design ledger (design_ledger) is likewise
encouraged to distinguish "model" rows from "contract" rows so a
reading agent can mechanically tell which carry verified
behaviour.
When a file lacks the marker the signal is simply absent — the brainstorm degrades to treating its content as unmarked, never hard-failing. The marker is consumed by the brainstorm skill (see its Step 1 and Step 4): content lifted from an aspirational source is flagged and must clear the Step-7 parse-every-block gate before it ships in a spec.
naming
| Key | Type | Default | Description |
|---|---|---|---|
counter_dirs |
list | [docs/specs, docs/plans, design/contracts, design/models] |
Directories that use the counter-prefix policy. |
policy |
enum | stable_per_directory_4digit |
One of stable_per_directory_4digit, date_prefix, flat. |
slug_separator |
string | - |
Separator inside the slug. |
stable_per_directory_4digit means each listed directory has a
per-directory counter, 4-digit zero-padded, assigned in
creation order, stable for the life of the file. New files
take the next-higher number; deleted files retire their number.
date_prefix uses YYYY-MM-DD-slug.md.
flat uses slug.md.
commands
| Key | Type | Default | Description |
|---|---|---|---|
build |
string | (required) | Build command — exit 0 means success. |
test |
string | (required) | Test command — exit 0 means success. |
lint |
string | (optional) | Lint command — exit 0 means success. |
doc_build |
string | (optional) | Documentation-build command used by the docwriter skill. Should print warnings on stderr so the agent can enumerate them (e.g. cargo doc --no-deps 2>&1). Omit if the project has no API docs. |
regression |
list | [] |
Regression scripts run by the audit skill. Each entry is a shell command; non-zero exit is a regress. |
architect_sweeps |
list | [] |
Project-specific architect sweep commands run by the architect agent in addition to its universal checks. Each entry is a shell command; non-zero exit means at least one sweep matched and the matches are drift-suspicions to verify. Optional. |
spec_validation
Optional. A registry mapping each markdown fence label to the tool that validates a spec code block of that kind. The brainstorm parse-gate and the grounding-check code-block pass run these parsers so that spec code blocks are treated as hypotheses to verify, not as authoritative truth.
spec_validation:
parsers:
ail:
ext: ".ail"
cmd: "ail parse {file}"
ail-json:
ext: ".ail.json"
cmd: "ail check {file}"
ll:
ext: ".ll"
cmd: "llvm-as {file} -o /dev/null"
The key of each parsers entry is the fence info-string of a spec
code block (the token immediately after the opening ```). Only
blocks whose label has an entry are validated; a block whose label
is absent from the map is skipped and the skip is documented ("no
parser for fence label X") — never a silent pass.
| Key | Type | Description |
|---|---|---|
ext |
string | Extension (including the leading dot) the harness gives the temp file it writes the block into, so tools that key off extension — .ail vs .ail.json — see the right one. |
cmd |
string | Validation command. MUST contain the {file} placeholder, which is substituted with the temp file's path. Exit 0 means a clean parse; any non-zero exit is a parse failure the consuming skill turns into a BLOCK. |
A malformed entry — cmd missing the {file} placeholder, or
either ext or cmd absent — is a profile error the consuming
skill surfaces, not a silent skip; the gate fails closed.
Omitting the whole spec_validation section disables the
block-validation gates: the consuming skills short-circuit, exactly
as with other omitted optional features.
vocabulary
| Key | Type | Default | Description |
|---|---|---|---|
cycle |
string | cycle |
One round in the pipeline graph (NOT the top-level container). Examples: cycle, release, epic. |
subcycle |
string | iteration |
A sub-unit of a cycle. Examples: iteration, sprint, story. |
milestone |
string | milestone |
Tracker container spanning many cycles; closes only when complete AND functional (see pipeline.md § Milestone-close gate). Examples: milestone, epic, release. |
ledger_entry |
string | contract |
What a single design-ledger entry is called. Examples: contract, RFC, ADR. |
Skills use these names in their generated artefacts and prose. Picking accurate vocabulary keeps prose readable; the underlying mechanics are identical regardless of name.
The renamings shown as examples above illustrate the slot only; they
are not nomenclature for any particular project. When a project sets
paths.glossary, that glossary is the source of truth for its
nomenclature and overrides these examples where they collide — a word
offered here may sit under Avoid in a given project's glossary
(see glossary-convention.md).
standing_reading
| Key | Type | Default | Description |
|---|---|---|---|
always |
list | [CLAUDE.md] |
Files every agent reads at start of every dispatch. |
by_role |
map | {} |
Map from role name to list of additional files. |
Role names match agent slugs: architect, bencher, debugger,
implementer, tester, fieldtester, docwriter,
grounding-check, plan-recon, spec-reviewer, quality-reviewer.
Entries may be shell commands as well as file paths — they are
read as opaque strings the agent should fetch / execute, e.g.
"git log -10 --format=full".
A set paths.glossary is implicitly appended to every role's
always list — it does not need its own entry here. The slot's
authoritative semantics live at the paths row above.
git
| Key | Type | Default | Description |
|---|---|---|---|
main_sacrosanct |
bool | true |
If true, no actor may reset or revert main. |
only_orchestrator_commits |
bool | true |
If true, no agent commits; the orchestrator commits. |
issue_tracker.kind |
enum | none |
One of gitea, github, linear, none. |
issue_tracker.close_marker |
string | "closes #N" |
Marker the orchestrator includes in commit bodies to auto-close issues. |
issue_tracker.url |
string | (empty) | Human-browsable URL of the issue list — surfaced in notifications and cross-references. |
issue_tracker.list_cmd |
string | (empty) | Shell command that lists open issues. Used by the boss skill to read the forward queue. Examples: tea issues ls --repo X/Y --state open, gh issue list --repo X/Y --state open. |
protected_branches |
list | [main] |
Branches that are sacrosanct in the same sense as main. |
notifications
| Key | Type | Default | Description |
|---|---|---|---|
command |
string | (empty) | Shell command the boss skill invokes on done-state and bounce-back. Receives the message text as a single argument. Example: "~/.claude/notify.sh". If empty, the orchestrator falls back to printing the notification in chat. |
pipeline
Per-phase configuration. Each phase has its own sub-map.
pipeline:
brainstorm:
gates: [specify] # optional discovery; hands ratified design to specify
optional: true # skipped when the design is settled in the sources
specify:
gates: [planner] # core node — planner cannot start until the spec is approved
planner:
gates: [implement]
implement: {} # standard
audit:
mandatory_at: cycle_close # auto-fires at end of each cycle
fieldtest:
boss_only: true # only orchestrator dispatches
when: surface_touch # condition tag (orchestrator judgement)
milestone_fieldtest:
boss_only: true
when: surface_touch # end-to-end proof of the milestone's promise
gates_close: milestone # its green roll-up is the functional leg of the milestone-close gate
docwriter:
boss_only: true
when: api_stable_across_n_cycles
debug:
trigger: bug # observable misbehaviour
red_first: true # RED test before any fix
# specify above is a CORE node (always present); tdd below is opt-in.
tdd: # opt-in: omit the key to disable the entry path
trigger: test_specifiable_feature # behaviour expressible as one failing test
red_first: true # RED executable-spec before any implementation
alt_to: brainstorm # alternative design entry; bounces back on a design fork
boss:
user_invoked: true # autonomous-orchestrator mode, /boss
Phases not listed are disabled for the project. A project that
does not want a fieldtest phase simply omits the key. tdd is
opt-in the same way. specify, by contrast, is a core node — it
is the spec-production gate before planner on every design path,
reachable directly from settled sources or via the optional
brainstorm discovery stage. tdd opt-in only adds the
test-specifiable bypass; with tdd omitted, the design entry paths
are brainstorm → specify → planner and specify → planner.
Example: minimal profile
paths:
spec_dir: docs/specs
plan_dir: docs/plans
code_roots: [src]
commands:
build: cargo build
test: cargo test
vocabulary:
cycle: cycle
subcycle: iteration
standing_reading:
always:
- CLAUDE.md
- "git log -10 --format=full"
git:
issue_tracker:
kind: github
close_marker: "closes #N"
pipeline:
brainstorm: { gates: [specify], optional: true }
specify: { gates: [planner] }
planner: { gates: [implement] }
implement: {}
audit: { mandatory_at: cycle_close }
debug: { trigger: bug, red_first: true }
This minimal profile enables five phases, no fieldtest, no docwriter, no design-ledger. Good starting point for a small project.