skilldrop-cli 0.11.5 → 0.11.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,55 +20,194 @@ Every skill is a plain `SKILL.md` folder — the [**Agent Skills open standard**
20
20
 
21
21
  ## How skilldrop works
22
22
 
23
- skilldrop runs two value streams, and **nothing comes out of either until it passes a review gate.** Both diagrams render on GitHub; the Mermaid sources live in [`docs/`](docs/) for easy re-rendering.
23
+ skilldrop ships **loops**, not just parts. A loop is a named sequence of stages over existing skills with a gate between them: [`loops/<name>/LOOP.md`](loops/) is what an agent reads, `loop.json` is the machine-readable contract ([RFC-0028](docs/rfcs/0028-loops-as-a-primitive.md)). **Nothing comes out of a loop until it passes that loop's gate.**
24
24
 
25
- ### Knowledge-work pipeline
25
+ A loop *sequences* skills — it never contains one. Every skill stays independently installable and runnable on its own, which is what keeps a single-folder copy working in Cursor, Kiro, or Aider.
26
26
 
27
- Raw input becomes a stakeholder-ready artifact — and loops back through review until it's approved.
27
+ Four loops cover the lifecycle, and they are separated by **reversibility** — how expensive the mistake is to unwind — which is why each gets its own gate rather than folding into a neighbour:
28
+
29
+ | Loop | Takes | Gate | Produces | Mistake costs |
30
+ |---|---|---|---|---|
31
+ | [`discover`](loops/discover/LOOP.md) | interviews, journeys, a strategy question | **G0** human — a person ratifies the brief | a ratified requirement | a re-brief |
32
+ | [`design`](loops/design/LOOP.md) | a ratified requirement | **G1** review — `council-review`'s panel | a recorded decision (ADR) | months, unwound in code |
33
+ | [`build`](loops/build/LOOP.md) | an agreed requirement or triaged defect | **G2** mechanical — `pre-merge-review`'s gate script decides | merged code | a revert |
34
+ | [`operate`](loops/operate/LOOP.md) | a shipped service | **G3** human — the incident is closed | a postmortem and runbook deltas | live users, irreversible |
35
+
36
+ Plus one **wrapper**, which is not a lifecycle stage but the two passes either side of *any* generator:
37
+
38
+ | Wrapper | Takes | Gate | Produces |
39
+ |---|---|---|---|
40
+ | [`ship-a-draft`](loops/ship-a-draft/LOOP.md) | raw notes, a transcript, a ticket | **G4** review — `doc-critique`'s verdict | a stakeholder-ready artifact |
41
+
42
+ Every gate emits a verdict from one shared vocabulary ([`contracts/terminals.json`](contracts/terminals.json)) in five classes — pass, conditional, revise, redirect, blocked — so `READY`, `PROCEED` and `SHIP IT` are recognisably the same kind of answer. Both diagrams render on GitHub; the Mermaid sources live in [`docs/`](docs/) for easy re-rendering.
43
+
44
+ *Diagrams below are generated from each loop's `loop.json` by [`build_loops.py`](build_loops.py) — edit the contract, not the picture.*
45
+
46
+ ### `discover` — raw signal to a ratified requirement
47
+
48
+ Interviews, journeys and strategy questions become one tagged brief, then numbered requirements a **human ratifies** before any design starts.
49
+
50
+ <!-- loop:discover:start -->
51
+
52
+ ```mermaid
53
+ %%{init: {'theme':'base','themeVariables':{'fontFamily':'Segoe UI, Helvetica, Arial','fontSize':'15px','lineColor':'#9AA5B1'},'flowchart':{'curve':'basis','rankSpacing':70,'nodeSpacing':50,'padding':16}}}%%
54
+ flowchart LR
55
+ classDef gen fill:#E8F0FE,stroke:#4C7DF0,stroke-width:1.5px,color:#1A3A8F;
56
+ classDef review fill:#FDEAEA,stroke:#E05B5B,stroke-width:1.5px,color:#8A1F1F;
57
+ classDef gate fill:#FBE3A2,stroke:#D9971E,stroke-width:2px,color:#6B4500,font-weight:bold;
58
+ classDef ship fill:#E6F7EC,stroke:#34A853,stroke-width:2px,color:#0F6B33,font-weight:bold;
59
+
60
+ gather["gather<br/><small>requirements-interview +2</small>"]:::gen
61
+ structure["structure<br/><small>brief-intake</small>"]:::gen
62
+ specify["specify<br/><small>prd-draft</small>"]:::gen
63
+ ratify["ratify<br/><small>doc-critique</small>"]:::gate
64
+ G0{"G0 · human"}:::gate
65
+ DONE(["complete"]):::ship
66
+
67
+ gather --> structure
68
+ structure --> specify
69
+ specify --> ratify
70
+ ratify --> G0
71
+ G0 == "PROCEED" ==> DONE
72
+
73
+ G0 -- "REVISE (max 3)" --> structure
74
+ ```
75
+
76
+ <!-- loop:discover:end -->
77
+
78
+ ### `design` — a requirement to a recorded decision
79
+
80
+ Constraints first, then structure and diagrams, then an attack, then a panel that must agree — and only then is the decision written down as an ADR.
81
+
82
+ <!-- loop:design:start -->
83
+
84
+ ```mermaid
85
+ %%{init: {'theme':'base','themeVariables':{'fontFamily':'Segoe UI, Helvetica, Arial','fontSize':'15px','lineColor':'#9AA5B1'},'flowchart':{'curve':'basis','rankSpacing':70,'nodeSpacing':50,'padding':16}}}%%
86
+ flowchart LR
87
+ classDef gen fill:#E8F0FE,stroke:#4C7DF0,stroke-width:1.5px,color:#1A3A8F;
88
+ classDef review fill:#FDEAEA,stroke:#E05B5B,stroke-width:1.5px,color:#8A1F1F;
89
+ classDef gate fill:#FBE3A2,stroke:#D9971E,stroke-width:2px,color:#6B4500,font-weight:bold;
90
+ classDef ship fill:#E6F7EC,stroke:#34A853,stroke-width:2px,color:#0F6B33,font-weight:bold;
91
+
92
+ constrain["constrain<br/><small>nfr-spec</small>"]:::gen
93
+ shape["shape<br/><small>design-doc·architecture-diagrams</small>"]:::gen
94
+ threat["threat<br/><small>threat-model</small>"]:::review
95
+ ratify["ratify<br/><small>council-review</small>"]:::gate
96
+ record["record<br/><small>adr-generator</small>"]:::gen
97
+ G1{"G1 · review"}:::gate
98
+ DONE(["complete"]):::ship
99
+
100
+ constrain --> shape
101
+ shape --> threat
102
+ threat --> ratify
103
+ ratify --> G1
104
+ G1 == "PROCEED" ==> record
105
+ record --> DONE
106
+
107
+ G1 -- "REVISE (max 3)" --> shape
108
+ ```
109
+
110
+ <!-- loop:design:end -->
111
+
112
+ ### `build` — a requirement to merged code
113
+
114
+ A vertical slice becomes shippable code through a self-correcting loop, gated by a script whose exit code decides. The inner generate-challenge cycle is the [`feature-implement-loop`](skills/feature-implement-loop/SKILL.md) skill.
115
+
116
+ <!-- loop:build:start -->
28
117
 
29
118
  ```mermaid
30
119
  %%{init: {'theme':'base','themeVariables':{'fontFamily':'Segoe UI, Helvetica, Arial','fontSize':'15px','lineColor':'#9AA5B1'},'flowchart':{'curve':'basis','rankSpacing':70,'nodeSpacing':50,'padding':16}}}%%
31
120
  flowchart LR
32
- classDef input fill:#FFF4E0,stroke:#E8A93B,stroke-width:2px,color:#7A4E00,font-weight:bold;
33
121
  classDef gen fill:#E8F0FE,stroke:#4C7DF0,stroke-width:1.5px,color:#1A3A8F;
34
122
  classDef review fill:#FDEAEA,stroke:#E05B5B,stroke-width:1.5px,color:#8A1F1F;
123
+ classDef gate fill:#FBE3A2,stroke:#D9971E,stroke-width:2px,color:#6B4500,font-weight:bold;
35
124
  classDef ship fill:#E6F7EC,stroke:#34A853,stroke-width:2px,color:#0F6B33,font-weight:bold;
36
125
 
37
- IN(["Raw input<br/>notes · ticket · transcript"]):::input
38
- brief["Structure the brief"]:::gen
39
- gens["Draft the artifact"]:::gen
40
- crit["Review and refine"]:::review
41
- ART(["Stakeholder-ready<br/>artifact"]):::ship
126
+ shape["shape<br/><small>user-story-splitter·bug-triage</small>"]:::gen
127
+ implement["implement<br/><small>feature-implement-loop</small>"]:::gen
128
+ verify["verify<br/><small>pre-merge-review</small>"]:::review
129
+ decide["decide<br/><small>council-review</small>"]:::gate
130
+ G2{"G2 · mechanical"}:::gate
131
+ G2_1{"G2.1 · human"}:::gate
132
+ DONE(["complete"]):::ship
133
+
134
+ shape --> implement
135
+ implement --> verify
136
+ verify --> G2
137
+ G2 == "READY" ==> decide
138
+ decide --> G2_1
139
+ G2_1 == "PROCEED" ==> DONE
140
+
141
+ G2 -- "NOT READY (max 3)" --> implement
142
+ G2_1 -- "REVISE (max 3)" --> shape
143
+ ```
144
+
145
+ <!-- loop:build:end -->
146
+
147
+ ### `operate` — a shipped service through detection and learning
148
+
149
+ Instrument, write the runbook, communicate the incident, then feed the postmortem's runbook deltas straight back into the runbook. The one loop whose failures are live.
150
+
151
+ <!-- loop:operate:start -->
42
152
 
43
- IN --> brief --> gens --> crit
44
- crit -- "revise" --> brief
45
- crit == "approved" ==> ART
153
+ ```mermaid
154
+ %%{init: {'theme':'base','themeVariables':{'fontFamily':'Segoe UI, Helvetica, Arial','fontSize':'15px','lineColor':'#9AA5B1'},'flowchart':{'curve':'basis','rankSpacing':70,'nodeSpacing':50,'padding':16}}}%%
155
+ flowchart LR
156
+ classDef gen fill:#E8F0FE,stroke:#4C7DF0,stroke-width:1.5px,color:#1A3A8F;
157
+ classDef review fill:#FDEAEA,stroke:#E05B5B,stroke-width:1.5px,color:#8A1F1F;
158
+ classDef gate fill:#FBE3A2,stroke:#D9971E,stroke-width:2px,color:#6B4500,font-weight:bold;
159
+ classDef ship fill:#E6F7EC,stroke:#34A853,stroke-width:2px,color:#0F6B33,font-weight:bold;
160
+
161
+ instrument["instrument<br/><small>observability-plan</small>"]:::gen
162
+ document["document<br/><small>runbook-generator</small>"]:::gen
163
+ respond["respond<br/><small>incident-comms</small>"]:::gen
164
+ learn["learn<br/><small>postmortem-generator</small>"]:::review
165
+ G3{"G3 · human"}:::gate
166
+ DONE(["complete"]):::ship
167
+
168
+ instrument --> document
169
+ document --> respond
170
+ respond --> learn
171
+ learn --> G3
172
+ G3 == "PROCEED" ==> DONE
173
+
174
+ G3 -- "REVISE (max 3)" --> document
46
175
  ```
47
176
 
48
- ### Code: implement and verify
177
+ <!-- loop:operate:end -->
178
+
179
+ ### `ship-a-draft` — raw input to a stakeholder-ready artifact
49
180
 
50
- A feature spec becomes shippable code through a self-correcting loop — generate, adversarially challenge, close the gaps, re-check — until the review is clean or a 3-round cap is hit. This is the [`feature-implement-loop`](skills/feature-implement-loop/SKILL.md) skill.
181
+ The wrapper: structured intake before any generator, critique and a machine-residue scrub after. Loops back through intake — not the draft — until it's approved.
182
+
183
+ <!-- loop:ship-a-draft:start -->
51
184
 
52
185
  ```mermaid
53
186
  %%{init: {'theme':'base','themeVariables':{'fontFamily':'Segoe UI, Helvetica, Arial','fontSize':'15px','lineColor':'#9AA5B1'},'flowchart':{'curve':'basis','rankSpacing':70,'nodeSpacing':50,'padding':16}}}%%
54
187
  flowchart LR
55
- classDef input fill:#FFF4E0,stroke:#E8A93B,stroke-width:2px,color:#7A4E00,font-weight:bold;
56
188
  classDef gen fill:#E8F0FE,stroke:#4C7DF0,stroke-width:1.5px,color:#1A3A8F;
57
189
  classDef review fill:#FDEAEA,stroke:#E05B5B,stroke-width:1.5px,color:#8A1F1F;
58
190
  classDef gate fill:#FBE3A2,stroke:#D9971E,stroke-width:2px,color:#6B4500,font-weight:bold;
59
191
  classDef ship fill:#E6F7EC,stroke:#34A853,stroke-width:2px,color:#0F6B33,font-weight:bold;
60
192
 
61
- IN(["Feature / story<br/>description + acceptance criteria"]):::input
62
- gC["Write and update<br/>code and tests"]:::gen
63
- revC["Challenge the code"]:::review
64
- gate{"Gaps found?"}:::gate
65
- SHIP(["Feature ready<br/>to be shipped"]):::ship
193
+ intake["intake<br/><small>brief-intake</small>"]:::gen
194
+ draft["draft<br/><small>*</small>"]:::gen
195
+ critique["critique<br/><small>doc-critique</small>"]:::review
196
+ polish["polish<br/><small>output-hygiene</small>"]:::review
197
+ G4{"G4 · review"}:::gate
198
+ DONE(["complete"]):::ship
199
+
200
+ intake --> draft
201
+ draft --> critique
202
+ critique --> G4
203
+ G4 == "SHIP IT" ==> polish
204
+ polish --> DONE
66
205
 
67
- IN --> gC --> revC --> gate
68
- gate -- "yes (up to 3 rounds)" --> gC
69
- gate == "no" ==> SHIP
206
+ G4 -- "MAJOR REWRITE (max 3)" --> intake
70
207
  ```
71
208
 
209
+ <!-- loop:ship-a-draft:end -->
210
+
72
211
  ## Skills in this repo
73
212
 
74
213
  ### Pipeline glue
@@ -0,0 +1,87 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/sananthanarayan/skilldrop/contracts/loop.schema.json",
4
+ "title": "skilldrop loop",
5
+ "$comment": "RFC-0028. A loop sequences existing skills; it never contains one. Skills stay in flat skills/<name> folders and stay independently installable — a loop is a named order plus the gates between stages. Enforced by validate.py with hand-rolled stdlib checks: skilldrop ships zero runtime dependencies and this file must not become a reason to add `jsonschema`.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["name", "description", "entrypoint", "kind", "stages"],
9
+ "properties": {
10
+ "$comment": { "type": "string" },
11
+ "name": {
12
+ "type": "string",
13
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
14
+ "description": "Kebab-case. Must equal the folder name and the LOOP.md frontmatter name — the same triple-match skills are held to."
15
+ },
16
+ "version": { "type": "string" },
17
+ "description": {
18
+ "type": "string",
19
+ "description": "Use-case-first. First half says what the loop delivers; second half states the trigger phrases an agent matches on."
20
+ },
21
+ "entrypoint": { "const": "LOOP.md" },
22
+ "kind": {
23
+ "enum": ["loop", "wrapper"],
24
+ "description": "`loop` advances stage to stage toward a terminal. `wrapper` wraps an arbitrary generator skill chosen at run time — its stages are the passes either side of that generator."
25
+ },
26
+ "cap": {
27
+ "type": "integer",
28
+ "minimum": 1,
29
+ "maximum": 10,
30
+ "default": 3,
31
+ "description": "Maximum revision rounds before the loop stops looping and emits its conditional or blocked terminal. Default 3, matching agent-loop-design's revision cap."
32
+ },
33
+ "stages": {
34
+ "type": "array",
35
+ "minItems": 1,
36
+ "items": {
37
+ "type": "object",
38
+ "additionalProperties": false,
39
+ "required": ["id", "type", "intent", "skills"],
40
+ "properties": {
41
+ "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
42
+ "type": {
43
+ "enum": ["generate", "verify", "gate"],
44
+ "description": "The three state types agent-loop-design mandates: 'Every loop has exactly these three state types.'"
45
+ },
46
+ "intent": { "type": "string", "description": "One line: what this stage is for." },
47
+ "skills": {
48
+ "type": "array",
49
+ "minItems": 1,
50
+ "items": { "type": "string" },
51
+ "description": "Skill folder names, in order. Each must be a real skills/<name>. `*` means any generator, and is legal only in a wrapper."
52
+ },
53
+ "gate": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "required": ["id", "kind", "verdicts"],
57
+ "properties": {
58
+ "id": {
59
+ "type": "string",
60
+ "pattern": "^G[0-9]+(\\.[0-9]+)?$",
61
+ "description": "Named gate, unique across the repo. A gate is a place a human or a script can point at."
62
+ },
63
+ "kind": {
64
+ "enum": ["mechanical", "review", "human"],
65
+ "description": "mechanical = a script's exit code decides. review = a skill or subagent panel decides. human = a person decides and the agent may not proceed without it."
66
+ },
67
+ "script": {
68
+ "type": "string",
69
+ "description": "Repo-relative path to the deciding script. Required when kind is mechanical, forbidden otherwise."
70
+ },
71
+ "verdicts": {
72
+ "type": "array",
73
+ "minItems": 2,
74
+ "items": { "type": "string" },
75
+ "description": "Every verdict this gate can emit. All must exist in contracts/terminals.json. Must include >=1 pass-class and >=1 non-pass."
76
+ },
77
+ "revise_to": {
78
+ "type": "string",
79
+ "description": "Stage id a revise-class verdict returns to. Must be an earlier stage in this loop."
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$comment": "RFC-0028 — the shared verdict vocabulary. Before this file, every gating skill invented its own terminal words: feature-implement-loop says VERIFIED, pre-merge-review says READY, council-review says PROCEED, doc-critique says SHIP IT. They mean the same five things. A loop's gate declares which verdicts it can emit, and validate.py checks every one against this file — so a new loop cannot invent a sixth kind of 'yes'.",
3
+ "version": "1.0.0",
4
+ "classes": {
5
+ "pass": "The gate is satisfied. The loop advances to the next stage, or terminates successfully.",
6
+ "conditional": "The gate is satisfied, but named open items travel forward with the artifact. Advancing is allowed; forgetting the items is not.",
7
+ "revise": "The gate is not satisfied and the fix is known. Return to the stage named by the loop's revision edge, subject to the cap.",
8
+ "redirect": "The gate is not satisfied and the work is the wrong shape. Do not revise — re-enter a different stage, a different loop, or a different artifact.",
9
+ "blocked": "The gate cannot be evaluated. A required input, decision, or permission is missing. Stop and name what is needed."
10
+ },
11
+ "verdicts": {
12
+ "VERIFIED": { "class": "pass", "origin": "feature-implement-loop" },
13
+ "READY": { "class": "pass", "origin": "pre-merge-review" },
14
+ "PROCEED": { "class": "pass", "origin": "council-review" },
15
+ "SHIP IT": { "class": "pass", "origin": "doc-critique" },
16
+ "VERIFIED WITH OPEN ITEMS": { "class": "conditional", "origin": "feature-implement-loop" },
17
+ "PROCEED WITH CONDITIONS": { "class": "conditional", "origin": "council-review" },
18
+ "SHIP WITH CHANGES": { "class": "conditional", "origin": "doc-critique" },
19
+ "NOT READY": { "class": "revise", "origin": "pre-merge-review" },
20
+ "REVISE": { "class": "revise", "origin": "council-review" },
21
+ "MAJOR REWRITE": { "class": "revise", "origin": "doc-critique" },
22
+ "RECONSIDER": { "class": "redirect", "origin": "council-review" },
23
+ "SPLIT": { "class": "redirect", "origin": "council-review" },
24
+ "WRONG ARTIFACT": { "class": "redirect", "origin": "doc-critique" },
25
+ "BLOCKED": { "class": "blocked", "origin": "feature-implement-loop" }
26
+ },
27
+ "rules": [
28
+ "Every gate declares at least one `pass` verdict and at least one non-pass verdict. A gate that can only succeed is not a gate.",
29
+ "Every gate can emit BLOCKED. A missing input is always possible and must never be fabricated past (AGENTS.md, non-interactive invocation).",
30
+ "A `revise` verdict is subject to the loop's `cap`. On the cap-th revise, the loop emits its conditional or blocked terminal instead of looping again.",
31
+ "A `redirect` verdict leaves the loop. It names where the work goes instead."
32
+ ]
33
+ }
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: build
3
+ description: Take an agreed requirement to merged code through a capped generate-verify-gate loop, with a mechanical gate that decides and a human who owns the merge. Use when the user wants to implement a story, fix a triaged bug, or ask whether a change is safe to merge.
4
+ ---
5
+
6
+ # build
7
+
8
+ The repo-scope loop: a requirement enters, merged code leaves, and nothing crosses a stage
9
+ boundary without passing that stage's gate. This loop *sequences* skills — it never contains
10
+ one. Every skill named below stays independently installable and runnable on its own.
11
+
12
+ ## Stages
13
+
14
+ | # | Stage | Type | Skills | Gate |
15
+ |---|---|---|---|---|
16
+ | 1 | `shape` | generate | [`user-story-splitter`](../../skills/user-story-splitter/SKILL.md), [`bug-triage`](../../skills/bug-triage/SKILL.md) | — |
17
+ | 2 | `implement` | generate | [`feature-implement-loop`](../../skills/feature-implement-loop/SKILL.md) | — |
18
+ | 3 | `verify` | verify | [`pre-merge-review`](../../skills/pre-merge-review/SKILL.md) | **G2** mechanical |
19
+ | 4 | `decide` | gate | [`council-review`](../../skills/council-review/SKILL.md) | **G2.1** human |
20
+
21
+ ## How to run this loop
22
+
23
+ 1. **Establish the unit of work.** New capability → `user-story-splitter`. Reported defect →
24
+ `bug-triage`. The stage is done when there is one vertical slice with acceptance criteria a
25
+ test can assert. Vague criteria are the single largest cause of a wasted round 3.
26
+ 2. **Implement.** Hand the slice to `feature-implement-loop`, which runs its own capped
27
+ generate-challenge-gate cycle internally. Do not re-implement its rounds here — this loop's
28
+ `cap` governs returns from G2, not the inner skill's rounds.
29
+ 3. **Verify at G2.** Run `pre-merge-review`. Its script decides and its panel explains:
30
+ `python3 skills/pre-merge-review/scripts/gate.py`. The exit code is the verdict —
31
+ `READY`, `NOT READY`, or `BLOCKED`.
32
+ 4. **Honour the gate.** `NOT READY` returns to `implement`, up to `cap` (3) times. On the
33
+ third return, stop looping and emit `BLOCKED` naming what did not converge. Never edit the
34
+ gate to make it pass.
35
+ 5. **Decide at G2.1.** The merge is a human's. Escalate design disagreements surfaced at G2 to
36
+ `council-review` rather than arguing them inside the diff; `RECONSIDER` and `SPLIT` both
37
+ leave this loop rather than revising within it.
38
+
39
+ ## Verdicts
40
+
41
+ Defined in [`contracts/terminals.json`](../../contracts/terminals.json). G2 emits
42
+ `READY` / `NOT READY` / `BLOCKED`. G2.1 emits the council vocabulary. A `revise`-class verdict
43
+ returns to the stage named in `revise_to`; a `redirect`-class verdict leaves the loop.
44
+
45
+ ## When a stage's skill is not installed
46
+
47
+ Skills install à la carte, so a stage may name a skill the target environment does not have.
48
+ Name the missing skill and skilldrop as its source, do the minimal inline version of that
49
+ stage, and record that the stage ran degraded. A missing skill is never a reason to skip a
50
+ **gate** — the gate is the loop's whole value.
51
+
52
+ ## Quality bar
53
+
54
+ - **The gate decides, not the agent.** G2's verdict is `gate.py`'s exit code. An agent that reasons its way past a red gate has broken the loop, not passed it.
55
+ - **The cap is honoured.** Three returns to `implement`, then `BLOCKED` with what did not converge. A fourth round is a defect in this loop, not diligence.
56
+ - **Every stage leaves evidence.** Each stage names its skill, its verdict, and its round number, so the run is auditable after the fact rather than asserted.
57
+ - **Acceptance criteria exist before `implement` starts.** A slice whose criteria a test cannot assert is not shaped; return it to `shape`.
58
+
59
+ ## Anti-patterns to avoid
60
+
61
+ - ❌ **Calling a skill from inside a skill to "continue the loop."** The loop sequences; skills do not chain. This is what keeps every skill portable to Cursor, Kiro, and Aider.
62
+ - ❌ **Editing `gate.py`, its config, or a test to turn G2 green.** That converts a mechanical gate into a decorative one.
63
+ - ❌ **Treating `PROCEED WITH CONDITIONS` as `PROCEED`.** The conditions travel with the artifact; dropping them is how conditional approvals become unconditional ones.
64
+ - ❌ **Running `decide` for every change.** G2.1 exists for escalated disagreement and the merge itself, not as a ceremony on top of a green gate.
65
+ - ❌ **Starting at `implement` because the story "is obvious."** Unshaped work is what produces a diff nobody can review against anything.
@@ -0,0 +1,48 @@
1
+ {
2
+ "$comment": "RFC-0028. This loop is docs/code-implement-verify.mmd promoted from a hand-maintained diagram into the machine-readable source that diagram is now generated from.",
3
+ "name": "build",
4
+ "version": "0.1.0",
5
+ "description": "Take an agreed requirement to merged code through a capped generate-verify-gate loop, with a mechanical gate that decides and a human who owns the merge. Use when the user wants to implement a story, fix a triaged bug, or ask whether a change is safe to merge.",
6
+ "entrypoint": "LOOP.md",
7
+ "kind": "loop",
8
+ "cap": 3,
9
+ "stages": [
10
+ {
11
+ "id": "shape",
12
+ "type": "generate",
13
+ "intent": "Turn a requirement or defect into one vertically-sliced unit of work with acceptance criteria.",
14
+ "skills": ["user-story-splitter", "bug-triage"]
15
+ },
16
+ {
17
+ "id": "implement",
18
+ "type": "generate",
19
+ "intent": "Write the code and its tests against the acceptance criteria, challenging the result each round.",
20
+ "skills": ["feature-implement-loop"]
21
+ },
22
+ {
23
+ "id": "verify",
24
+ "type": "verify",
25
+ "intent": "Judge the diff that now exists. The script decides; the panel explains.",
26
+ "skills": ["pre-merge-review"],
27
+ "gate": {
28
+ "id": "G2",
29
+ "kind": "mechanical",
30
+ "script": "skills/pre-merge-review/scripts/gate.py",
31
+ "verdicts": ["READY", "NOT READY", "BLOCKED"],
32
+ "revise_to": "implement"
33
+ }
34
+ },
35
+ {
36
+ "id": "decide",
37
+ "type": "gate",
38
+ "intent": "A human merges. Design disagreements surfaced at G2 are adjudicated here, not argued in the diff.",
39
+ "skills": ["council-review"],
40
+ "gate": {
41
+ "id": "G2.1",
42
+ "kind": "human",
43
+ "verdicts": ["PROCEED", "PROCEED WITH CONDITIONS", "REVISE", "RECONSIDER", "SPLIT", "BLOCKED"],
44
+ "revise_to": "shape"
45
+ }
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: design
3
+ description: Take a ratified requirement to a recorded architectural decision — constraints, structure, diagrams, threats, then a panel that must agree before the decision is written down. Use when the user is designing a system, choosing an architecture, or asking how something should be built.
4
+ ---
5
+
6
+ # design
7
+
8
+ The loop with the worst reversibility profile in the repo. A discovery mistake costs a
9
+ re-brief; a design mistake surfaces months later, in code nobody wants to unwind. That is why
10
+ its gate is a **panel** — independent positions, surfaced cruxes, recorded dissent — and not
11
+ a script, and why the decision is recorded only *after* the panel agrees.
12
+
13
+ ## Stages
14
+
15
+ | # | Stage | Type | Skills | Gate |
16
+ |---|---|---|---|---|
17
+ | 1 | `constrain` | generate | [`nfr-spec`](../../skills/nfr-spec/SKILL.md) | — |
18
+ | 2 | `shape` | generate | [`design-doc`](../../skills/design-doc/SKILL.md), [`architecture-diagrams`](../../skills/architecture-diagrams/SKILL.md) | — |
19
+ | 3 | `threat` | verify | [`threat-model`](../../skills/threat-model/SKILL.md) | — |
20
+ | 4 | `ratify` | gate | [`council-review`](../../skills/council-review/SKILL.md) | **G1** review |
21
+ | 5 | `record` | generate | [`adr-generator`](../../skills/adr-generator/SKILL.md) | — |
22
+
23
+ ## How to run this loop
24
+
25
+ 1. **Constrain before shaping.** `nfr-spec` first, always. A design produced before its
26
+ quality targets exist gets judged on taste, and taste does not survive a review panel.
27
+ 2. **Shape prose and picture together.** `design-doc` and `architecture-diagrams` are one
28
+ artifact in two renderings. A diagram that disagrees with the doc is a defect in both.
29
+ 3. **Attack it before ratifying.** `threat-model` consumes the design directly. Running it
30
+ after G1 means the panel ratified something nobody had attacked.
31
+ 4. **Ratify at G1.** `council-review` seats the standing panel, takes positions *before*
32
+ cross-talk, names the cruxes, and records dissent with "what would change our mind".
33
+ `REVISE` returns to `shape`. `SPLIT` and `RECONSIDER` leave the loop.
34
+ 5. **Record last.** `adr-generator` writes the decision *after* it is a decision, with the
35
+ rejected options and the reasoning that killed them. An ADR written before G1 is a proposal
36
+ wearing an ADR's clothes.
37
+
38
+ ## Verdicts
39
+
40
+ Defined in [`contracts/terminals.json`](../../contracts/terminals.json). `PROCEED WITH
41
+ CONDITIONS` is the common outcome and the most abused: the conditions are part of the
42
+ decision, and `record` must carry them into the ADR.
43
+
44
+ ## Non-interactive runs
45
+
46
+ `council-review` can be run by an agent seating the panel itself, so G1 is satisfiable without
47
+ a human. `SPLIT` is not — a genuine unresolved split needs a person. Emit
48
+ `BLOCKED: need a decision-maker for <the crux>` and name the positions.
49
+
50
+ ## When a stage's skill is not installed
51
+
52
+ Name the missing skill and skilldrop as its source, do the minimal inline version, and record
53
+ the stage as degraded. If `council-review` is missing, do not skip G1 — run the panel inline
54
+ from the design's own quality attributes and say the seating was improvised.
55
+
56
+ ## Quality bar
57
+
58
+ - **Quality targets exist before structure does.** `nfr-spec` is stage 1 because a design without numbers can only be argued about.
59
+ - **The ADR names what was rejected and why.** A decision record with one option is a description of what happened, not a decision.
60
+ - **Dissent is recorded, not resolved away.** A panel that always reaches consensus is not seating real positions.
61
+ - **The diagram and the doc say the same thing.** They are checked against each other before G1, not after someone builds from the wrong one.
62
+
63
+ ## Anti-patterns to avoid
64
+
65
+ - ❌ **Writing the ADR before G1.** It pre-commits the panel to a decision it has not made, and every reviewer can feel it.
66
+ - ❌ **Running `threat-model` after ratification.** The panel then ratified an unattacked design, which is the failure this ordering exists to prevent.
67
+ - ❌ **Treating `PROCEED WITH CONDITIONS` as `PROCEED`.** The conditions must reach the ADR; dropping them is how a conditional approval silently becomes unconditional.
68
+ - ❌ **Skipping `constrain` because the NFRs are "obvious".** Obvious targets are the ones nobody writes down and everybody remembers differently.
@@ -0,0 +1,47 @@
1
+ {
2
+ "$comment": "RFC-0028. The loop with the worst reversibility profile: a design mistake surfaces months later in code nobody wants to unwind. That is why its gate is a panel, not a script.",
3
+ "name": "design",
4
+ "version": "0.1.0",
5
+ "description": "Take a ratified requirement to a recorded architectural decision — constraints, structure, diagrams, threats, then a panel that must agree before the decision is written down. Use when the user is designing a system, choosing an architecture, or asking how something should be built.",
6
+ "entrypoint": "LOOP.md",
7
+ "kind": "loop",
8
+ "cap": 3,
9
+ "stages": [
10
+ {
11
+ "id": "constrain",
12
+ "type": "generate",
13
+ "intent": "Name the quality targets before the structure, so the design is judged against numbers rather than taste.",
14
+ "skills": ["nfr-spec"]
15
+ },
16
+ {
17
+ "id": "shape",
18
+ "type": "generate",
19
+ "intent": "Write the design and render it. The prose and the picture are one artifact and must not disagree.",
20
+ "skills": ["design-doc", "architecture-diagrams"]
21
+ },
22
+ {
23
+ "id": "threat",
24
+ "type": "verify",
25
+ "intent": "Attack the design that now exists, before it is ratified rather than after it is built.",
26
+ "skills": ["threat-model"]
27
+ },
28
+ {
29
+ "id": "ratify",
30
+ "type": "gate",
31
+ "intent": "A standing panel takes independent positions before cross-talk, surfaces the cruxes, and records dissent.",
32
+ "skills": ["council-review"],
33
+ "gate": {
34
+ "id": "G1",
35
+ "kind": "review",
36
+ "verdicts": ["PROCEED", "PROCEED WITH CONDITIONS", "REVISE", "RECONSIDER", "SPLIT", "BLOCKED"],
37
+ "revise_to": "shape"
38
+ }
39
+ },
40
+ {
41
+ "id": "record",
42
+ "type": "generate",
43
+ "intent": "Write the decision down with its rejected alternatives, so the next team inherits the reasoning and not just the outcome.",
44
+ "skills": ["adr-generator"]
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: discover
3
+ description: Take raw signal — interviews, journeys, a strategy question — to a requirement a human has ratified, so design starts from an agreed problem rather than an assumed one. Use when the user is deciding what to build, scoping a feature, or turning stakeholder conversations into requirements.
4
+ ---
5
+
6
+ # discover
7
+
8
+ The first loop of the lifecycle, and the cheapest one to run twice. Everything downstream
9
+ inherits whatever this loop got wrong, which is why it ends at a **human** gate rather than a
10
+ script: no check can tell you that you solved the wrong problem well.
11
+
12
+ ## Stages
13
+
14
+ | # | Stage | Type | Skills | Gate |
15
+ |---|---|---|---|---|
16
+ | 1 | `gather` | generate | [`requirements-interview`](../../skills/requirements-interview/SKILL.md), [`user-journey-map`](../../skills/user-journey-map/SKILL.md), [`strategy-analysis`](../../skills/strategy-analysis/SKILL.md) | — |
17
+ | 2 | `structure` | generate | [`brief-intake`](../../skills/brief-intake/SKILL.md) | — |
18
+ | 3 | `specify` | generate | [`prd-draft`](../../skills/prd-draft/SKILL.md) | — |
19
+ | 4 | `ratify` | gate | [`doc-critique`](../../skills/doc-critique/SKILL.md) | **G0** human |
20
+
21
+ ## How to run this loop
22
+
23
+ 1. **Gather from whichever direction the signal arrives.** A stakeholder conversation →
24
+ `requirements-interview`. An existing experience with known friction → `user-journey-map`.
25
+ An open strategic question → `strategy-analysis`. Run one; running all three on the same
26
+ input produces three views of the same thing and no more information.
27
+ 2. **Structure once.** `brief-intake` tags every field `[explicit]` / `[implied]` /
28
+ `[inferred]` / `[missing]` with verbatim quotes. The tags are the deliverable — an
29
+ untagged brief hides which parts are somebody's assumption.
30
+ 3. **Resolve the missing before specifying.** `brief-intake` ends with what the downstream
31
+ skill will refuse to start without. Answer those; do not let `prd-draft` invent them.
32
+ 4. **Specify.** `prd-draft` turns the brief into numbered requirements a design can be held to.
33
+ 5. **Ratify at G0.** Run `doc-critique` against the PRD, then put the decision to a human.
34
+ The critique informs; the human decides. `REVISE` returns to `structure`, not to `specify`
35
+ — a weak PRD almost always means a thin brief.
36
+
37
+ ## Verdicts
38
+
39
+ Defined in [`contracts/terminals.json`](../../contracts/terminals.json). G0 emits `PROCEED`,
40
+ `PROCEED WITH CONDITIONS`, `REVISE`, `RECONSIDER`, or `BLOCKED`. `RECONSIDER` leaves the loop:
41
+ the problem itself is wrong, and no amount of re-briefing fixes that.
42
+
43
+ ## Non-interactive runs
44
+
45
+ With no human present, G0 cannot be satisfied. Emit `BLOCKED: need ratification of <the
46
+ brief's central claim>` and stop. Do not self-ratify — a fabricated goal corrupts every
47
+ artifact the other four loops produce.
48
+
49
+ ## When a stage's skill is not installed
50
+
51
+ Name the missing skill and skilldrop as its source, do the minimal inline version of that
52
+ stage, and record that it ran degraded. Never skip G0.
53
+
54
+ ## Quality bar
55
+
56
+ - **Every field carries a provenance tag.** A brief that does not distinguish quoted from inferred cannot be ratified, only believed.
57
+ - **`[missing]` is resolved or stated, never filled.** Inventing the goal, the customer, or the success measure is the one failure this loop exists to prevent.
58
+ - **The requirements are numbered and testable.** "Fast" is not a requirement; a latency target is.
59
+ - **A human ratifies before design starts.** G0 is the loop's only reason to exist — an unratified brief is a draft, whatever the critique said.
60
+
61
+ ## Anti-patterns to avoid
62
+
63
+ - ❌ **Running all three `gather` skills to be thorough.** Three lenses on one input is not three inputs; pick the one that matches where the signal came from.
64
+ - ❌ **Letting `prd-draft` fill a `[missing]` field.** That converts an open question into a fact nobody agreed to.
65
+ - ❌ **Treating `doc-critique`'s `SHIP IT` as ratification.** The critique judges the document; G0 judges the problem.
66
+ - ❌ **Returning `REVISE` to `specify`.** Re-writing the PRD from the same thin brief reproduces the same gaps in better prose.
@@ -0,0 +1,41 @@
1
+ {
2
+ "$comment": "RFC-0028. The first loop of the lifecycle: nothing is designed or built until a human has ratified what problem is being solved. Cheapest loop to redo and the most expensive to skip.",
3
+ "name": "discover",
4
+ "version": "0.1.0",
5
+ "description": "Take raw signal — interviews, journeys, a strategy question — to a requirement a human has ratified, so design starts from an agreed problem rather than an assumed one. Use when the user is deciding what to build, scoping a feature, or turning stakeholder conversations into requirements.",
6
+ "entrypoint": "LOOP.md",
7
+ "kind": "loop",
8
+ "cap": 3,
9
+ "stages": [
10
+ {
11
+ "id": "gather",
12
+ "type": "generate",
13
+ "intent": "Collect the raw signal from whichever direction it arrives: a stakeholder conversation, an existing user journey, or a strategic question.",
14
+ "skills": ["requirements-interview", "user-journey-map", "strategy-analysis"]
15
+ },
16
+ {
17
+ "id": "structure",
18
+ "type": "generate",
19
+ "intent": "Turn the mess into one brief with every field tagged explicit / implied / inferred / missing, so downstream can see what was assumed.",
20
+ "skills": ["brief-intake"]
21
+ },
22
+ {
23
+ "id": "specify",
24
+ "type": "generate",
25
+ "intent": "Turn the ratified brief into numbered requirements a design can be held to.",
26
+ "skills": ["prd-draft"]
27
+ },
28
+ {
29
+ "id": "ratify",
30
+ "type": "gate",
31
+ "intent": "A human agrees this is the problem worth solving. The critique informs that decision; it does not make it.",
32
+ "skills": ["doc-critique"],
33
+ "gate": {
34
+ "id": "G0",
35
+ "kind": "human",
36
+ "verdicts": ["PROCEED", "PROCEED WITH CONDITIONS", "REVISE", "RECONSIDER", "BLOCKED"],
37
+ "revise_to": "structure"
38
+ }
39
+ }
40
+ ]
41
+ }
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: operate
3
+ description: Take a shipped service through detection, response, and learning — instrument it, write the runbook, communicate the incident, then feed the postmortem's deltas back into the runbook. Use when the user is preparing to run a service, is in an incident, or is writing a postmortem.
4
+ ---
5
+
6
+ # operate
7
+
8
+ The only loop whose failures are **irreversible and live**. The other four can be re-run at
9
+ the cost of time; this one runs while real users are affected. Its feedback edge is the point:
10
+ `postmortem-generator` emits runbook deltas phrased as edits, and those go straight back into
11
+ `document`. An incident that changes no procedure has not been learned from.
12
+
13
+ ## Stages
14
+
15
+ | # | Stage | Type | Skills | Gate |
16
+ |---|---|---|---|---|
17
+ | 1 | `instrument` | generate | [`observability-plan`](../../skills/observability-plan/SKILL.md) | — |
18
+ | 2 | `document` | generate | [`runbook-generator`](../../skills/runbook-generator/SKILL.md) | — |
19
+ | 3 | `respond` | generate | [`incident-comms`](../../skills/incident-comms/SKILL.md) | — |
20
+ | 4 | `learn` | verify | [`postmortem-generator`](../../skills/postmortem-generator/SKILL.md) | **G3** human |
21
+
22
+ ## How to run this loop
23
+
24
+ 1. **Instrument first.** `observability-plan` decides what is measured and what pages a human.
25
+ You cannot respond to what you never detected, and you cannot write a runbook entry for an
26
+ alert that does not exist.
27
+ 2. **Write the runbook per alert.** Each alert the previous stage defined maps to a
28
+ `runbook-generator` entry. An alert with no procedure wakes someone who then has to think.
29
+ 3. **Respond to the audience the incident actually has.** `incident-comms` is staged —
30
+ detect, mitigate, resolve — and the stage determines the message. Writing a resolution
31
+ update during mitigation is the most common error here.
32
+ 4. **Learn at G3.** `postmortem-generator` analyses blamelessly and ends with runbook deltas.
33
+ A human signs off that the incident is closed. `REVISE` returns to `document`: the deltas
34
+ are the loop's output, and applying them is what closes it.
35
+
36
+ Entering mid-loop is normal and expected. An incident starts at `respond`; a new service
37
+ starts at `instrument`. Do not replay earlier stages for their own sake.
38
+
39
+ ## Verdicts
40
+
41
+ Defined in [`contracts/terminals.json`](../../contracts/terminals.json). G3 emits `PROCEED`,
42
+ `PROCEED WITH CONDITIONS`, `REVISE`, or `BLOCKED`. `PROCEED WITH CONDITIONS` means the
43
+ incident is closed but named follow-ups are outstanding — they travel with the postmortem.
44
+
45
+ ## Non-interactive runs
46
+
47
+ Never fabricate incident facts — timings, impact, customer counts, root cause. When the
48
+ timeline is incomplete, emit `BLOCKED: need <the missing facts>` and name them. A confident
49
+ postmortem built on guessed impact is worse than no postmortem.
50
+
51
+ ## When a stage's skill is not installed
52
+
53
+ Name the missing skill and skilldrop as its source, do the minimal inline version, and record
54
+ the stage as degraded. During a live incident, prefer the degraded inline version over
55
+ stopping to install anything.
56
+
57
+ ## Quality bar
58
+
59
+ - **Every alert has a runbook entry.** An alert that pages someone with no procedure is an interruption, not a signal.
60
+ - **The postmortem ends in runbook deltas.** Analysis with no procedural change is a story about an outage.
61
+ - **Comms match the incident's actual stage.** Detect, mitigate, and resolve have different audiences and different truths.
62
+ - **Blameless means blameless.** Naming a person is a defect in the postmortem; naming a missing guardrail is the point.
63
+
64
+ ## Anti-patterns to avoid
65
+
66
+ - ❌ **Writing the runbook before the observability plan.** Procedures for alerts that do not exist, and none for the alerts that do.
67
+ - ❌ **Skipping `learn` because the incident was small.** Small incidents are where the cheap runbook deltas are.
68
+ - ❌ **Guessing impact numbers to finish the postmortem.** State the gap; a postmortem's value is entirely in its accuracy.
69
+ - ❌ **Replaying `instrument` during a live incident.** Enter at `respond`; the loop is not a checklist to complete in order.
@@ -0,0 +1,41 @@
1
+ {
2
+ "$comment": "RFC-0028. The only loop whose failures are irreversible and live. Its feedback edge is real and already documented in the repo: postmortem-generator emits runbook deltas phrased as edits for runbook-generator.",
3
+ "name": "operate",
4
+ "version": "0.1.0",
5
+ "description": "Take a shipped service through detection, response, and learning — instrument it, write the runbook, communicate the incident, then feed the postmortem's deltas back into the runbook. Use when the user is preparing to run a service, is in an incident, or is writing a postmortem.",
6
+ "entrypoint": "LOOP.md",
7
+ "kind": "loop",
8
+ "cap": 3,
9
+ "stages": [
10
+ {
11
+ "id": "instrument",
12
+ "type": "generate",
13
+ "intent": "Decide what is measured and what pages a human. You cannot respond to what you never detected.",
14
+ "skills": ["observability-plan"]
15
+ },
16
+ {
17
+ "id": "document",
18
+ "type": "generate",
19
+ "intent": "Write the procedure the on-call follows at 3am, per alert the previous stage defined.",
20
+ "skills": ["runbook-generator"]
21
+ },
22
+ {
23
+ "id": "respond",
24
+ "type": "generate",
25
+ "intent": "Communicate during the incident, to the audience that needs it, at the stage the incident is actually in.",
26
+ "skills": ["incident-comms"]
27
+ },
28
+ {
29
+ "id": "learn",
30
+ "type": "verify",
31
+ "intent": "Analyse blamelessly and emit runbook deltas. An incident that changes no procedure has not been learned from.",
32
+ "skills": ["postmortem-generator"],
33
+ "gate": {
34
+ "id": "G3",
35
+ "kind": "human",
36
+ "verdicts": ["PROCEED", "PROCEED WITH CONDITIONS", "REVISE", "BLOCKED"],
37
+ "revise_to": "document"
38
+ }
39
+ }
40
+ ]
41
+ }
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: ship-a-draft
3
+ description: Take raw mess to a stakeholder-ready artifact by wrapping any skilldrop generator in the two passes either side of it — structured intake before, critique and machine-residue scrub after. Use when the user has notes, a transcript, or a ticket and wants a finished document rather than a first draft.
4
+ ---
5
+
6
+ # ship-a-draft
7
+
8
+ A **wrapper**, not a lifecycle loop. Its centre stage is whichever generator the user actually
9
+ needs — an ADR, a design doc, a runbook, a deck, an exec summary. The wrapper contributes the
10
+ two passes every generator otherwise leaves to chance: collect the input properly before, and
11
+ check the argument and the surface after.
12
+
13
+ ## Stages
14
+
15
+ | # | Stage | Type | Skills | Gate |
16
+ |---|---|---|---|---|
17
+ | 1 | `intake` | generate | [`brief-intake`](../../skills/brief-intake/SKILL.md) | — |
18
+ | 2 | `draft` | generate | any generator (`*`) | — |
19
+ | 3 | `critique` | verify | [`doc-critique`](../../skills/doc-critique/SKILL.md) | **G4** review |
20
+ | 4 | `polish` | verify | [`output-hygiene`](../../skills/output-hygiene/SKILL.md) | — |
21
+
22
+ ## How to run this wrapper
23
+
24
+ 1. **Pick the generator first.** The brief is shaped *for a target*, so `draft` is chosen
25
+ before `intake` runs, not after. `brief-intake`'s own routing table maps trigger phrases to
26
+ targets; use it.
27
+ 2. **Collect once.** Run `brief-intake`. Every field is tagged `[explicit]` / `[implied]` /
28
+ `[inferred]` / `[missing]`, and its "Missing for downstream" section predicts what the
29
+ chosen generator will refuse to start without. Resolve those before drafting.
30
+ 3. **Draft.** Run the chosen generator on the brief. It is a normal skilldrop skill with its
31
+ own quality bar — this wrapper does not override it.
32
+ 4. **Critique at G4.** Run `doc-critique`, which dispatches to the same rubric the generator
33
+ was held to. `MAJOR REWRITE` returns to `intake` (not to `draft` — a rewrite usually means
34
+ the input was wrong, not the prose). `WRONG ARTIFACT` leaves the wrapper entirely.
35
+ 5. **Polish last.** Run `output-hygiene` only once the argument is settled. It is a surface
36
+ pass; running it on a draft that is about to be rewritten wastes it.
37
+
38
+ ## Verdicts
39
+
40
+ Defined in [`contracts/terminals.json`](../../contracts/terminals.json). G4 emits the critique
41
+ vocabulary. `SHIP WITH CHANGES` carries its changes forward to `polish`; it does not mean the
42
+ changes are optional.
43
+
44
+ ## When a stage's skill is not installed
45
+
46
+ Name the missing skill and skilldrop as its source, do the minimal inline version of that
47
+ stage, and say the stage ran degraded. Do not skip G4 — an unreviewed artifact is the failure
48
+ mode this wrapper exists to prevent.
49
+
50
+ ## Quality bar
51
+
52
+ - **The generator is chosen before intake runs.** A brief collected for no particular target is a summary, and downstream will reject it for missing fields.
53
+ - **`polish` runs after the argument is settled, never before.** Scrubbing prose that is about to be rewritten is wasted work and hides the rewrite.
54
+ - **A `[missing]` tag is resolved or stated, never silently filled.** Fabricating a goal, an owner, or a decision corrupts every downstream artifact.
55
+ - **Every run ends by naming what was not touched.** `output-hygiene`'s "Not touched" section is part of the deliverable, not an appendix.
56
+
57
+ ## Anti-patterns to avoid
58
+
59
+ - ❌ **Running `polish` as the whole review.** Clean prose with a broken argument still fails; that is what G4 is for.
60
+ - ❌ **Skipping `intake` because the input "is already structured."** A Slack thread that looks organized is still untagged — nobody downstream can tell what was inferred.
61
+ - ❌ **Looping `critique` → `draft` instead of `critique` → `intake`.** Re-drafting from the same incomplete brief reproduces the same gaps with new words.
62
+ - ❌ **Treating `WRONG ARTIFACT` as a severe `MAJOR REWRITE`.** It is a redirect: the user wanted a different document, and revising this one cannot get there.
@@ -0,0 +1,41 @@
1
+ {
2
+ "$comment": "RFC-0028. This wrapper is docs/knowledge-work-pipeline.mmd promoted from a hand-maintained diagram into the machine-readable source that diagram is now generated from. It is a wrapper, not a loop: the generator at its centre is chosen at run time from whichever artifact the user actually wants.",
3
+ "name": "ship-a-draft",
4
+ "version": "0.1.0",
5
+ "description": "Take raw mess to a stakeholder-ready artifact by wrapping any skilldrop generator in the two passes either side of it — structured intake before, critique and machine-residue scrub after. Use when the user has notes, a transcript, or a ticket and wants a finished document rather than a first draft.",
6
+ "entrypoint": "LOOP.md",
7
+ "kind": "wrapper",
8
+ "cap": 3,
9
+ "stages": [
10
+ {
11
+ "id": "intake",
12
+ "type": "generate",
13
+ "intent": "Collect the raw input once, into the shape the chosen generator expects, tagging every field explicit / implied / inferred / missing.",
14
+ "skills": ["brief-intake"]
15
+ },
16
+ {
17
+ "id": "draft",
18
+ "type": "generate",
19
+ "intent": "Run the generator the brief was shaped for. Any artifact skill is legal here — that choice is the wrapper's whole point.",
20
+ "skills": ["*"]
21
+ },
22
+ {
23
+ "id": "critique",
24
+ "type": "verify",
25
+ "intent": "Review the draft against the same rubric the generator was held to.",
26
+ "skills": ["doc-critique"],
27
+ "gate": {
28
+ "id": "G4",
29
+ "kind": "review",
30
+ "verdicts": ["SHIP IT", "SHIP WITH CHANGES", "MAJOR REWRITE", "WRONG ARTIFACT", "BLOCKED"],
31
+ "revise_to": "intake"
32
+ }
33
+ },
34
+ {
35
+ "id": "polish",
36
+ "type": "verify",
37
+ "intent": "Strip what the machine left behind before the artifact leaves the building. Surface pass only — never a substitute for the critique above.",
38
+ "skills": ["output-hygiene"]
39
+ }
40
+ ]
41
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "skilldrop-cli",
3
- "version": "0.11.5",
4
- "description": "Portable AI-agent skills for the deliverables knowledge workers ship — diagrams, ADRs, PRDs, runbooks, decks, reviews — installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
3
+ "version": "0.11.7",
4
+ "description": "Portable AI-agent skills for the deliverables knowledge workers ship \u2014 diagrams, ADRs, PRDs, runbooks, decks, reviews \u2014 installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
5
5
  "author": {
6
6
  "name": "Sanjay Ananthanarayan",
7
7
  "url": "https://github.com/sananthanarayan"
@@ -13,6 +13,8 @@
13
13
  "bin/",
14
14
  "skills/",
15
15
  "agents/",
16
+ "loops/",
17
+ "contracts/",
16
18
  "packs.json",
17
19
  "model-routing.json"
18
20
  ],
@@ -14,6 +14,9 @@
14
14
  "related": [
15
15
  "figma-diagrams"
16
16
  ],
17
+ "handoff": [
18
+ { "to": "figma-diagrams", "when": "the diagram needs to live where designers work", "purpose": "Push the rendered diagram into Figma.", "fallback": "If figma-diagrams is absent, leave the Mermaid source and say it needs manual import; never fabricate a Figma URL." }
19
+ ],
17
20
  "tags": [
18
21
  "diagrams",
19
22
  "mermaid",
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["feature-implement-loop", "postmortem-generator", "user-story-splitter"],
9
+ "handoff": [
10
+ { "to": "feature-implement-loop", "when": "the defect is reproduced and scoped", "purpose": "Fix the triaged defect through the same capped loop a story gets.", "fallback": "If feature-implement-loop is absent, fix inline with a regression test that fails before the fix." }
11
+ ],
9
12
  "tags": ["bug-triage", "bug-report", "ticket", "qa", "repro", "severity"],
10
13
  "model": { "tier": "standard", "rationale": "Extraction plus judgment calls (severity vs priority, hypothesis ranking) — same shape as brief-intake: above light, below heavy." }
11
14
  }
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["architecture-diagrams"],
9
+ "handoff": [
10
+ { "to": "architecture-diagrams", "when": "the design is written and needs rendering", "purpose": "Render the prose as a diagram that must not disagree with it.", "fallback": "If architecture-diagrams is absent, emit Mermaid inline and check every node against a claim in the doc." }
11
+ ],
9
12
  "tags": ["design-doc", "documentation", "engineering", "review"],
10
13
  "model": { "tier": "standard", "rationale": "Synthesizes a design doc from a brief. Escalates to opus on big or genuinely contested inputs." }
11
14
  }
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["design-doc", "devils-advocate", "doc-critique", "pre-merge-review"],
9
+ "handoff": [
10
+ { "to": "pre-merge-review", "when": "the code exists and the question is whether it can merge", "purpose": "Judge the diff that now exists against a mechanical gate.", "fallback": "If pre-merge-review is absent, run the repo's own lint and tests and honour the exit code; do not self-certify." }
11
+ ],
9
12
  "tags": ["dev-workflow", "implementation", "tdd", "acceptance-criteria", "adversarial", "self-correcting", "code-generation"],
10
13
  "model": { "tier": "standard", "rationale": "Code + test generation against acceptance criteria. The adversarial pass delegates to devils-advocate (heavy) where available; the loop itself is generation." }
11
14
  }
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["postmortem-generator", "runbook-generator"],
9
+ "handoff": [
10
+ { "to": "postmortem-generator", "when": "the incident is resolved", "purpose": "Analyse blamelessly and emit runbook deltas.", "fallback": "If postmortem-generator is absent, write the timeline, the contributing factors, and the procedural changes inline." }
11
+ ],
9
12
  "tags": ["incident", "communication", "status-page", "outage", "stakeholder", "sre"],
10
13
  "model": { "tier": "standard", "rationale": "Audience-segmented message generation under a strict don't-retract discipline. Same shape as exec-summary/audience-profile — translation and altitude, not adversarial reasoning." }
11
14
  }
@@ -6,6 +6,11 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["capacity-cost-model", "design-doc", "prd-draft", "test-plan-generator", "threat-model"],
9
+ "handoff": [
10
+ { "to": "design-doc", "when": "the quality targets are set", "purpose": "Design against the stated numbers rather than against taste.", "fallback": "If design-doc is absent, restate each target beside the design choice that serves it." },
11
+ { "to": "threat-model", "when": "the design has a trust boundary worth attacking", "purpose": "Attack the design before it is ratified.", "fallback": "If threat-model is absent, list the trust boundaries and one abuse case per boundary inline." },
12
+ { "to": "test-plan-generator", "when": "the targets need verifying, not just stating", "purpose": "Turn each quality target into a coverage entry.", "fallback": "If test-plan-generator is absent, name the test that would falsify each target." }
13
+ ],
9
14
  "tags": ["nfr", "requirements", "slo", "performance", "availability", "quality-attributes"],
10
15
  "model": { "tier": "standard", "rationale": "Rubric-driven sweep with archetype defaults; the judgment is calibrating targets to business reality. Bounded by the catalog; escalate via ambiguous-input on contested SLOs." }
11
16
  }
@@ -6,6 +6,10 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["capacity-cost-model", "incident-comms", "nfr-spec", "postmortem-generator", "runbook-generator", "success-metrics"],
9
+ "handoff": [
10
+ { "to": "runbook-generator", "when": "the alerts are defined and each needs a procedure", "purpose": "Write the procedure the on-call follows per alert.", "fallback": "If runbook-generator is absent, write one numbered procedure per alert inline." },
11
+ { "to": "incident-comms", "when": "detection fired and an audience needs telling", "purpose": "Communicate at the stage the incident is actually in.", "fallback": "If incident-comms is absent, state the stage, the impact, and the next update time inline." }
12
+ ],
9
13
  "tags": ["observability", "slo", "sli", "alerting", "monitoring", "sre"],
10
14
  "model": { "tier": "standard", "rationale": "Methodology synthesis against fixed SRE practices (golden signals, burn-rate alerting, pillar split). SLO calibration needs judgment but is bounded; escalate via ambiguous-input on contested reliability targets." }
11
15
  }
@@ -15,6 +15,9 @@
15
15
  "doc-critique",
16
16
  "ai-usage-policy"
17
17
  ],
18
+ "handoff": [
19
+ { "to": "doc-critique", "when": "the surface is clean and the draft is still weak", "purpose": "The fault is the argument, not the residue.", "fallback": "If doc-critique is absent, name the weakest claim and what evidence it needs." }
20
+ ],
18
21
  "tags": [
19
22
  "hygiene",
20
23
  "cleanup",
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["runbook-generator"],
9
+ "handoff": [
10
+ { "to": "runbook-generator", "when": "the postmortem produced runbook deltas", "purpose": "Apply the deltas as edits to the existing runbook.", "fallback": "If runbook-generator is absent, phrase each delta as a concrete before/after edit so a human can apply it." }
11
+ ],
9
12
  "tags": ["postmortem", "incident", "rca", "sre", "blameless", "outage"],
10
13
  "model": { "tier": "standard", "rationale": "Synthesizes a structured doc from incident notes. Contributing-factor chains need judgment but are bounded; escalate via large-input on huge scrollbacks." }
11
14
  }
@@ -6,6 +6,11 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["brief-intake", "bug-triage", "business-case", "design-doc", "nfr-spec", "success-metrics", "user-story-splitter"],
9
+ "handoff": [
10
+ { "to": "nfr-spec", "when": "the functional requirements are agreed", "purpose": "Set the quality targets the design will be judged against.", "fallback": "If nfr-spec is absent, state latency, availability and scale targets inline as numbers, not adjectives." },
11
+ { "to": "user-story-splitter", "when": "the requirements are ready to become units of work", "purpose": "Split into vertically-sliced stories with acceptance criteria.", "fallback": "If user-story-splitter is absent, slice inline and give each story acceptance criteria a test can assert." },
12
+ { "to": "design-doc", "when": "the what is agreed and the how is open", "purpose": "Design the system that satisfies these requirements.", "fallback": "If design-doc is absent, write the approach, the alternatives, and the trade-offs inline." }
13
+ ],
9
14
  "tags": ["prd", "requirements", "product", "discovery", "moscow", "non-goals"],
10
15
  "model": { "tier": "standard", "rationale": "Synthesizes a structured requirements doc from a brief. The solution-language discipline needs care; bounded by the template. Escalate via ambiguous-input on contested scope." }
11
16
  }
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["feature-implement-loop", "devils-advocate", "council-review", "doc-critique"],
9
+ "handoff": [
10
+ { "to": "council-review", "when": "the blocker is a design disagreement, not a defect", "purpose": "Adjudicate the disagreement outside the diff.", "fallback": "If council-review is absent, state each position and its strongest counter inline, and name the crux the decision turns on." }
11
+ ],
9
12
  "tags": ["dev-workflow", "code-review", "pre-merge", "quality-gate", "subagents", "production-readiness"],
10
13
  "model": { "tier": "standard", "rationale": "Coordination: runs a deterministic gate script, dispatches the (heavy) reviewer subagents, and renders a rule-based go/no-go. The adversarial reasoning is delegated to the panel, so the skill itself is orchestration, not deep judgment." }
11
14
  }
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["brief-intake", "decision-log", "prd-draft"],
9
+ "handoff": [
10
+ { "to": "brief-intake", "when": "the interview is done and the notes are raw", "purpose": "Collect the transcript into a tagged brief before any generator sees it.", "fallback": "If brief-intake is absent, tag each captured field [explicit]/[implied]/[inferred]/[missing] inline and say which downstream skill the brief is shaped for." }
11
+ ],
9
12
  "tags": ["discovery", "interviews", "requirements", "elicitation", "stakeholders", "user-research"],
10
13
  "model": { "tier": "standard", "rationale": "Question banks are rubric-shaped, but ranking by design impact and deriving falsification conditions for the specific feature is synthesis — above light." }
11
14
  }
@@ -6,6 +6,10 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["business-case", "okr-cascade", "prfaq", "tech-comparison-matrix"],
9
+ "handoff": [
10
+ { "to": "tech-comparison-matrix", "when": "the options are named and need comparing on stated criteria", "purpose": "Score the named options against weighted criteria.", "fallback": "If tech-comparison-matrix is absent, build a plain criteria-by-option table inline and state the weights." },
11
+ { "to": "business-case", "when": "the direction is chosen and needs costing before approval", "purpose": "Cost the chosen option against a do-nothing baseline.", "fallback": "If business-case is absent, state option 0 and the three cost layers (build, run, opportunity) inline." }
12
+ ],
9
13
  "tags": ["strategy", "swot", "tows", "five-forces", "pestle", "competitive-analysis", "market-analysis"],
10
14
  "model": { "tier": "heavy", "rationale": "Framework selection plus evidenced multi-factor judgment ending in a ranked, committal verdict. Cheaper models fill cells with generic filler, skip the TOWS crossings, and refuse to take a side. Never downgrade." }
11
15
  }
@@ -6,6 +6,10 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["architecture-diagrams", "prd-draft", "reverse-architecture", "success-metrics", "user-story-splitter"],
9
+ "handoff": [
10
+ { "to": "prd-draft", "when": "a friction point on the journey is worth fixing", "purpose": "Turn the named friction into numbered requirements.", "fallback": "If prd-draft is absent, write the requirements inline as numbered, testable statements and note that prd-draft in skilldrop would structure them." },
11
+ { "to": "success-metrics", "when": "the fix needs a measure before it is built", "purpose": "Design the measurement for the journey step being changed.", "fallback": "If success-metrics is absent, state one baseline and one target per fixed step inline." }
12
+ ],
9
13
  "tags": ["journey-map", "customer-experience", "ux", "touchpoints", "mermaid", "personas"],
10
14
  "model": { "tier": "standard", "rationale": "Structured synthesis into a fixed four-row stage model plus bounded ranking judgment. Escalate via ambiguous-input when the persona or outcome is contested or research inputs conflict." }
11
15
  }
@@ -6,6 +6,9 @@
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["feature-implement-loop"],
9
+ "handoff": [
10
+ { "to": "feature-implement-loop", "when": "a story has acceptance criteria a test can assert", "purpose": "Implement the slice through a capped generate-verify loop.", "fallback": "If feature-implement-loop is absent, implement inline but still challenge the result and cap the rounds at three." }
11
+ ],
9
12
  "tags": ["user-stories", "agile", "backlog", "acceptance-criteria", "planning", "sprint"],
10
13
  "model": { "tier": "standard", "rationale": "Decomposes an epic into INVEST slices with testable ACs. Structured synthesis; escalation rules cover large or contradictory PRDs." }
11
14
  }