# Spec Workflow

> Spec-driven development loop with parallel task groups and the .claude/specs/<slug>/ structure (spec.md, design.md, tasks.md, review.md). Use before any non-trivial work that touches multiple files, involves architectural choices, or will be delegated to an agent team.

- Skill: `aws-samples/spec-workflow` (Agent Skill)
- Install (CLI): `npx skillmds@latest add aws-samples/spec-workflow`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aws-samples/spec-workflow/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: aws-samples (https://skillmd.com/u/aws-samples)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aws-samples/spec-workflow

---


# Spec-Driven Workflow

## When to Create a Spec

Create a spec before any non-trivial work — if it touches multiple files, involves architectural choices, or will be delegated to an agent team.

## Directory Structure

```
.claude/specs/<slug>/
  spec.md          # Design decisions, requirements, constraints
  design.md        # Architecture, repo structure, infrastructure design (optional)
  tasks.md         # Parallelized task list with agent assignments
  review.md        # per-group review findings per cycle (PASS/FAIL)
  review-e2e.md    # end-to-end review of the integrated deliverable (own cycles, own 3-cycle budget)
  sa-review.md     # sa-agent Well-Architected findings (optional)
  test-plan.md     # Tier coverage map — which T1/T2/T3/T4 check covers which component and criterion
  test-evidence.md # Per-tier verification evidence: command, exit code, key assertion output
  decisions.md     # Mid-flight decision log
  requirements.md  # From /brainstorm (optional)
  prd/             # Product requirements docs (optional)
```

Use short kebab-case slugs (e.g., `auth-api`, `vpc-redesign`).

## Task Format (`tasks.md`)

Tasks organized into parallel groups. All tasks in a group execute simultaneously; groups execute sequentially.

```markdown
## Group 1: <description>
Spec ref: `spec.md#<section>` — <what this implements>.
- [ ] [coding] <verb> <what> | `path/to/files` | <acceptance criteria>. Run: `<command>`
- [ ] [devops] <verb> <what> | `path/to/files` | <acceptance criteria>. Run: `<command>`
```

### Task Rules

- Each task is self-contained — completable without knowledge of sibling tasks
- Prefixed `[coding]`, `[devops]`, or `[sa]` for agent assignment
- Explicit file paths (no two tasks in same group write to same file)
- Interface contracts inline if producing/consuming shared interfaces (exact signatures)
- Verification command included, and it runs the **test tier** the task calls for (`testing-standards.md`) — a build/lint/validate command is not a test gate
- Small enough for one teammate in a single session

### Task Coordination

Tasks tracked in two synced places:
1. `tasks.md` — full context, completion notes, blocker details
2. Shared task list — `TaskCreate`/`TaskUpdate`/`TaskList` for real-time coordination

### Parallelization Guidelines

Maximize parallelism: no shared file writes -> same group. Infrastructure before app code. Shared interfaces before consumers. SA review runs parallel with implementation (reviews design, not code).

**Author for a worker pool, not a single worker.** The lead spawns *parallel pools* of same-role agents (up to 6 `coding`, 2 `devops`, 4 `review`) that self-claim from a shared queue. To keep them saturated:
- Make groups **wide** — as many file-disjoint same-role tasks per group as there are instances of that role. A group with one fat task starves the pool; split fat tasks along file/module boundaries.
- Make groups **few** — only start a new group when a real dependency forces a barrier. Independent work stays in the same group.
- Front-load a shared interface as a small early group so all dependents then run in parallel.
- Keep `[coding]` and `[devops]` work file-disjoint so both pools run at once.

**Parallel review (synthesizer + analysts).** When a group's changes span multiple areas, the lead assigns one reviewer as **synthesizer** (sole author of `review.md`, owns the single group verdict) and the rest as **analysts** who each review a disjoint slice and message structured findings to the synthesizer — they write no file. There is always exactly one `review.md` and one PASS/FAIL per cycle; a single reviewer handles small, cohesive groups alone.

## Development Loop

Plan -> **hand the lead role to the main agent** -> Build (per group) -> Review -> Fix (if FAIL) -> End-to-end review -> Docs -> Cleanup. See `fullstack-agent` system prompt for the detailed phase steps.

`fullstack-agent` owns Phase 1 only: it writes the spec, design, and task plan, then returns a **Handoff Package** (spawn plan + `TaskCreate` payloads + group order + open risks) and stops. A subagent either cannot spawn teammates at all or coordinates them unreliably across the nesting boundary, so the **main agent** assumes the lead role from Phase 2 on — it spawns the pool, owns the shared task store, and drives the build-review loop. The lead is a role; whoever holds it is who teammates message.

**Security scan remediation priority**: (1) Critical findings — immediate fix required. Run scans: `bandit -r src/ -f json -o .claude/specs/<slug>/bandit-results.json`, `semgrep --config auto --json -o .claude/specs/<slug>/semgrep-results.json`, `safety check --json > .claude/specs/<slug>/safety-results.json`, `checkov -d infra/ -o json > .claude/specs/<slug>/checkov-results.json`. (2) High findings — fix or document risk acceptance with compensating controls before merge, (3) Medium findings — fix within sprint or document acceptance.

**Acceptance criteria MUST include verification in priority order**: (1) Encryption at rest verified via `aws <service> describe-<resource> | jq '.EncryptionConfiguration'` (expect: AWS KMS key ARN present) — blocks deployment, (2) Encryption in transit verified via `aws <service> get-<resource>-policy` (expect: `aws:SecureTransport` condition present) — blocks deployment, (3) Access logging enabled via `aws <service> get-<resource>-logging` (expect: logging target configured) — required for review PASS, (4) Data classification tags via `aws <service> list-tags-of-resource` (expect: `data-classification` tag present) — required for review PASS.

**Serverless-specific acceptance criteria**: For Lambda tasks, verify event schema conformance via `get_lambda_event_schemas` from `aws-serverless` plugin. For SAM deployments, verification MUST include `sam_build` + `sam_local_invoke` (local test) before `sam_deploy`. For API Gateway, verify authorization is configured on all routes. For Aurora DSQL tasks, verify schema via `get_schema` and test queries via `readonly_query` from `databases-on-aws` plugin. For Amplify tasks, verify sandbox deployment succeeds before production.

**Test tiers (see the always-on `testing-standards.md` rule)**: Every deliverable is proven at four tiers — **T1** unit (isolated logic, mocked cloud), **T2** integration/contract (components against each other and against real-shaped dependencies; event, API, data-schema, IaC-output, and config-surface contracts asserted from both sides), **T3** deployed-resource verification (the live deployed resource exercised with the application's own identity — no mocks: Lambda invoked and `FunctionError` read, execution role checked with `iam simulate-principal-policy`, table key schema/GSIs asserted against the queries the code runs, every route called with **and** without a valid credential), **T4** end-to-end journeys (one per `spec.md` acceptance criterion through a real entry point, plus a failure journey). A green `deploy` is not a pass — it proves the control plane accepted your definitions, not that the role, schema, wiring, or auth work. Author `test-plan.md` in Phase 1 mapping tiers to components and criteria; record evidence in `test-evidence.md`. Every new permission, env var, or schema element needs a check that would fail without it. A skipped tier is declared and escalated, never silent.

**Completion criteria**: Zero criticals + zero warnings + all four tiers passing (or explicitly declared unrunnable and escalated) + all tasks `[x]`. Suggestions don't block.

**Live-validation gate (IaC / deploy / shell tooling) — the T3 gate**: Static checks (`terraform validate`, `cfn-lint`, `shellcheck`, `bash -n`, `checkov`, `helm lint`) are necessary but NOT sufficient — they cannot catch runtime/cloud-semantics bugs (wrong build context, a config file clobbering an env var, a missing `--region`, an SSE-S3-not-KMS backend, a wrong-kubeconfig-context deploy). Any group that changes a deploy script, IaC, or CI MUST be exercised by a real `deploy → smoke → teardown` (or the closest executable equivalent) before it is "done". If it cannot run in the current environment, record the affected criteria as author-and-static-validate-only and escalate that the live gate is outstanding — never a PASS that implies it ran.

**Verify the verifier**: A green gate is not proof the gate is adequate. When a check passes, confirm it actually asserts what it claims (a license-header check that greps one line passed truncated headers; a `verify-codegen` target was itself broken; a task `Run:` of `go build`+`go vet` never ran the CI-blocking linter). When you find a silent-gap class, fix the *check*, not just the instances.

**Review cycle budget**: The budget is **3 review cycles per review scope, non-resetting**, and there are two kinds of scope with independent counts. **Each task group** gets its own 3 (tracked as `## Cycle N` sections in `review.md`) — per group, not pooled across groups. **The end-to-end review** — the final pass over the whole integrated deliverable, run after every group has PASSed, covering cross-group integration seams, end-to-end flows against `spec.md` acceptance criteria, whole-repo security/IaC posture, and any live-validation gate not yet run against the assembled system — gets its own 3 (tracked in `review-e2e.md`). The counts never mix: an unused group cycle cannot fund the end-to-end pass, an end-to-end cycle cannot re-review one group, and the end-to-end pass is not a fourth cycle for a group that already failed 3 times. Name the scope and cycle in every handoff. A cycle is consumed when a synthesizer is **spawned**, not when it reports — so replacement reviewers and retries after an interruption or a resumed session count against the same 3. Never reset for a new fix wave, a new reviewer, a rewritten review file, or a re-spawned pool; derive the next number from the `## Cycle N` sections already in that scope's file, not from memory. Cycle 1 is broad, cycle 2 verifies fixes and hunts regressions, **cycle 3 is terminal**. A FAIL in cycle 1 or 2 earns exactly one scoped fix wave, re-verified by the next cycle of that same scope; a FAIL in cycle 3 ends the automatic loop for that scope — preserve findings and evidence, mark the tasks `[!]`, and report the group (or the whole deliverable, for end-to-end) blocked for the user. Never open cycle 4 in a scope without explicit user authorization logged in `decisions.md`, and don't route around the budget by relabelling a cycle a "quick recheck". Three FAILs mean the spec or the decomposition is wrong, not that a fourth pass is needed.

**Safeguards**: Log decisions in `decisions.md`. Same blocker twice -> escalate to user. Ground truth is disk + sentinels + `git diff` + `tasks.md`, not the task-store MCP or the mailbox — both lag and occasionally reset; when they disagree with disk, disk wins.

## Spec and Document Formats

Reference templates live in `docs/specs/templates/` (`spec.md`, `design.md`, `review.md`, `sa-review.md`, `decisions.md`, `prd.md`) — copy them into the working spec at `.claude/specs/<slug>/` as starting points; they are examples, not rigid constraints. If the directory is absent, follow the section structures described in this file and in the agent definitions. Any `design.md` MUST include a Security Considerations section regardless of template availability.

