Capability: spec-workflow
The core loop: a work item is specified as a chain of artifacts — optional brainstorm, then a Kiro-style 3-phase spec plus a testing plan — each iterated with the human feedback its approval gate records, locked by that gate, then executed end-to-end with minimal intervention.
What it is
The product-development-lifecycle workflow the-loop runs on every work item, exposed as the /the-loop:work-on superset command and granular per-step commands (brainstorm, new-requirement, create-ticket, create-design, create-tasks-plan, execute-tasks, finish-tasks, work-status), plus handoff, which starts a work item from a conversation at the stage it reached (issue-517).
Current behaviour
- Every work item SHALL have a ticket; nothing is worked without one.
- A work item's spec SHALL live in
docs/specs/<id>/— the loop's fixed convention; the CLI's ownrouting.graph.specDirdefaults to it, and an operator whose instance drives repositories laid out differently sets that key or passes--spec-dir(issue-352) — as the artifact chainbrainstorm.md (optional) → requirements.md|bugfix.md → design.md → testing-plan.md → tasks.md, plusevidence/— the record each gate leaves, and the committed proof once verification has run. - Every tree of checked-in knowledge the loop maintains SHALL sit at its conventional place, not a configured one: specs at
docs/specs/<id>/, capability docs atdocs/capabilities/and learnings atdocs/learnings/(the indexlearnings.md, onelearning-<nnn>.mdeach,topics/), all repo-relative (issue-224, decision-082 placed the learnings inside the documentation tree; issue-352 removed theworkflowkeys that had let a project move the three). The learnings deliberately sit inside the documentation tree, so a repository that publishesdocs/publishes its learnings with it; the git-ignored write-gate queue (.the-loop/learnings-pending/) is harness state and stays out of it. requirements.mdandbugfix.mdSHALL be two accepted names for the same phase-1 artifact, not two artifacts. Either clears therequirements-definitiongate, held to the identical standard; both present blocks, because two phase-1 artifacts in one folder have no defined source of truth (decision-045). Both bundled templates carry the## Requirementsand## Security considerationssections the gate requires, so the choice is about which shape fits the work — reproduction and root cause, or user stories — and never about which one will pass.- An artifact with an approval gate SHALL be iterated with the feedback that gate records and SHALL be locked by the gate itself (issue-281): on an authorized approval,
lock-artifactswritesstatus: approvedand the approver into the front matter. The session SHALL NOT setstatus: approvedand SHALL NOT request an approval of its own — one gate, one human reply (the review per phase is always on and delivered by the gates; theworkflow.requireHumanReviewPerPhaseswitch was removed in issue-352). The artifact with no gate (tasks.md) advances on shape alone;brainstorm.mdis locked bybrainstorm-approval(issue-494). No downstream artifact is written against an upstream one whose gate has not yet approved it. - The spec chain SHALL live in the origin repository — the one the ticket was created in — however many repositories the work item touches, and each contributing repository SHALL get one pull request walking its own inner loop (issue-183, decision-069). A work item MAY declare those repositories with
the-loop graph repos <id> --repository <owner>/<repo> …once the design and the task DAG say what the change spans, which records them inwork-item-state.jsonand turns them into a gate atimplementationrather than a note. - Where each artifact is iterated with humans SHALL be a durable, reviewable surface — never a terminal. For the outer loop the work item declares which, at
phase-selection: the work item itself (the default — comments on the ticket, so an item whose code lands in other repositories opens no discussion-only PR) or a pull request in the origin repository (theouter-loop-on-pull-requestbox). Either way the artifact SHALL be a committed file linked from the ticket — the choice is the review surface, not whether the chain is checked in. A pull request's own loop SHALL always be iterated on that pull request, and a contribution SHALL NOT be asked the question at all (issue-199): it joins a work item somebody else is running, so its one artifact is iterated on that thread and its record carries no surface. - WHEN an authorized
the-loop executeticks theclaude-artifactrow AND the work item resolves to theclaudeharness THENwork-item-state.jsonSHALL recordclaudeArtifact: true, and the session SHALL publish the spec chain as one Claude artifact — a tab per spec file, republished to the same URL on every change, linked once from the ticket (issue-471). The files SHALL stay the source of truth, and a comment on the artifact SHALL NOT answer a gate. On any other harness the tick SHALL NOT be applied, and the confirmation SHALL say so. - WHEN the
explainerrow is left ticked atphase-selection(the default) THEN the outer loop SHALL teach and check understanding twice (issue-488): afterdesign-approvalthe session SHALL write a spec explainer and spec quiz (/the-loop:explain), and code generation SHALL wait until an authorized user ticks the-loop's checkbox on the ticket; aftersecurity-reviewit SHALL write the explainer of the change — the reviewer's starting point — and the code quiz, and the review request SHALL wait for a tick on the pull request. The page SHALL be a tab of the spec-chain artifact whenclaudeArtifactis true, its own Claude artifact otherwise, and a committed self-contained HTML file on a harness with no artifact tool; the files SHALL stay the gates' subject. Seeskills/the-loop/reference/explainer.md. - WHEN a work item starts as a fuzzy idea THEN the loop SHALL begin with a
brainstorm.mdroot artifact (optional Phase 0) and convert it to requirements once thebrainstorm-approvalgate locks it on an authorized approval (issue-494). WHILE that gate is open, a comment that does not decide the review SHALL leave it waiting, in thebrainstormingphase. WHEN nobrainstorm.mdwas written, orbrainstormingwas declared skipped, THEN the loop SHALL route past the gate torequirements-definition. - WHEN a developer hands a conversation to the-loop (
/the-loop:handoff, thehandoff-to-the-loopskill, issue-517) THEN the skill SHALL draft only the prefix of the chain the conversation settled, interview, and post nothing before the developer confirms. It then files the GitHub issue (plus an optional Jira copy), and in a checkout pushes athe-loop/spec branch and a draft PR. It posts a handoff record last, and arms the item when asked. The skill SHALL refuse in a daemon-spawned session.The record names a stage and the node the walk enters:
Stage Carried enterexploringnothing, or a partial brainstorm.mdbrainstormingbrainstorm-settledbrainstorm.mdbrainstorm-approvalrequirements-settled+ requirements.mdorbugfix.mdrequirements-approvaldesign-settled+ design.md,testing-plan.mddesign-approvaldesign-settled+ design.mdonlytest-planningEach carried file is pinned by a
sha256of its LF bytes, and travels on the spec branch, inside the ticket comment (<details>blocks, overflow in part comments), or in the spec-chain Claude artifact. Before any later phase runs, theimport-handoffnode writes the files intodocs/specs/<id>/and checks each one. A file that is missing, tampered with or short of a required section demotes the walk to the phase that produces it. A carried artifact is never re-drafted.The approval rules do not change. The phase-selection reply still authorizes the walk. The developer's chat confirmation may approve only the earlier carried artifacts (
approved-in-chat, locked withapprovedVia: handoff <url>). The furthest carried artifact waits for its own gate on the ticket. See process-graph § Handed-off work items and decision-150.
- The work item's phase SHALL be tracked on the ticket via labels (
loop:<phase>, a fixed vocabulary since issue-352) through the state machinenot-started → brainstorming (optional) → requirements-definition → design → test-planning → tasks-breakdown → implementation → verification → needs-review → complete, with the fine detail (current node, attempts, declared skips) inwork-item-state.json. tasks.mdSHALL be a DAG of small verifiable tasks referencing requirements, each task's_Test:_naming a row oftesting-plan.md's matrix; checkmarks are kept current during implementation.- How the work item will be proved SHALL be planned, then executed as its own phase (testing-and-contracts, issue-163):
test-planningauthorstesting-plan.mdbefore the task DAG — and sits beforedesign-approval, so one human gate approves and locks the design and the plan derived from it — andverificationexecutes it after implementation and before the review chain, with results and committed evidence recorded in the same artifact. An activity that could not run is never ticked. - Security SHALL be a gated concern of each phase (a fixed rule, not a setting): requirements/bugfix carry a Security considerations threat-model-lite (untrusted actors, trust boundaries, abuse cases, fail-closed — "no new attack surface" is written and justified, never implied); design carries a Security design section enforcing every boundary; security-relevant tasks name the negative test proving the boundary holds.
- Completion SHALL be gated by the ready-to-ship gate (green checks, threads resolved, evidence — summarised from the verification results, a passed security review — the built-in security-review skill when available, else the-loop's checklist — PR briefing, capability docs folded in) and the fixed risk tiers: tier 1–2 autonomous-complete, 3–4 human-approves-pr, 5 human-approves-spec-and-pr, inferred from the change (default 3) and raised by a fixed set of sensitive paths (schemas,
.the-loop/**,.github/workflows/**, auth/secret/credential paths). An effective risk tier ≥ 4 SHALL wait for a named human security sign-off, and an unresolved security finding SHALL block completion at any tier. Tests are written alongside the implementation, always (a bug fix reproduces red first); there is no TDD mode to choose. - The loop SHALL read and honor the operator's custom instruction docs (
config.customInstructions): every registered doc is read, in order, immediately after loading the config when work on an item starts (and re-read after a context clear). The structured config wins where both speak; no instruction doc can weaken the loop's gates (security, paper trail, reviews, autonomy) — such instructions are ignored and the conflict logged, fail-closed. A missing doc is handled percustomInstructions.onMissing(defaultwarn). - A registration SHALL be verifiable, not only honoured. WHEN the agent (or an operator) runs
the-loop instructions --doc <entry>… --on-missing <policy>with the entries read fromcustomInstructions(the CLI reads no harness config, issue-352) THEN the loop SHALL report every doc given, in the order given, with its resolved path and one ofpresent/missing/unreadable/invalid; everything that is notpresentSHALL count as unresolved (invalidincluded), and--on-missingSHALL decide the exit code —error→ 1,warn→ 0 with a warning naming each one,ignore→ 0. IF no doc is given THEN the report SHALL be empty and the exit code 0, because registering nothing is not an error. The report SHALL carry facts about each doc and never its contents (cli, issue-132). - The loop SHALL manage its context window by checkpoint-then-reset (a fixed rule since issue-352,
config.contextManagementbefore it): a reset (clear or compact) is always preceded by a checkpoint —tasks.mdcheckmarks current, WIP committed, the phase label in sync. No prose checkpoint is written: the next step is the first unticked task and the pointer iswork-item-state.json's (issue-365). - WHEN the phase advances across a locked artifact (most importantly tasks-breakdown → implementation) THEN the loop SHALL clear and derive the next phase's work from the checked-in artifacts, not the conversation.
- WHEN a task in the DAG completes THEN the loop SHALL checkpoint and compact; mid-task only compaction is permitted, never clearing. Headless sessions reset by ending at the boundary and resuming fresh from the state file and the checkmarks.
- The phase state machine SHALL be executable, not only described. Each phase above is a node in the shipped process graph, with entry/exit hook chains that decide when it is complete and declared edges that route on those decisions (process-graph, issue-109). The prose in
reference/workflow.mdand the graph incli/the_loop/graph/pdlc.yamldescribe the same loop; the graph is the one that runs.the-loop check <id>reports where a work item actually stands against its checked-in artifacts, and--recomputederives that verdict from the artifacts alone rather than trusting stored state. - A work item may be delivered by several PRs. WHEN more than one PR delivers a work item (a spec PR then an implementation PR, a stacked series, a follow-up after review, one PR per repository) THEN the loop SHALL label each of them for routing and list all of them in
evidence/pull-requests.md, andfinish-tasksSHALL require every listed PR to be merged or closed before the work item is marked complete — one PR merging is not the work item ending (issue-101).
Design
reference/workflow.md · reference/context.md · reference/instructions.md · reference/security.md · SKILL.md · architecture § the loop
History
| Work item | What changed | Links |
|---|---|---|
| issue-517 | A conversation can be handed to the-loop at the stage it reached (2026-10-21): /the-loop:handoff (the handoff-to-the-loop skill) drafts the settled prefix of the chain, interviews, files the issue with a hashed handoff record, and the item enters at brainstorming, brainstorm-approval, requirements-approval, test-planning or design-approval. The new import-handoff node imports and checks the carried files and demotes on a failure; the approval gates are unchanged, and the furthest artifact is never approved in chat | spec, process-graph, decision-150, issue |
| issue-494 | The brainstorm is gated (2026-10-16): a human brainstorm-approval node follows brainstorming, so the author can comment and ask questions as often as they need and the brainstorm moves to requirements only on their approval, which locks brainstorm.md. A brainstorm that was never written, or a declared-skipped brainstorming, routes past the gate. Reverses issue-281's "gate-less" rule for brainstorm.md only; tasks.md stays gate-less | spec, process-graph, issue |
| issue-488 | The explainer and the quizzes (2026-10-15): a spec explainer + spec quiz before code generation and an explainer of the change + code quiz before review, sized by a depth ladder (micro / standard / deep, 0 / 3 / 5 questions), each gated by one attributed tick; published into the spec-chain artifact, its own artifact, or a committed HTML file with copy-paste view commands; on by default, one row to switch off | spec, process-graph, decision-143, issue |
| issue-471 | The spec chain can also be read as one Claude artifact (2026-10-06): ticked at phase-selection on a claude work item, the session publishes one page with a tab per spec file, republishes it to the same URL on every change and links it once from the ticket. The markdown files stay the source of truth and the gates' subject; artifact comments are feedback, never a gate answer. Off by default, and not applied on any other harness | spec, process-graph, issue |
| issue-368 | The work item's spec directory carries its pull requests (2026-09-15): work-item-state.json gained pullRequests[] — ref, repository, number, URL, inner-loop directory, upstream state and who recorded it — so a reviewer reads which pull requests deliver the item from the branch, and a second machine does not re-derive them from gh. It lost the session block in the same change: a harness conversation id is a handle to one machine and never belonged in a repository | spec, decision-128, process-graph, issue |
| issue-365 (review) | The multi-repo declaration moved off artifacts (2026-09-14) and onto a verb the agent calls, the-loop graph repos, writing work-item-state.json. It cannot be a phase-selection question: that gate runs before requirements, design and tasks exist, and which repositories a change spans is not knowable until they do — so it is declared at tasks-breakdown, bounded by shape and by the instance's own repositories, with the flags as the full set so a declaration can be corrected. The state file was renamed in the same round | spec, decision-127, process-graph, issue |
| issue-365 | The execution log was retired (2026-09-14): no template, no scaffolding, no log-entry hook at 47 node boundaries, no phase mirror and no prose checkpoint before a context reset — every fact in it was already in work-item-state.json, the loop:<phase> label, the commits and the harness's own transcript. What the log gated stayed: each review-chain node now reads one record of its own under evidence/, and the multi-repo repos declaration moved to work-item-state.json, declared by the agent once the task DAG exists. Existing logs are left where they are — history, read by nothing | spec, decision-126, process-graph, issue |
| issue-352 | The harness config became the agent's alone (2026-09-12): ticketing, workflow.phases, workflow.phaseLabelPrefix, workflow.specApproach, workflow.requireHumanReviewPerPhase, localOrchestration, notifications, reviews.critics and graph left it (version 0.3.0); labels are loop:<phase>; the-loop instructions and the-loop scenarios take the registered docs and globs as flags the agent passes; the skill's Configuration section tells the harness what the file is for and what to hand the CLI. Nine more blocks left because they configured what is now the-loop's fixed rule: autonomy (tiers 1–2 autonomous-complete, 3–4 human-approves-pr, 5 human-approves-spec-and-pr, inferred from the change, fixed sensitive paths), security (considerations in every requirements, design enforces the boundaries, a security review at the ready-to-ship gate, tier 4+ human sign-off), tdd (standard, always), minimalism, tokenEconomy, selfImprovement (learnings always on, index under 200 lines, written at the third occurrence), contextManagement (clear at a phase boundary, compact after each task, never mid-task), userInteraction and externalTools. A fourth pass removed workflow (specDir, capabilitiesDir, learningsDir): docs/specs/<id>/, docs/capabilities/ and docs/learnings/ are the loop's convention, and an instance laid out differently sets the CLI's routing.graph.specDir | spec, decision-123, issue |
| issue-281 | Approvals became gate-owned (2026-08-25): every artifact phase had been costing the human two approvals — one out-of-band to let the session set status: approved (demanded by locked: true on the producing node's exit), one at the graph's approval node, which discards pre-gate feedback — and tasks-breakdown demanded one with no gate at all. Producing nodes now gate shape only; a new lock-artifacts hook on requirements-approval, design-approval and the contribution loop's plan-approval writes status: approved plus the approvers as part of classifying the human's one reply; gate-less artifacts (brainstorm.md, tasks.md) advance with no human stop; and the skills/commands stopped re-implementing approvals in prose | spec, process-graph, issue |
| issue-224 | The learnings tree moved under the documentation tree: docs/learnings instead of a hardcoded top-level learnings/, with the-loop's own tree moved there and the upgrade command presenting (never taking) the relocation (the workflow.learningsDir key this introduced left the harness config in issue-352; the location is now the convention) | spec, decision-082, issue |
| issue-183 | The chain got a place: it lives in the repository the ticket was created in, one PR per contributing repository delivers it, and each work item declares at phase-selection whether the outer loop's artifacts are iterated on that repository's PR or on the work item itself (the default) — the inner loop deliberately not configurable. execution-log.md gained an optional repos: declaration that await-inner-loops gates on | spec, decision-069, process-graph, issue |
| issue-163 | The chain gained testing-plan.md between design and tasks, and the state machine gained the test-planning and verification phases — how a work item is proved is now planned, gated and evidenced rather than assumed | spec, decision-060, testing-and-contracts, issue |
| issue-124 | A bug's bugfix.md clears the phase-1 gate it always should have: the two documented names became alternatives for one artifact, both present blocks, and the bundled bugfix template gained the ## Requirements heading the gate asks for | spec, decision-045, process-graph, issue |
| issue-109 | The phase state machine became executable: every phase is a node in the shipped process graph, with hook chains deciding completion and declared edges routing on the outcome | spec, process-graph, decision-041, issue |
| issue-101 | The execution log tracks a list of the PRs delivering a work item; each is labelled for routing and all must be merged/closed before finish-tasks completes the item | spec, decision-039, issue |
| issue-132 | Custom instruction docs became verifiable: the-loop instructions reports which registered docs resolve and turns onMissing into an exit code, so a mistyped path is a signal rather than silence | spec, decision-049, cli, issue |
| issue-59 | Added per-installation custom instruction docs the loop reads and honors (customInstructions config, onboarding group, precedence rules) | spec, decision-029 |
| issue-48 | Added checkpoint-then-reset context-window management (clear at phase boundaries, compact at task boundaries, contextManagement config) | spec, decision-027 |
| issue-47 | Security became a gated concern of every phase: threat-model-lite in requirements, Security design section, security-review gate item, risk-tiered human sign-off (config.security) | spec, decision-026 |
| issue-25 | Added the capability-docs fold-in as a ready-to-ship gate item | spec, decision-020 |
| issue-18 | Design phase gained first-class UI/UX design artifacts | spec, decision-018 |
| issue-17 | Added the optional brainstorming phase and the iterate-until-locked rule as a first-class principle | spec, decision-017 |
| issue-1 | Established the 3-phase Kiro-style spec workflow, phase labels, granular commands and templates (v0) | spec, decision-004, decision-011 |