task-pipeline-skill 0.12.0 → 1.0.0
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/CHANGELOG.md +477 -0
- package/LICENSE +47 -0
- package/README.md +369 -171
- package/cursor/rules/task-pipeline.mdc +125 -20
- package/package.json +8 -4
- package/plugins/task-pipeline/.claude-plugin/plugin.json +15 -4
- package/plugins/task-pipeline/commands/task-pipeline.md +20 -8
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +112 -39
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +35 -16
- package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +119 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +47 -14
- package/plugins/task-pipeline/skills/task-pipeline/references/brainstorm.md +108 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/build.md +365 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +72 -31
- package/plugins/task-pipeline/skills/task-pipeline/references/conventions.md +27 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/decomposition.md +139 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/grill.md +78 -7
- package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +159 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/loop-guard.md +100 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/planning.md +195 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/review.md +174 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +144 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +190 -35
- package/plugins/task-pipeline/skills/task-pipeline/references/tdd.md +110 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +5 -3
- package/plugins/task-pipeline/skills/task-pipeline/templates/brief.md +50 -2
- package/plugins/task-pipeline/skills/task-pipeline/templates/carryover.md +36 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Decomposition — cutting a platform into bricks
|
|
2
|
+
|
|
3
|
+
A one-feature task goes through the pipeline once. A **platform** — anything whose
|
|
4
|
+
brief describes more than one deliverable, more than one surface, or a system
|
|
5
|
+
rather than a change — must be cut into modules first, and then built one brick at
|
|
6
|
+
a time, each brick carrying its own documentation, spec, plan, build and gates.
|
|
7
|
+
|
|
8
|
+
This runs at the end of **stage 2**, on the approved design, before any spec is
|
|
9
|
+
written. It is skipped — explicitly, in writing — when the work is a single module.
|
|
10
|
+
|
|
11
|
+
## When it applies
|
|
12
|
+
|
|
13
|
+
Decompose when any of these is true:
|
|
14
|
+
|
|
15
|
+
- the brief names several independent capabilities ("accounts, billing, reporting");
|
|
16
|
+
- the work spans several surfaces (API + web + worker) that could ship separately;
|
|
17
|
+
- the REQ table has requirements that no single deliverable satisfies together;
|
|
18
|
+
- the design's units have their own data and could plausibly be owned by different
|
|
19
|
+
people.
|
|
20
|
+
|
|
21
|
+
Otherwise record one line in the design — `single module: <name>` — and go to
|
|
22
|
+
stage 3. A skipped decomposition is a decision, never an omission.
|
|
23
|
+
|
|
24
|
+
## How to cut
|
|
25
|
+
|
|
26
|
+
**By capability, not by layer.** "Ordering", "Billing", "Notifications" are
|
|
27
|
+
modules. "Controllers", "Services", "Database" are not: a layer cut forces every
|
|
28
|
+
feature to touch every module, which is the opposite of a brick.
|
|
29
|
+
|
|
30
|
+
A module is a **brick** when all of these hold:
|
|
31
|
+
|
|
32
|
+
1. **Independently specifiable** — you can write its dossier without deciding
|
|
33
|
+
another module's internals.
|
|
34
|
+
2. **Independently buildable and testable** — its tests pass without another
|
|
35
|
+
module's implementation present (stubs at the contract are fine).
|
|
36
|
+
3. **Owns its data** — the entities it is the source of truth for belong to it, and
|
|
37
|
+
nothing else writes them.
|
|
38
|
+
4. **Talks through declared contracts only** — every cross-module interaction is a
|
|
39
|
+
named API, event or schema, listed in both modules' dossiers.
|
|
40
|
+
5. **Deliverable on its own** — landing it leaves the system working, even if the
|
|
41
|
+
capability is not yet reachable by users.
|
|
42
|
+
|
|
43
|
+
If a candidate fails (2) or (3), the cut is in the wrong place: either merge it
|
|
44
|
+
into its neighbor or move the disputed data to the module that truly owns it.
|
|
45
|
+
|
|
46
|
+
**Order the bricks:**
|
|
47
|
+
|
|
48
|
+
- **The walking skeleton first.** The first module is the thinnest end-to-end slice
|
|
49
|
+
that proves the architecture — one real path through the system, however small.
|
|
50
|
+
Building three "foundation" modules before anything runs end-to-end hides
|
|
51
|
+
integration risk until the worst possible moment.
|
|
52
|
+
- Then topological order: nothing is built before what it depends on.
|
|
53
|
+
- **No cycles.** A cycle means the cut is wrong. Break it by moving the shared
|
|
54
|
+
concept into its own module, or by turning one direction of the dependency into
|
|
55
|
+
an event the other module subscribes to. Record which you chose and why.
|
|
56
|
+
|
|
57
|
+
## The module map — the artifact
|
|
58
|
+
|
|
59
|
+
Write `docs/superpowers/specs/YYYY-MM-DD-<topic>-modules.md` and commit it. It is
|
|
60
|
+
the program's spine: every later run reads it, and its status column is how a
|
|
61
|
+
resumed session knows where the program stopped.
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
# Module map — <platform>
|
|
65
|
+
|
|
66
|
+
Build order is top to bottom. Status: `planned` → `in progress` → `done` |
|
|
67
|
+
`deferred`. One row per module, no exceptions.
|
|
68
|
+
|
|
69
|
+
| # | Module | Delivers | Owns (entities) | Depends on | Contracts exposed | UI? | REQs | Status |
|
|
70
|
+
|---|---|---|---|---|---|---|---|---|
|
|
71
|
+
| 1 | ordering | place and track an order | Order, OrderLine | — | `POST /orders`, `OrderPlaced` event | yes | REQ-001, REQ-004 | planned |
|
|
72
|
+
| 2 | billing | charge for a placed order | Invoice, Payment | ordering | `InvoiceIssued` event | no | REQ-002 | planned |
|
|
73
|
+
|
|
74
|
+
## Cut rationale
|
|
75
|
+
|
|
76
|
+
<why these seams and not others; what was merged or split, and what a cycle forced>
|
|
77
|
+
|
|
78
|
+
## Cross-module contracts
|
|
79
|
+
|
|
80
|
+
<one block per contract: owner module, consumer(s), exact shape (schema or
|
|
81
|
+
signature), and the failure behavior when the other side is unavailable>
|
|
82
|
+
|
|
83
|
+
## Deferred to later modules
|
|
84
|
+
|
|
85
|
+
<capabilities deliberately postponed, with the module that will carry them>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Every REQ from the brief appears in exactly one module's `REQs` cell. A REQ that
|
|
89
|
+
fits nowhere means the map is incomplete; a REQ in two modules means the seam runs
|
|
90
|
+
through a requirement — re-cut or split the REQ.
|
|
91
|
+
|
|
92
|
+
## GATE (part of stage 2, manual)
|
|
93
|
+
|
|
94
|
+
Together with the design approval:
|
|
95
|
+
|
|
96
|
+
1. Every module satisfies the brick criteria, or its exception is written down.
|
|
97
|
+
2. The dependency graph is acyclic and the build order is topological.
|
|
98
|
+
3. The first module is a walking skeleton, or the reason it isn't is recorded.
|
|
99
|
+
4. Every REQ maps to exactly one module.
|
|
100
|
+
5. Cross-module contracts are named (shape can be locked later, in each module's
|
|
101
|
+
spec — but the *existence* and *owner* of each contract is decided here).
|
|
102
|
+
6. The operator approves the map and the order.
|
|
103
|
+
|
|
104
|
+
## The program loop — one brick at a time
|
|
105
|
+
|
|
106
|
+
After the map is approved, the pipeline runs **per module**, in build order:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
module N → stage 3 (dossier/spec) → 4 plan → 5 build → 6 tests
|
|
110
|
+
→ 7 lint + deploy → 8 post-deploy → 9 docs + wiki → 10 acceptance
|
|
111
|
+
→ mark module done → module N+1 (back to stage 3)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Rules for the loop:
|
|
115
|
+
|
|
116
|
+
- **Stages 0–2 run once for the platform.** Modules do not re-grill and do not
|
|
117
|
+
re-decompose. New information that changes the map goes back to stage 2
|
|
118
|
+
deliberately, as a map revision with the operator's approval — not as a quiet
|
|
119
|
+
edit mid-module.
|
|
120
|
+
- **Each module's spec is a full dossier** ([`spec.md`](spec.md)): architecture,
|
|
121
|
+
entities, contracts in and out, business rules, edge and failure cases, UI/Figma
|
|
122
|
+
chain when it has a surface.
|
|
123
|
+
- **The contract is the boundary.** A module may stub what a later module will
|
|
124
|
+
provide, but it may not reach into another module's internals; if it needs to,
|
|
125
|
+
the seam is wrong — back to the map.
|
|
126
|
+
- **Deploy cadence is the brief's call** (autonomy sweep): deploy each module as it
|
|
127
|
+
lands, or build several and deploy once. Record it; don't decide it per module.
|
|
128
|
+
- **Update the map's status column as each module closes**, in the same commit as
|
|
129
|
+
that module's acceptance. The map is the resume point after a lost context.
|
|
130
|
+
- **Loop discipline:** a module re-entering the same stage a third time trips the
|
|
131
|
+
loop guard ([`loop-guard.md`](loop-guard.md)) — stop, name the oscillation, and
|
|
132
|
+
fix the layer that owns it instead of iterating.
|
|
133
|
+
|
|
134
|
+
## Program done
|
|
135
|
+
|
|
136
|
+
The program is finished when every row is `done` or `deferred` with an agreed home,
|
|
137
|
+
the cross-module contracts are exercised by tests that cross the seam (not just
|
|
138
|
+
per-module unit tests), and the final acceptance covers the platform's REQ table as
|
|
139
|
+
a whole — not module by module.
|
|
@@ -4,7 +4,7 @@ The intake grill is **part of this skill**. No companion skill to install, no
|
|
|
4
4
|
provider to resolve, nothing to fall back to: this file *is* the implementation.
|
|
5
5
|
|
|
6
6
|
Its job is not to design. It is to take a one-line request ("make me feature X")
|
|
7
|
-
and interview it into a brief complete enough that stages 1→
|
|
7
|
+
and interview it into a brief complete enough that stages 1→10 finish without
|
|
8
8
|
coming back to the operator.
|
|
9
9
|
|
|
10
10
|
> Adapted, with thanks, from Matt Pocock's `grilling` / `grill-with-docs` skills
|
|
@@ -12,7 +12,27 @@ coming back to the operator.
|
|
|
12
12
|
> half — glossary challenges, `CONTEXT.md`, ADR discipline — comes from there; the
|
|
13
13
|
> autonomy sweep and the brief are this pipeline's.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Phase 1 — harvest before you ask
|
|
16
|
+
|
|
17
|
+
**Do not open the interview cold.** Stage 0 begins by finding what the project
|
|
18
|
+
already knows about this task: the code, `CLAUDE.md`, `CONTEXT.md` and the ADRs,
|
|
19
|
+
`docs/` and `docs/ux/`, past pipeline briefs, the **knowledge wiki** when one is
|
|
20
|
+
installed, and any **other repository or hosted doc system the project names as
|
|
21
|
+
its docs**. Full procedure, source order, the wiki's detection and install line,
|
|
22
|
+
and the ledger to write: [`knowledge-sources.md`](knowledge-sources.md).
|
|
23
|
+
|
|
24
|
+
Two things come out of it, both required before question one:
|
|
25
|
+
|
|
26
|
+
- the **source ledger** in the brief — one row per source consulted, what it says
|
|
27
|
+
about this task, and how fresh it is (`no sources found` is a valid row);
|
|
28
|
+
- the list of things you therefore **don't need to ask**, and the specific points
|
|
29
|
+
where a source looks stale or ambiguous — those become the sharpest questions.
|
|
30
|
+
|
|
31
|
+
Everything below runs against that harvest. An answer you can't check against a
|
|
32
|
+
source is a recollection, and the whole loop exists to stop the run from building
|
|
33
|
+
on one.
|
|
34
|
+
|
|
35
|
+
## Phase 2 — the loop
|
|
16
36
|
|
|
17
37
|
Interview the operator relentlessly about every aspect of the task until you reach
|
|
18
38
|
a **shared understanding**. Walk down each branch of the decision tree, resolving
|
|
@@ -73,6 +93,15 @@ Create these files **lazily** — only when you have something real to write.
|
|
|
73
93
|
check whether the code agrees, and surface contradictions: *"Your code cancels
|
|
74
94
|
entire Orders, but you just said partial cancellation is possible — which is
|
|
75
95
|
right?"*
|
|
96
|
+
- **Cross-reference with the harvest — every answer, not just the domain ones.**
|
|
97
|
+
Phase 1 put the ADRs, runbooks and wiki pages in your hands; use them the same
|
|
98
|
+
way: *"The March ADR says orders are written only through the command handler,
|
|
99
|
+
you just described a direct write — has that changed?"* The operator **outranks
|
|
100
|
+
every document**, but only out loud: an override quoted against its source is a
|
|
101
|
+
recorded decision, an unquoted one is an undetected divergence. When two sources
|
|
102
|
+
disagree, precedence is code > host docs/ADRs > wiki > memory, and the loser is
|
|
103
|
+
logged for the stage-9 update ([`knowledge-sources.md`](knowledge-sources.md) →
|
|
104
|
+
*Phase 2*).
|
|
76
105
|
- **Update `CONTEXT.md` inline.** Resolve a term → write it down right then, not in
|
|
77
106
|
a batch at the end. Format: [`templates/context.md`](../templates/context.md).
|
|
78
107
|
Keep it free of implementation detail — only terms a domain expert would
|
|
@@ -95,19 +124,23 @@ numbering (scan for the highest number, increment).
|
|
|
95
124
|
## The autonomy sweep
|
|
96
125
|
|
|
97
126
|
Resolving the *task* is not enough. The grill must also pre-resolve everything that
|
|
98
|
-
would otherwise stop stages 1→
|
|
127
|
+
would otherwise stop stages 1→10 mid-flight. Every row gets an answer **or** an
|
|
99
128
|
explicit "stop and ask me here":
|
|
100
129
|
|
|
101
130
|
| Stage | What to settle up front |
|
|
102
131
|
|---|---|
|
|
103
132
|
| run-wide | the model decision ([`model-tiering.md`](model-tiering.md)); what to decide autonomously vs escalate |
|
|
133
|
+
| 0 Harvest | doc sources beyond this repo — other repos, hosted doc systems, the knowledge wiki — and whether stage 9 may write to them (another repo is outward: propose + PR, never a direct push) |
|
|
104
134
|
| 1 Docs | external libs/APIs/SDKs in play; any private ones context7 can't resolve → where their docs live |
|
|
135
|
+
| 2 Decompose | is this a platform (several capabilities/surfaces) or one module? if platform: deploy cadence — per module or once at the end |
|
|
105
136
|
| 2–3 Spec | UI verdict (arms super-ux); any scenario-tracing waiver |
|
|
106
137
|
| 4–5 Dev | base branch; worktree/branch policy; is `main` off-limits; commit convention; task tracker |
|
|
138
|
+
| 5 Integration | how the branch lands (merge / PR + approver / "leave it unmerged"); parallel fan-out wanted (one worktree per implementer)? |
|
|
107
139
|
| 6 Tests | the test command; what "green" means here; known-red baseline; coverage expectation |
|
|
108
140
|
| 7 Lint+deploy | lint command; deploy target and path; release automation on/off; deploy-from-main rule; **deploy authorization** |
|
|
109
141
|
| 8 Post-deploy | where logs / health live (app name, endpoint, workflow) |
|
|
110
142
|
| 9 Docs+wiki | which module docs / runbooks this change updates; wiki sync yes/no |
|
|
143
|
+
| 10 Acceptance | who signs off; where deferred REQs are tracked (issue tracker, backlog) |
|
|
111
144
|
|
|
112
145
|
**Deploy authorization has a hard floor.** Deploy and publish are outward and
|
|
113
146
|
irreversible, so a vague "just do everything" authorizes nothing. A standing
|
|
@@ -116,14 +149,52 @@ preconditions ("staging once lint and the full suite are green; production alway
|
|
|
116
149
|
asks"). Specific and recorded → it satisfies the stage-7 manual gate. Broader,
|
|
117
150
|
absent or ambiguous → stage 7 stops and asks.
|
|
118
151
|
|
|
152
|
+
## The REQ spine — the grill's other hard output
|
|
153
|
+
|
|
154
|
+
Prose scope is not checkable. Before the brief is confirmed, the grill must turn
|
|
155
|
+
what was asked into an **addressable list of requirements**, because every later
|
|
156
|
+
stage traces to these IDs and stage 10 accounts for every one of them.
|
|
157
|
+
|
|
158
|
+
| ID | Requirement | How it's verified | Status |
|
|
159
|
+
|---|---|---|---|
|
|
160
|
+
| REQ-001 | … | test name / `file:line` / command + expected output / `SCN-…` | open |
|
|
161
|
+
|
|
162
|
+
Three rules that decide whether the spine is worth anything:
|
|
163
|
+
|
|
164
|
+
1. **One REQ = one independently verifiable deliverable.** Not one per sentence of
|
|
165
|
+
the request. A small task gets three rows, not thirty — an inflated table is
|
|
166
|
+
ignored, and an ignored table protects nothing.
|
|
167
|
+
2. **Every row names its check.** *A requirement you can't say how to verify is a
|
|
168
|
+
badly-stated requirement* — split or sharpen it here, during the grill. This is
|
|
169
|
+
the single defence against the failure mode where three vague REQs cover a large
|
|
170
|
+
task and acceptance goes green over half of it.
|
|
171
|
+
3. **Ask what "finished" means per row, not for the task overall.** "Export works"
|
|
172
|
+
hides five decisions; "exports the currently filtered rows as CSV, verified by
|
|
173
|
+
`test_export_respects_filters`" hides none.
|
|
174
|
+
|
|
175
|
+
**Then freeze it.** Adding a requirement mid-run is fine — append with its source.
|
|
176
|
+
**Removing or narrowing one requires the operator's explicit agreement**, recorded
|
|
177
|
+
in the carry-over ledger. Quietly restating the task in smaller terms is the
|
|
178
|
+
subtlest way to lose it: every gate downstream then passes honestly, on a task
|
|
179
|
+
that shrank without anyone deciding it should.
|
|
180
|
+
|
|
119
181
|
## Output
|
|
120
182
|
|
|
121
183
|
Everything resolved goes into the **task brief**, seeded from
|
|
122
184
|
[`templates/brief.md`](../templates/brief.md) and committed to
|
|
123
|
-
`docs/superpowers/specs/YYYY-MM-DD-<topic>-brief.md` — scope,
|
|
124
|
-
|
|
125
|
-
assumptions. Seed the template only when
|
|
126
|
-
existing brief.
|
|
185
|
+
`docs/superpowers/specs/YYYY-MM-DD-<topic>-brief.md` — scope, **the REQ table**,
|
|
186
|
+
**the phase-1 source ledger**, users, UI verdict, constraints, locked decisions,
|
|
187
|
+
the autonomy table, done-criteria, open assumptions. Seed the template only when
|
|
188
|
+
the file is absent; never overwrite an existing brief.
|
|
189
|
+
|
|
190
|
+
The ledger is not decoration: **stage 9 updates exactly what stage 0 read**, and
|
|
191
|
+
every doc the grill proved stale is already listed there with what's wrong.
|
|
192
|
+
|
|
193
|
+
Alongside it, seed the **carry-over ledger** from
|
|
194
|
+
[`templates/carryover.md`](../templates/carryover.md) at
|
|
195
|
+
`…-carryover.md` — append-only, written by every later stage, read in full by
|
|
196
|
+
stage 10. Anything deferred, dropped, or half-done from here on goes there the
|
|
197
|
+
moment it's said: **deferred out loud is forgotten.**
|
|
127
198
|
|
|
128
199
|
Plus, where the session produced them: an updated `CONTEXT.md` and any ADRs, each
|
|
129
200
|
written as the decision landed.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Knowledge sources — harvest before the grill, update after the build
|
|
2
|
+
|
|
3
|
+
Stage 0 has two phases. This file is **phase 1**: before the first question is
|
|
4
|
+
asked, find and read what the project already knows about this task. The interview
|
|
5
|
+
([`grill.md`](grill.md)) is phase 2, and it runs *against* what was harvested here.
|
|
6
|
+
|
|
7
|
+
The same source list closes the loop at **stage 9**: what was read at the start is
|
|
8
|
+
what gets updated at the end. A source good enough to answer a question is a source
|
|
9
|
+
that goes stale when the answer changes.
|
|
10
|
+
|
|
11
|
+
## Why this is a phase and not "explore a bit first"
|
|
12
|
+
|
|
13
|
+
An agent that starts asking without harvesting spends the operator's turns on
|
|
14
|
+
questions the project already answered — in an ADR, in a runbook, in a wiki page
|
|
15
|
+
written three months ago by the same person now being asked. That is the expensive
|
|
16
|
+
failure, but not the worst one.
|
|
17
|
+
|
|
18
|
+
The worst one is silent: **the operator misremembers, the agent believes them, and
|
|
19
|
+
the run builds on it.** People answer from memory about systems they wrote a year
|
|
20
|
+
ago. Without the documents in hand you cannot tell a decision from a recollection,
|
|
21
|
+
so every later gate passes honestly on a false premise. Harvesting first is what
|
|
22
|
+
makes the grill's answers *checkable* instead of merely confident.
|
|
23
|
+
|
|
24
|
+
## The sources, in the order to try them
|
|
25
|
+
|
|
26
|
+
| # | Source | How to find it | What it's good for |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| 1 | **The code** | the repo you're in | what actually runs — the tiebreaker |
|
|
29
|
+
| 2 | **Host agent docs** | `CLAUDE.md`, `AGENTS.md`, `.cursor/rules/` | conventions, commands, deploy path, house rules |
|
|
30
|
+
| 3 | **Domain docs** | `CONTEXT.md` / `CONTEXT-MAP.md`, `docs/adr/` | the glossary and the decisions with their reasons |
|
|
31
|
+
| 4 | **Product/UX docs** | `docs/ux/` (super-ux chain), `README`, runbooks | user-facing behavior that is already specified |
|
|
32
|
+
| 5 | **Pipeline history** | `docs/superpowers/specs/`, `plans/`, past `-carryover.md` | what a previous run of this pipeline decided or deferred |
|
|
33
|
+
| 6 | **The knowledge wiki** | see below | distilled cross-project knowledge, prior sessions, why decisions were made |
|
|
34
|
+
| 7 | **Other doc repos the project names** | a docs repo URL or submodule in `CLAUDE.md`/`README`, a sibling checkout, a `docs/` monorepo package | specs, contracts and runbooks that live outside this repo |
|
|
35
|
+
| 8 | **Hosted doc systems the project names** | Notion / Confluence / Google Docs referenced in the project | the same, when the team keeps them there |
|
|
36
|
+
|
|
37
|
+
Rules for the list:
|
|
38
|
+
|
|
39
|
+
- **Never invent a source.** A doc repo is in scope because the project names it,
|
|
40
|
+
not because it plausibly exists. Nothing is cloned or fetched on a guess.
|
|
41
|
+
- **Sources 7–8 are read-only at this stage**, and reading a hosted system needs a
|
|
42
|
+
connected tool — if there's no tool, record the gap and ask the operator to paste
|
|
43
|
+
what matters rather than pretending the source was covered.
|
|
44
|
+
- **The wiki is optional; the harvest is not.** With no wiki and no doc repos, the
|
|
45
|
+
harvest is sources 1–5 and takes two minutes. Skipping it is never the answer.
|
|
46
|
+
|
|
47
|
+
## The knowledge wiki — recommended
|
|
48
|
+
|
|
49
|
+
The wiki this pipeline is built to work with is
|
|
50
|
+
**[obsidian-wiki](https://github.com/ar9av/obsidian-wiki)** (Karpathy's LLM-wiki
|
|
51
|
+
pattern: raw sources → distilled wiki → schema). It is the one source that carries
|
|
52
|
+
*why* across projects and across months, which is exactly what a fresh context lacks.
|
|
53
|
+
|
|
54
|
+
**Detect it** — any of: `~/.obsidian-wiki/config` exists; the `wiki-query` /
|
|
55
|
+
`wiki-update` skills resolve.
|
|
56
|
+
|
|
57
|
+
- **Installed → use it.** Query it during the harvest (`wiki-query`, or the vault's
|
|
58
|
+
`index.md` + a targeted grep when the skill isn't loaded), and sync back at stage
|
|
59
|
+
9 (`wiki-update`).
|
|
60
|
+
- **Not installed → recommend it once, in the preflight block, with the line:**
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
pip install obsidian-wiki
|
|
64
|
+
obsidian-wiki setup --vault /path/to/your/vault
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Then continue without it. It is a **recommendation, never a gate** — no stage
|
|
68
|
+
blocks on a missing wiki, and the pipeline never nags twice in a run.
|
|
69
|
+
|
|
70
|
+
## How to harvest — retrieval, not reading
|
|
71
|
+
|
|
72
|
+
The harvest is bounded by the *task*, not by the size of the sources. You are not
|
|
73
|
+
reading the wiki; you are asking it about this task.
|
|
74
|
+
|
|
75
|
+
1. **Take the task's nouns** — the entities, the feature name, the subsystem, the
|
|
76
|
+
file paths the operator mentioned — plus their obvious synonyms.
|
|
77
|
+
2. **Query each source with those terms**: `wiki-query` for the wiki; `grep`/`Read`
|
|
78
|
+
for repo docs; the tracker/hosted-doc tool if one is connected.
|
|
79
|
+
3. **Follow one hop, not ten.** A hit that names an ADR, a scenario id or a module
|
|
80
|
+
is worth opening. A page three links away is context, not evidence.
|
|
81
|
+
4. **Stop when the terms stop returning anything new.** Same rule as the interview:
|
|
82
|
+
no grinding past diminishing returns.
|
|
83
|
+
|
|
84
|
+
## Record it — the source ledger
|
|
85
|
+
|
|
86
|
+
Write what you found into the brief's **Knowledge sources** section
|
|
87
|
+
([`templates/brief.md`](../templates/brief.md)) before the first question. One row
|
|
88
|
+
per source actually consulted:
|
|
89
|
+
|
|
90
|
+
| Source | What it says about this task | Fresh? | Authority |
|
|
91
|
+
|---|---|---|---|
|
|
92
|
+
| `docs/adr/0007-single-write-model.md` | orders are written only through the command handler | 2026-03 | decision |
|
|
93
|
+
| wiki: `projects/x/concepts/billing-seams` | why invoicing was split out; the retry rule | 2026-06 | context |
|
|
94
|
+
| `CLAUDE.md` | test = `npm test`, deploy from `main` only | current | convention |
|
|
95
|
+
| (none for the export UI) | — | — | — |
|
|
96
|
+
|
|
97
|
+
The ledger is what makes phase 2 work: during the interview you cite rows from it,
|
|
98
|
+
and at stage 9 you update the same rows. A source consulted but not recorded is a
|
|
99
|
+
source nobody will update.
|
|
100
|
+
|
|
101
|
+
**"No sources found" is a valid, recorded outcome.** Write the row. An empty ledger
|
|
102
|
+
tells the next run that the search happened and came back empty — silence doesn't.
|
|
103
|
+
|
|
104
|
+
## Phase 2 — validate the answers against the harvest
|
|
105
|
+
|
|
106
|
+
This is the payoff, and it belongs to the grill loop
|
|
107
|
+
([`grill.md`](grill.md) → *Domain awareness*). Every operator answer that touches a
|
|
108
|
+
harvested source gets checked against it, on the spot:
|
|
109
|
+
|
|
110
|
+
> "The ADR from March says orders are written only through the command handler —
|
|
111
|
+
> you just described a direct write. Has that changed, or should the export go
|
|
112
|
+
> through the handler?"
|
|
113
|
+
|
|
114
|
+
Three shapes and what to do with each:
|
|
115
|
+
|
|
116
|
+
| The answer… | Do |
|
|
117
|
+
|---|---|
|
|
118
|
+
| **agrees** with the source | nothing — note it, move on |
|
|
119
|
+
| **contradicts** a source | quote the source, name the conflict, ask which governs. The answer is either "the doc is stale" (→ it gets updated at stage 9, log it now) or "I misremembered" (→ the doc stands). Both are cheap here and expensive at stage 6 |
|
|
120
|
+
| **goes beyond** every source | this is new knowledge — it belongs in the brief, and usually in `CONTEXT.md` or an ADR as it lands |
|
|
121
|
+
|
|
122
|
+
**The operator outranks the docs — but only out loud.** A person may overrule any
|
|
123
|
+
document; they may not do it by accident. The point of quoting the source is that
|
|
124
|
+
the override becomes a recorded decision instead of an undetected divergence.
|
|
125
|
+
|
|
126
|
+
**Precedence when two sources disagree with each other:** code > host docs and
|
|
127
|
+
ADRs > the wiki > anyone's memory. The wiki is *distilled* knowledge and can lag
|
|
128
|
+
the repo by months; the code is what runs. A disagreement between them is a grill
|
|
129
|
+
question, never a silent pick — and it is usually a sign the doc is due an update.
|
|
130
|
+
|
|
131
|
+
## Close the loop — stage 9 updates what stage 0 read
|
|
132
|
+
|
|
133
|
+
The ledger is the stage-9 work list. For each row:
|
|
134
|
+
|
|
135
|
+
- **Host repo docs, ADRs, runbooks, `docs/ux/`** — updated in the **same change**,
|
|
136
|
+
per the host's own rules ([`conventions.md`](conventions.md)).
|
|
137
|
+
- **Anything the run proved stale** — including a doc that was "wrong but nobody
|
|
138
|
+
had time": that's why the conflict was logged in phase 2 instead of only being
|
|
139
|
+
resolved verbally.
|
|
140
|
+
- **The wiki** — `wiki-update` syncs what this run learned. Distil the *knowledge*
|
|
141
|
+
(decisions, seams, gotchas, why), never a diff summary.
|
|
142
|
+
- **Another repository's docs** — writing to a repo the operator didn't ask you to
|
|
143
|
+
touch is **outward**: propose the change, get an explicit go, then open a PR
|
|
144
|
+
there. Absent a go, it goes in the carry-over ledger with the exact edit needed.
|
|
145
|
+
|
|
146
|
+
A source that was worth reading at stage 0 and is wrong at stage 9 is the next
|
|
147
|
+
run's false premise. Closing that loop is the whole point of harvesting from a
|
|
148
|
+
written list instead of from whatever the search happened to surface.
|
|
149
|
+
|
|
150
|
+
## Rationalizations
|
|
151
|
+
|
|
152
|
+
| Excuse | Reality |
|
|
153
|
+
|---|---|
|
|
154
|
+
| "I'll just ask them, it's faster" | You'll ask about things a doc already answers, and you'll believe an answer you can't check. Retrieval is cheaper than a turn. |
|
|
155
|
+
| "The wiki's probably stale" | Then say so with the page in hand and get it corrected. "Probably stale" unread is an assumption; read, it's a finding. |
|
|
156
|
+
| "No docs in this repo" | Check `CLAUDE.md` for the repo that has them, and the wiki for the last time anyone touched this. Then record the empty ledger. |
|
|
157
|
+
| "The operator knows their own system" | They do — a year ago, before three other people changed it. That's the exact case where quoting the doc pays. |
|
|
158
|
+
| "Reading the whole wiki costs too much" | The harvest is a query per task noun, not a read. If it feels expensive, you're reading instead of retrieving. |
|
|
159
|
+
| "I'll update the docs at the end from memory" | The ledger exists because the end is exactly when you no longer remember which sources you leaned on. |
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Loop guard — breaking churn, cross-cutting
|
|
2
|
+
|
|
3
|
+
Any stage that can repeat can also **churn**: a later pass undoing what an earlier
|
|
4
|
+
pass in the same run already did, two shapes alternating, the same file rewritten
|
|
5
|
+
round after round with no new information. Churn looks like progress and consumes
|
|
6
|
+
a run.
|
|
7
|
+
|
|
8
|
+
This file is the detector and the break protocol. It binds every repeating loop in
|
|
9
|
+
the pipeline: the stage-5 fix loop, a stage re-entered after a failed gate, the
|
|
10
|
+
per-module program loop ([`decomposition.md`](decomposition.md)), and any
|
|
11
|
+
audit → fix → audit cycle.
|
|
12
|
+
|
|
13
|
+
## Bookkeeping — the thing that makes detection mechanical
|
|
14
|
+
|
|
15
|
+
You cannot detect churn from memory, especially after compaction. Every repeating
|
|
16
|
+
pass appends one line to the run's ledger (`.task-pipeline/build/<plan>/progress.md`
|
|
17
|
+
for stage 5; `.task-pipeline/run.md` for stage-level and program-level loops):
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
touch: <file> — pass <N> (<stage|round|module>) — reason: <finding id / gate item>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
One line per file per pass. The reason must name **what forced the edit** — a
|
|
24
|
+
finding id, a failed gate item, an operator instruction. "Cleanup", "polish" and
|
|
25
|
+
"while I was there" are not reasons; they are churn with better manners.
|
|
26
|
+
|
|
27
|
+
## Detection — any one of these trips the guard
|
|
28
|
+
|
|
29
|
+
1. **Revert-oscillation.** An edit restores something an earlier pass in this run
|
|
30
|
+
deliberately removed, or re-removes what an earlier pass added. Shape A → B → A.
|
|
31
|
+
2. **Repeat touch without new information.** The same file is edited in two
|
|
32
|
+
consecutive passes and the second pass's `reason` is the same finding/gate item
|
|
33
|
+
as the first — the fix did not fix it, or the two passes disagree about what
|
|
34
|
+
"fixed" means.
|
|
35
|
+
3. **Finding resurrection.** A finding whose text (normalized) matches one already
|
|
36
|
+
marked ADDRESSED or parked-with-ruling in this run comes back.
|
|
37
|
+
4. **Gate ping-pong.** The same stage is re-entered for the third time on the same
|
|
38
|
+
artifact, or two adjacent stages hand work back and forth (spec ⇄ plan,
|
|
39
|
+
plan ⇄ build) more than twice.
|
|
40
|
+
5. **Cross-loop contradiction.** A pass in one loop edits a file that a *different*
|
|
41
|
+
loop (another task, another module) already closed in this run — two owners for
|
|
42
|
+
one file.
|
|
43
|
+
|
|
44
|
+
Caps that trip the guard by themselves: **5 fix rounds** per task
|
|
45
|
+
([`build.md`](build.md)), **2 re-entries** per stage per artifact, **3 passes** per
|
|
46
|
+
module in the program loop.
|
|
47
|
+
|
|
48
|
+
## The break protocol
|
|
49
|
+
|
|
50
|
+
When the guard trips, **stop editing immediately**. Do not dispatch another fix, do
|
|
51
|
+
not "just try one more thing". Then, in this order:
|
|
52
|
+
|
|
53
|
+
1. **Freeze and name it.** Write the oscillation down in the ledger and to the
|
|
54
|
+
operator: shape **A** vs shape **B**, one line each, plus who is asking for each
|
|
55
|
+
(a finding, the plan's text, the spec, a gate check, an operator instruction) and
|
|
56
|
+
the evidence for each — `file:line`, the failing command, the review verdict.
|
|
57
|
+
2. **Find the layer that owns the conflict.** Churn almost always means a decision
|
|
58
|
+
is being re-litigated at the wrong altitude:
|
|
59
|
+
- two findings disagree → the **review rubric** decides
|
|
60
|
+
([`review.md`](review.md)); if it genuinely doesn't, it's a spec question;
|
|
61
|
+
- a finding contradicts the plan → the **operator** decides which governs
|
|
62
|
+
(never dismiss the finding, never fix against the plan silently);
|
|
63
|
+
- the plan contradicts the spec → back to **stage 4** with the evidence;
|
|
64
|
+
- the spec is ambiguous or wrong → back to **stage 3**, and if the ambiguity was
|
|
65
|
+
an unresolved intake question, say so — that is a stage-0 miss worth recording;
|
|
66
|
+
- two modules claim the same file or entity → back to **decomposition**: the cut
|
|
67
|
+
is wrong.
|
|
68
|
+
**Never resolve a higher-layer conflict inside a lower loop.** Patching code to
|
|
69
|
+
satisfy two contradictory requirements is how a run burns its remaining budget.
|
|
70
|
+
3. **Re-plan the check.** Replace whatever ad-hoc verification was running with an
|
|
71
|
+
explicit ordered checklist: every disputed item, one line each, in dependency
|
|
72
|
+
order, with a single owner and a single verification command per item. Write it
|
|
73
|
+
to the ledger before touching anything.
|
|
74
|
+
4. **Go in order, one at a time.** Verify item 1 → if it fails, fix only item 1 →
|
|
75
|
+
re-verify only item 1 → commit → item 2. No parallel edits, no bundled fixes, no
|
|
76
|
+
opportunistic cleanup in the same commit. The point is that each change has one
|
|
77
|
+
reason and one proof.
|
|
78
|
+
5. **Re-check the whole list once** at the end, in the same order. If a later item
|
|
79
|
+
broke an earlier one, that pair is the real conflict — escalate it per step 2
|
|
80
|
+
instead of looping again.
|
|
81
|
+
6. **Record the ruling.** Ledger line: `loop-guard: <A vs B> — ruling: <what governs
|
|
82
|
+
and why> — items: <N> verified in order`. The final review reads it.
|
|
83
|
+
|
|
84
|
+
## When to stop and hand back
|
|
85
|
+
|
|
86
|
+
If step 2 lands on "the operator decides", or a cap is hit a second time after a
|
|
87
|
+
re-planned pass, **stop and report BLOCKED** with: the two shapes, the evidence, the
|
|
88
|
+
history of passes, and your recommendation. That is a complete, honest hand-back —
|
|
89
|
+
far cheaper than a third round of the same argument.
|
|
90
|
+
|
|
91
|
+
## Rationalizations
|
|
92
|
+
|
|
93
|
+
| Excuse | Reality |
|
|
94
|
+
|---|---|
|
|
95
|
+
| "One more pass and it converges" | Two passes with the same reason already proved it doesn't. The disagreement is above the code. |
|
|
96
|
+
| "I'll just revert to what worked" | That is the oscillation, not the exit. Name A and B first. |
|
|
97
|
+
| "The reviewer keeps changing its mind" | Different findings on the same lines mean the requirement is ambiguous. That's a spec question. |
|
|
98
|
+
| "Tidying while I'm in the file" | Untracked edits are what make churn invisible. One reason per change, in the ledger. |
|
|
99
|
+
| "Logging the loop is bureaucracy" | Detection needs a record; after compaction the ledger is the only memory that survives. |
|
|
100
|
+
| "It's faster than escalating" | A run that spends its budget re-deciding a spec question delivers nothing. Escalation costs one message. |
|