Stage 2: Spec
Goal: create spec.md from intent.md so engineering work has a clear
contract. The agent writes the spec, and the human reviews it. Automate checks
where possible. Keep human attention on gate decisions.
Heartbeat: on entry and at every sub-task change, overwrite
.sdlc/work/<slug>/progress.md with one line —
spec · <doing what> · <ISO timestamp> (AGENTS.md rule 9).
Before you start
- Run
gates/check-gate.sh intent .sdlc/work/<slug>/intent.md. STOP if closed.
- Read intent.md fully. Read
.sdlc/memory/POLICY.md,
.sdlc/memory/INDEX.md, .sdlc/memory/DOMAIN.md, and the feature's
harvest.md if present; open lesson files whose tags match the current
task. Use DOMAIN.md terms so the spec uses the project's established
vocabulary.
- Brownfield: read the researcher report from stage 1 (or dispatch one now).
Draft
Fill templates/spec.md. Rules:
- Human summary first. The spec body is an agent-facing contract. The
gate reviewer is a human — possibly one with no technical background.
Write the top "Human summary" section so ANYONE can follow it (extends
hard rule 8): no code identifiers, no jargon (gloss an unavoidable term in the same
sentence), visible behavior rather than system internals — what problem,
what gets built, what stays unchanged, and each flagged concern as a
one-line decision with your recommendation. Test: would a non-developer
colleague understand every sentence? If not, rewrite. Write it LAST
(after the adversarial pass), place it FIRST.
- Every requirement traces to a line in intent.md. Do not add features that
intent.md does not request.
- Every intent.md open question ends up in exactly one of two places: answered
in the spec, or carried forward as a flagged concern.
- Define data shapes before behavior. Check schemas, API contracts, migrations,
and serialization end to end.
- Behavior as AS-IS → TO-BE pairs (template table). Brownfield AS-IS comes
from explorer or browser evidence with file:line or capture references. Use
observations, not memory. The pair format is also how the change is
presented to the human at the gate: what happens today, what will happen
after.
- Brownfield: include a "What stays untouched" section with testable
statements about behavior that must survive. This becomes the regression baseline.
- Ask for constraints the code does not show. Ownership boundaries,
forbidden areas, deploy windows, compatibility promises. Record them in the
spec. The plan stage inherits them and does not interview the human again.
- State the release procedure in one line (template section): branch →
merge target → push → deploy command. Ship follows this line; "none" is a
valid deploy command.
- Flag security, compliance, UX, and performance concerns inline. The human
resolves them at the gate.
Adversarial verification (automated, before the human)
Lazy shortcut: at lazymode ≥2 (AGENTS.md rule 3), run tools/tripwire.sh
over the draft spec.md first — a clean scan skips this review; any hit runs
it in full.
Dispatch a fresh-context adversary (roles/adversary.md) with ONLY:
intent.md, draft spec.md, .sdlc/memory/POLICY.md if present, and the
researcher report if any. It checks intent mismatch, wrong data shapes,
missing edge cases, scope creep, untestable requirements, and policy
violations.
- Fix what it catches; note each objection + resolution in spec.md's
Adversarial review section (proof for the human that review happened).
- If it finds an intent contradiction you cannot resolve from the artifacts:
STOP, return the question to the user. Do not guess.
- Repeat until the adversary has no blocking objections (max 2 rounds).
Non-blocking leftovers become flagged concerns; a blocker surviving
round 2 blocks
--lazy — human ask at any lazymode (rule 3).
Gate
At lazymode ≥2 (AGENTS.md rule 3): after a clean tripwire scan or a passed
adversary review (see the lazy shortcut above), run
<kit>/gates/approve.sh spec .sdlc/work/<slug>/spec.md --lazy, post the
Human summary and Flagged concerns as FYI, and dispatch plan
(skills/3-plan) as a subagent task (AGENTS.md rule 5). Otherwise:
Review .sdlc/work/<slug>/spec.md, especially Flagged concerns.
Then: <kit>/gates/approve.sh spec .sdlc/work/<slug>/spec.md
STOP after requesting approval.
1---2name: sdlc-spec3description: Spec generation, adversary-reviewed before the human gate. Triggers: intent gate approved.4---56# Stage 2: Spec78Goal: create `spec.md` from `intent.md` so engineering work has a clear9contract. The agent writes the spec, and the human reviews it. Automate checks10where possible. Keep human attention on gate decisions.1112Heartbeat: on entry and at every sub-task change, overwrite13`.sdlc/work/<slug>/progress.md` with one line —14`spec · <doing what> · <ISO timestamp>` (AGENTS.md rule 9).1516## Before you start17181. Run `gates/check-gate.sh intent .sdlc/work/<slug>/intent.md`. STOP if closed.192. Read intent.md fully. Read `.sdlc/memory/POLICY.md`,20 `.sdlc/memory/INDEX.md`, `.sdlc/memory/DOMAIN.md`, and the feature's21 `harvest.md` if present; open lesson files whose tags match the current22 task. Use DOMAIN.md terms so the spec uses the project's established23 vocabulary.243. Brownfield: read the researcher report from stage 1 (or dispatch one now).2526## Draft2728Fill `templates/spec.md`. Rules:2930- **Human summary first.** The spec body is an agent-facing contract. The31 gate reviewer is a human — possibly one with no technical background.32 Write the top "Human summary" section so ANYONE can follow it (extends33 hard rule 8): no code identifiers, no jargon (gloss an unavoidable term in the same34 sentence), visible behavior rather than system internals — what problem,35 what gets built, what stays unchanged, and each flagged concern as a36 one-line decision with your recommendation. Test: would a non-developer37 colleague understand every sentence? If not, rewrite. Write it LAST38 (after the adversarial pass), place it FIRST.39- Every requirement traces to a line in intent.md. Do not add features that40 intent.md does not request.41- Every intent.md open question ends up in exactly one of two places: answered42 in the spec, or carried forward as a flagged concern.43- Define data shapes before behavior. Check schemas, API contracts, migrations,44 and serialization end to end.45- Behavior as AS-IS → TO-BE pairs (template table). Brownfield AS-IS comes46 from explorer or browser evidence with file:line or capture references. Use47 observations, not memory. The pair format is also how the change is48 presented to the human at the gate: what happens today, what will happen49 after.50- Brownfield: include a **"What stays untouched"** section with testable51 statements about behavior that must survive. This becomes the regression baseline.52- **Ask for constraints the code does not show.** Ownership boundaries,53 forbidden areas, deploy windows, compatibility promises. Record them in the54 spec. The plan stage inherits them and does not interview the human again.55- **State the release procedure in one line** (template section): branch →56 merge target → push → deploy command. Ship follows this line; "none" is a57 valid deploy command.58- Flag security, compliance, UX, and performance concerns inline. The human59 resolves them at the gate.6061## Adversarial verification (automated, before the human)6263Lazy shortcut: at lazymode ≥2 (AGENTS.md rule 3), run `tools/tripwire.sh`64over the draft spec.md first — a clean scan skips this review; any hit runs65it in full.6667Dispatch a fresh-context adversary (`roles/adversary.md`) with ONLY:68intent.md, draft spec.md, `.sdlc/memory/POLICY.md` if present, and the69researcher report if any. It checks intent mismatch, wrong data shapes,70missing edge cases, scope creep, untestable requirements, and policy71violations.7273- Fix what it catches; note each objection + resolution in spec.md's74 **Adversarial review** section (proof for the human that review happened).75- If it finds an intent contradiction you cannot resolve from the artifacts:76 STOP, return the question to the user. Do not guess.77- Repeat until the adversary has no blocking objections (max 2 rounds).78 Non-blocking leftovers become flagged concerns; a blocker surviving79 round 2 blocks `--lazy` — human ask at any lazymode (rule 3).8081## Gate8283At lazymode ≥2 (AGENTS.md rule 3): after a clean tripwire scan or a passed84adversary review (see the lazy shortcut above), run85`<kit>/gates/approve.sh spec .sdlc/work/<slug>/spec.md --lazy`, post the86Human summary and Flagged concerns as FYI, and dispatch plan87(`skills/3-plan`) as a subagent task (AGENTS.md rule 5). Otherwise:8889> Review `.sdlc/work/<slug>/spec.md`, especially **Flagged concerns**.90> Then: `<kit>/gates/approve.sh spec .sdlc/work/<slug>/spec.md`9192STOP after requesting approval.