task-pipeline-skill 1.32.0 → 1.37.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 +253 -0
- package/CONTRIBUTING.md +76 -1
- package/README.md +24 -0
- package/SKILL-CARD.md +1 -1
- package/cursor/rules/task-pipeline.mdc +34 -9
- package/package.json +1 -1
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/commands/task-pipeline.md +11 -0
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +2 -0
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +133 -21
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +12 -5
- package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +20 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/continuity.md +18 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/exposure.md +110 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/loop-guard.md +52 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +2 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/progress.md +190 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +88 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +109 -9
- package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +1 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/run.md +77 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Progress — saying which pipeline this is, and where in it
|
|
2
|
+
|
|
3
|
+
**One job: make the run's position a printed fact instead of something the operator
|
|
4
|
+
reconstructs from the last thing that scrolled past.**
|
|
5
|
+
|
|
6
|
+
A pipeline that never says where it is has one specific failure, and it is not
|
|
7
|
+
confusion — it is that **a stage looks done because nothing printed**.
|
|
8
|
+
[`stages.md`](stages.md) opens with a checklist for exactly that reason and then marks
|
|
9
|
+
it *"copy it, tick it"*: an instruction with no gate behind it, which is rung 1
|
|
10
|
+
behaving like rung 3 ([`gates.md`](gates.md) → *Axis B*). This file is that checklist
|
|
11
|
+
promoted to something the run must emit.
|
|
12
|
+
|
|
13
|
+
**Boundary.** This file decides **what is printed and when**. It decides nothing about
|
|
14
|
+
what is true: every number on the block has a home somewhere else and is read from
|
|
15
|
+
there. A progress line that computes its own counts is the fourth copy of the truth,
|
|
16
|
+
and [`continuity.md`](continuity.md) already says what happens to those — nobody
|
|
17
|
+
maintains them and the next run reads them as current.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Contents
|
|
22
|
+
|
|
23
|
+
- The two boundaries, and only those two
|
|
24
|
+
- The header block
|
|
25
|
+
- The iteration line
|
|
26
|
+
- The rail is computed, never eleven
|
|
27
|
+
- What each glyph means
|
|
28
|
+
- Every number is borrowed
|
|
29
|
+
- Absent is a word, never a zero
|
|
30
|
+
- The run ledger this reads from
|
|
31
|
+
- Rationalizations
|
|
32
|
+
|
|
33
|
+
## The two boundaries, and only those two
|
|
34
|
+
|
|
35
|
+
**Task start** and **iteration close**. Nothing else.
|
|
36
|
+
|
|
37
|
+
An iteration is already defined — *one item taken to its gate*
|
|
38
|
+
([`continuity.md`](continuity.md) → *What one iteration means*) — and that definition
|
|
39
|
+
is what makes this cheap. Printing per agent turn would put a bar above every tool
|
|
40
|
+
call, and a block that appears fifty times a run is a block nobody reads, including
|
|
41
|
+
the one time it says something.
|
|
42
|
+
|
|
43
|
+
Between the two boundaries the run prints whatever it normally prints. This file adds
|
|
44
|
+
no narration.
|
|
45
|
+
|
|
46
|
+
## The header block
|
|
47
|
+
|
|
48
|
+
Emitted **once, before stage 0's first question**, and again whenever the module
|
|
49
|
+
changes:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
task-pipeline v1.34.0 · pipeline-audit · module P1 «the progress print» (1 of 4)
|
|
53
|
+
0 ✓ 1 ✓ 2 ✓ 3 ▶ 4 · 5 · 6 · 7 · 8 · 9 · 10 ·
|
|
54
|
+
███████░░░░░░░░░░░░░░░░░░░ gates 3/11 · now 3 Spec · manual
|
|
55
|
+
board B-028 · carry-over 0 rows · exposure 99 never · unlooked 0
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Four lines, and each one answers a question an operator otherwise has to ask:
|
|
59
|
+
|
|
60
|
+
| Line | Answers |
|
|
61
|
+
|---|---|
|
|
62
|
+
| 1 | *which skill, which version, which programme, which module of how many* |
|
|
63
|
+
| 2 | *which stages are closed, which one is live* |
|
|
64
|
+
| 3 | *how far along, what is running now, will it stop for me* |
|
|
65
|
+
| 4 | *what is queued, what is deferred, what nobody has confirmed* |
|
|
66
|
+
|
|
67
|
+
**The module segment is omitted when there is no module map.** A task that stage 2
|
|
68
|
+
never decomposed has no module, and printing `(1 of 1)` turns an absence into a claim
|
|
69
|
+
— the shape [`audit.md`](audit.md) is built around. Where stage 2 recorded `single
|
|
70
|
+
module: <name>` ([`decomposition.md`](decomposition.md)), print that phrase instead.
|
|
71
|
+
|
|
72
|
+
## The iteration line
|
|
73
|
+
|
|
74
|
+
Emitted at the **close** of every iteration, one line:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
▶ pipeline-audit · P1 (1/4) · 5 Dev auto · iter 3 · gates 5/11 · next B-025
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**`next` cites a `B-NNN`, never a description.** That rule is
|
|
81
|
+
[`continuity.md`](continuity.md)'s and it is the reason this line exists at all:
|
|
82
|
+
*"next up is X"* was already the one sentence in a loop that no gate reads. A board id
|
|
83
|
+
can be checked against `docs/superpowers/backlog.md`; *"next up: the export fix"*
|
|
84
|
+
cannot.
|
|
85
|
+
|
|
86
|
+
**Nothing queued is `next —`, printed.** A loop that reaches an empty board says so;
|
|
87
|
+
omitting the field is indistinguishable from forgetting it.
|
|
88
|
+
|
|
89
|
+
## The rail is computed, never eleven
|
|
90
|
+
|
|
91
|
+
The stage ids on the rail come from the project's `pipeline.json` → `stages[]`. They
|
|
92
|
+
are **not** the eleven in [`../pipeline.example.json`](../pipeline.example.json), which
|
|
93
|
+
is this plugin's *example* flow — a host project replaces it with its own stages
|
|
94
|
+
(`SKILL.md` → *Bring your own skills*).
|
|
95
|
+
|
|
96
|
+
A bar reading `gates 5/11` in a project with six stages is a false success in the
|
|
97
|
+
purest form the pipeline has: a summary that is confidently wrong about the thing it
|
|
98
|
+
summarises, printed in the place designed to be trusted at a glance.
|
|
99
|
+
|
|
100
|
+
So the rail carries **no stage count of its own**. Read the array, print what is in it.
|
|
101
|
+
Six stages give six positions.
|
|
102
|
+
|
|
103
|
+
## What each glyph means
|
|
104
|
+
|
|
105
|
+
| Glyph | Means | Written when |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `✓` | the stage's **gate passed** | the gate's own verdict was recorded |
|
|
108
|
+
| `▶` | in flight | the stage was entered and its gate has not returned |
|
|
109
|
+
| `·` | not entered | — |
|
|
110
|
+
| `✗` | entered, gate returned a failure | the verdict said so |
|
|
111
|
+
| `⊘` | skipped, **with the reason on the same run's record** | the short path, or a stage the brief excluded |
|
|
112
|
+
|
|
113
|
+
**`✓` means the gate passed — not that the stage was walked.** This is the whole
|
|
114
|
+
integrity of the block. A rail is a summary, and a summary is the easiest artefact in
|
|
115
|
+
a run to write from memory rather than from the record; a glyph set by recollection is
|
|
116
|
+
[`gates.md`](gates.md)'s *false success* with a nicer typeface. Derive each glyph from
|
|
117
|
+
the verdict the gate wrote, in the run ledger, and from nothing else.
|
|
118
|
+
|
|
119
|
+
**`⊘` may never be silent.** A skipped stage with no recorded reason is exactly what a
|
|
120
|
+
`·` looks like from outside, and the two mean opposite things.
|
|
121
|
+
|
|
122
|
+
## Every number is borrowed
|
|
123
|
+
|
|
124
|
+
| Field | Its home |
|
|
125
|
+
|---|---|
|
|
126
|
+
| `board B-NNN` | `docs/superpowers/backlog.md` ([`backlog.md`](backlog.md)) |
|
|
127
|
+
| `carry-over N rows` | the run's carry-over ledger, as printed beside every gate verdict |
|
|
128
|
+
| `exposure N never` | `docs/superpowers/verification.md` ([`exposure.md`](exposure.md)) |
|
|
129
|
+
| `unlooked N` | the gate's own disclosure ([`gates.md`](gates.md) → *Disclosures*) |
|
|
130
|
+
| `gates N/M` | the run ledger's verdict rows, and `pipeline.json` → `stages[]` |
|
|
131
|
+
|
|
132
|
+
**None of these is recomputed here.** If a number on the block disagrees with the
|
|
133
|
+
number beside a gate verdict, the block is wrong — that direction, always, because the
|
|
134
|
+
gate looked and the block quoted.
|
|
135
|
+
|
|
136
|
+
This also settles what the block is *not*: it is neither a ratchet nor a disclosure of
|
|
137
|
+
its own ([`gates.md`](gates.md) → *Ratchets*, *Disclosures*). It sets no floor and
|
|
138
|
+
carries no target. It is a **restatement with a citation**, and the citation is the
|
|
139
|
+
only reason a restatement is allowed here at all.
|
|
140
|
+
|
|
141
|
+
## Absent is a word, never a zero
|
|
142
|
+
|
|
143
|
+
Where a value does not exist, print the word:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
board — · carry-over 0 rows · exposure — · unlooked 0
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`exposure —` says *no verification ledger in this project*. `exposure 0` says *nothing
|
|
150
|
+
is unconfirmed*, which is the opposite claim, and it is the same inversion
|
|
151
|
+
[`exposure.md`](exposure.md) refuses when it prints `never checked` rather than
|
|
152
|
+
`0 days`. A zero standing in for an absence is how a project learns it is safe.
|
|
153
|
+
|
|
154
|
+
`carry-over 0 rows` **is** a real zero and prints as one: the ledger exists and holds
|
|
155
|
+
nothing.
|
|
156
|
+
|
|
157
|
+
## The run ledger this reads from
|
|
158
|
+
|
|
159
|
+
`.task-pipeline/run.md`, seeded at stage 0 from
|
|
160
|
+
[`../templates/run.md`](../templates/run.md), one file per run.
|
|
161
|
+
|
|
162
|
+
It already had a second owner before this file existed:
|
|
163
|
+
[`loop-guard.md`](loop-guard.md) names it as the record that makes churn detection
|
|
164
|
+
**mechanical**, and calls it the only memory that survives compaction. It was never
|
|
165
|
+
written by any run — the detector had no input, and the guard was doctrine wearing a
|
|
166
|
+
script's clothes. One file serves both readers: the guard reads the `touch:` lines,
|
|
167
|
+
this block reads the verdict rows and the iteration counter.
|
|
168
|
+
|
|
169
|
+
Three kinds of line, appended, never rewritten:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
stage: 3 Spec — gate manual — verdict pass — 2026-08-10T14:02Z
|
|
173
|
+
iter: 3 — item B-025 — closed at gate 6
|
|
174
|
+
touch: test/validate.py — pass 2 (stage 7) — reason: F-014
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**The counter is a count of `iter:` lines, not a number the agent remembers.** After a
|
|
178
|
+
compaction the agent's memory of "iteration 3" is gone and the file's is not, which is
|
|
179
|
+
the entire argument for keeping it on disk rather than in the reply.
|
|
180
|
+
|
|
181
|
+
## Rationalizations
|
|
182
|
+
|
|
183
|
+
| The excuse | What is actually true |
|
|
184
|
+
|---|---|
|
|
185
|
+
| "The operator can see the stages scroll by" | They can see that *something* printed. A stage that ended silently and a stage that never started look identical in a transcript, which is the failure `stages.md`'s checklist was written for and never enforced. |
|
|
186
|
+
| "A progress bar is decoration" | Then delete the numbers and keep the bar. The objection is really to the bar; the four borrowed counts are the payload, and they are the ones nobody prints today. |
|
|
187
|
+
| "I know which stage I'm on, I'll write the rail from memory" | Then the rail is a claim about the run rather than a reading of it, and it will be right until the run it most matters on. Derive it from the verdicts. |
|
|
188
|
+
| "There's no module map, I'll put (1 of 1)" | An undecomposed task has no module. `(1 of 1)` is an invented denominator, and a reader cannot tell it from a real one. |
|
|
189
|
+
| "Printing it every iteration is noise" | One line. The block is four, and it appears at task start. If that is noise, the run is emitting far worse elsewhere. |
|
|
190
|
+
| "The ledger is bureaucracy, I'll count iterations in my head" | Your head does not survive compaction. That is not a hypothetical here — it is why `loop-guard.md` asked for this file in the first place. |
|
|
@@ -37,6 +37,8 @@ file exists to stop.
|
|
|
37
37
|
- The prune — mandatory, and it runs after the stamp
|
|
38
38
|
- The loop closes at stage 0
|
|
39
39
|
- Where a lesson goes when it is not about this project
|
|
40
|
+
- Publishing the insight — the skill learns from every project that runs it
|
|
41
|
+
- What may leave the project — the redaction list
|
|
40
42
|
- Rationalizations
|
|
41
43
|
|
|
42
44
|
## Write the entry only for a divergence — and name the layer that owned it
|
|
@@ -227,9 +229,92 @@ rule that was retired for going cold is exactly the rule about to be re-learned.
|
|
|
227
229
|
|
|
228
230
|
A lesson that would be true in any repository does not belong in one project's
|
|
229
231
|
retro — it belongs in the pipeline's own doctrine
|
|
230
|
-
([`learned.md`](learned.md), which is exactly that list, earned the same way).
|
|
231
|
-
|
|
232
|
-
|
|
232
|
+
([`learned.md`](learned.md), which is exactly that list, earned the same way). A local
|
|
233
|
+
file that accumulates universal rules is a fork of the skill that nobody named.
|
|
234
|
+
|
|
235
|
+
**This said *"open an issue upstream"* for eight releases and named no repository, no
|
|
236
|
+
trigger and no authorization** — an instruction on rung 1 that everybody read as done.
|
|
237
|
+
The rest of this section is the mechanism.
|
|
238
|
+
|
|
239
|
+
## Publishing the insight — the skill learns from every project that runs it
|
|
240
|
+
|
|
241
|
+
**One job: stop a lesson dying in the repository that learned it.**
|
|
242
|
+
|
|
243
|
+
A retro entry is written per project and read by that project's next stage 0. The
|
|
244
|
+
pipeline itself never sees it. So a defect in the **skill** — a gate that loops, a
|
|
245
|
+
doctrine promising what nothing enforces, a rule firing on the wrong shape — is
|
|
246
|
+
rediscovered independently in every project and fixed in none of them.
|
|
247
|
+
|
|
248
|
+
**Opt-in, per project, off by default** — `pipeline.json` → `retro.publish`:
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
"retro": {
|
|
252
|
+
"publish": {
|
|
253
|
+
"repo": "ssheleg/task-pipeline",
|
|
254
|
+
"label": "retro-insight",
|
|
255
|
+
"redact": "strict"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Absent, nothing is published, and nothing is asked. **Silence arms nothing** — the same
|
|
261
|
+
floor deploy authorization uses, and for the same reason: this is an **outward act**,
|
|
262
|
+
and an outward act taken from a generic flag is an outward act nobody authorized
|
|
263
|
+
([`continuity.md`](continuity.md) → *The limit, before the capability*).
|
|
264
|
+
|
|
265
|
+
**The body is printed in full before the issue is opened, every time.** Not a summary
|
|
266
|
+
of it, not its title — the string that will be sent. The operator standing at stage
|
|
267
|
+
10's manual gate is already reading; showing them what leaves the machine costs one
|
|
268
|
+
block and is the only moment anyone can stop it.
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
── would open issue ──────────────────────────────────────────
|
|
272
|
+
repo: ssheleg/task-pipeline
|
|
273
|
+
label: retro-insight
|
|
274
|
+
title: [retro] a queue is not a diagnosis
|
|
275
|
+
<the whole body, verbatim>
|
|
276
|
+
──────────────────────────────────────────────────────────────
|
|
277
|
+
opening… → #24
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**No `gh`, no network, no permission?** Print the body, say the issue was **not**
|
|
281
|
+
opened, and carry the exact text in the carry-over ledger. That is the honest
|
|
282
|
+
degradation; a second transport is not.
|
|
283
|
+
|
|
284
|
+
## What may leave the project — the redaction list
|
|
285
|
+
|
|
286
|
+
An issue is a **public artefact in someone else's repository**. What travels is the
|
|
287
|
+
*class*; what stays is everything that identifies where it happened.
|
|
288
|
+
|
|
289
|
+
| Goes | Stays |
|
|
290
|
+
|---|---|
|
|
291
|
+
| the class of failure, stated in the abstract | the file, the function, the line it happened in |
|
|
292
|
+
| which stage owned it and which stage surfaced it | the repository, organisation, branch or commit |
|
|
293
|
+
| the doctrine or guard that missed it, by its name **in this skill** | any host path, absolute or relative |
|
|
294
|
+
| the fix by grade, and the check that would catch it | the code, the config values, the data |
|
|
295
|
+
| whether an existing standing instruction fired | any person, company, customer or product name |
|
|
296
|
+
|
|
297
|
+
Five rules, numbered so a reader can point at one:
|
|
298
|
+
|
|
299
|
+
1. **No host paths.** Only paths inside task-pipeline itself — `references/…`,
|
|
300
|
+
`templates/…`, `test/validate.py`. An absolute path names a machine.
|
|
301
|
+
2. **No host identifiers**: repository, organisation, branch, commit, tag, issue or PR
|
|
302
|
+
number belonging to the project the run happened in.
|
|
303
|
+
3. **No code, no configuration values, no data** — not a snippet, not a redacted
|
|
304
|
+
snippet. A shape can be described in a sentence.
|
|
305
|
+
4. **No names**: person, company, customer, employer, product.
|
|
306
|
+
5. **The title states the class, not the incident** — *"a queue is not a diagnosis"*,
|
|
307
|
+
never *"our export job looped"*.
|
|
308
|
+
|
|
309
|
+
**The printed text and the sent text are one string.** Redacting after the print, or
|
|
310
|
+
printing a cleaned-up version of what is actually sent, is the false-success shape this
|
|
311
|
+
bundle names outright ([`gates.md`](gates.md) → *False success*): a mechanism reporting
|
|
312
|
+
on itself rather than on what it did.
|
|
313
|
+
|
|
314
|
+
**When in doubt the rule is subtraction, not judgement.** An insight that survives
|
|
315
|
+
losing a detail is still an insight; a detail that leaks cannot be recalled from an
|
|
316
|
+
index. If removing it makes the entry incomprehensible, the entry was about the project
|
|
317
|
+
and not about the skill — keep it local.
|
|
233
318
|
|
|
234
319
|
## Rationalizations
|
|
235
320
|
|
|
@@ -8,12 +8,27 @@ operator's explicit go). These stages (0 intake + 1→10) are the plugin's
|
|
|
8
8
|
`pipeline.schema.json`; a host project replaces it with its own
|
|
9
9
|
stages/agents/types (see SKILL.md → *Bring your own skills*).
|
|
10
10
|
|
|
11
|
-
## The run checklist —
|
|
11
|
+
## The run checklist — printed, not remembered
|
|
12
12
|
|
|
13
|
-
Complex workflows lose steps silently.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
Complex workflows lose steps silently. **The run says where it is**, at two boundaries
|
|
14
|
+
and only two — task start and iteration close ([`progress.md`](progress.md)):
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
task-pipeline vX.Y.Z · <topic> · module <id> «<name>» (N of M)
|
|
18
|
+
0 ✓ 1 ✓ 2 ✓ 3 ▶ 4 · 5 · 6 · 7 · 8 · 9 · 10 ·
|
|
19
|
+
███████░░░░░░░░░░░░░░░░░░░ gates 3/11 · now 3 Spec · manual
|
|
20
|
+
board B-NNN · carry-over N rows · exposure N never · unlooked N
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The rail's positions come from the project's own `pipeline.json`, never from the count
|
|
24
|
+
below — those eleven are this plugin's example flow. Each glyph is read from the
|
|
25
|
+
verdict its gate wrote to `.task-pipeline/run.md`, and from nothing else: a rail
|
|
26
|
+
written from memory is a summary that is confidently wrong exactly where it is trusted
|
|
27
|
+
at a glance.
|
|
28
|
+
|
|
29
|
+
The checklist below is what that rail summarises. This section said *"copy it, tick
|
|
30
|
+
it"* until 2026-08-10 — an instruction with no gate behind it, which is the same
|
|
31
|
+
failure it was written to prevent, one level up.
|
|
17
32
|
|
|
18
33
|
```
|
|
19
34
|
Pipeline progress
|
|
@@ -35,7 +50,7 @@ never that the work was skipped quietly.
|
|
|
35
50
|
|
|
36
51
|
## Contents
|
|
37
52
|
|
|
38
|
-
- The run checklist —
|
|
53
|
+
- The run checklist — printed, not remembered
|
|
39
54
|
- 0 — Intake grill — MANDATORY
|
|
40
55
|
- 1 — Docs study
|
|
41
56
|
- 2 — Brainstorm + decompose
|
|
@@ -123,6 +138,27 @@ never that the work was skipped quietly.
|
|
|
123
138
|
or they genuinely disagree and that is a decision. There is no fourth option, and
|
|
124
139
|
starting on an unresolved divergence means building against a system that does
|
|
125
140
|
not exist.
|
|
141
|
+
- **Phase 1d — the short-path triage: printed, proposed, never taken silently.** This
|
|
142
|
+
pipeline's own boundary exempts a typo, a one-line fix and a mechanical rename — and
|
|
143
|
+
nothing measured that until 2026-08-10, so the exemption depended on an agent
|
|
144
|
+
remembering it while eleven stages and four manual gates stood in front of a
|
|
145
|
+
one-paragraph edit. Three questions, each with something behind it:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
1. files the request names, resolved git ls-files -- <paths> -> N
|
|
149
|
+
2. any of them a public contract the version-synced surfaces,
|
|
150
|
+
pipeline.schema.json, the
|
|
151
|
+
command, the README -> yes/no
|
|
152
|
+
3. behaviour a user or a caller observes changes -> yes/no
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Few files, no contract, no observable change ⇒ **propose** the short path: stages 1,
|
|
156
|
+
2, 3 and 4 marked `⊘` with the triage answer as the reason, and 5→10 running
|
|
157
|
+
unchanged. **Propose, never take.** The answer goes in the brief's autonomy sweep and
|
|
158
|
+
silence takes the full flow — the same floor deploy authorization uses. The glyph is
|
|
159
|
+
what makes it safe: a skipped stage is printed on the rail **with its reason**
|
|
160
|
+
([`progress.md`](progress.md)), and a skip nobody can see is indistinguishable from a
|
|
161
|
+
stage that was never entered.
|
|
126
162
|
- **How it runs: [`grill.md`](grill.md)** — the full doctrine, built into this
|
|
127
163
|
skill (nothing to install). In short: one question per turn, a recommended
|
|
128
164
|
answer with each, explore the codebase before asking, depth-first through the
|
|
@@ -170,12 +206,22 @@ never that the work was skipped quietly.
|
|
|
170
206
|
is now stale), no open contradictions, **every
|
|
171
207
|
autonomy-sweep row is answered or explicitly marked "stop and ask here"**, the
|
|
172
208
|
**REQ table is written and every row names its check**, the carry-over ledger is
|
|
173
|
-
seeded,
|
|
209
|
+
seeded, **`.task-pipeline/run.md` exists and the header block has been printed**
|
|
210
|
+
([`progress.md`](progress.md)), the model decision is recorded, and the operator
|
|
211
|
+
confirms the brief. Stop when a
|
|
174
212
|
re-scan surfaces no new branches (don't grill past diminishing returns;
|
|
175
213
|
reversible calls can be deferred with a note). Only then start stage 1.
|
|
176
214
|
- **The verification ledger is read.** `docs/superpowers/verification.md` — the harvest
|
|
177
215
|
quotes **how many rows sit at `never`**, because that is the project's standing
|
|
178
216
|
exposure and stage 0 is where it is cheapest to look ([`verification.md`](verification.md)).
|
|
217
|
+
- **The run ledger is seeded and the header block is printed** — in that order, before
|
|
218
|
+
the first grill question. `.task-pipeline/run.md` from
|
|
219
|
+
[`../templates/run.md`](../templates/run.md) is the record **two** mechanisms already
|
|
220
|
+
depended on and no run had ever written: [`loop-guard.md`](loop-guard.md) calls its
|
|
221
|
+
own churn detection mechanical and reads the `touch:` lines, and
|
|
222
|
+
[`progress.md`](progress.md) derives the rail and the iteration counter from the
|
|
223
|
+
`stage:` and `iter:` lines. The header goes out before the interview because a run
|
|
224
|
+
that announces its position only at the end announced it to nobody.
|
|
179
225
|
- **The board is read, or seeded.** `docs/superpowers/backlog.md` ([`backlog.md`](backlog.md)) — its **open count is quoted in the brief**, measured by a command at the top of the run rather than inherited from the last run's report. Absent ⇒ seeded from the template and said so; an empty board and no board are the same thing to work on, and only one of them can be appended to.
|
|
180
226
|
|
|
181
227
|
## 1 — Docs study
|
|
@@ -256,6 +302,32 @@ never that the work was skipped quietly.
|
|
|
256
302
|
never rebuild from scratch. If the chain already exists and is validated (e.g.
|
|
257
303
|
the task entered from super-ux), just verify (linter green) and embed it into
|
|
258
304
|
the spec; only build the parts that are missing.
|
|
305
|
+
- **COPY track — how it sounds.** Every string a product's user will read is written
|
|
306
|
+
through super-ux's `copywriting`, against the brand pack (`docs/brand/voice.md`,
|
|
307
|
+
`terminology.md`, `facts.md`). No pack ⇒ `/brand-init` **before** the first string,
|
|
308
|
+
not after: a voice reverse-engineered from copy already written is a description of
|
|
309
|
+
what happened, not a decision. In scope: interface strings, errors, empty states,
|
|
310
|
+
the landing, pricing, the user-facing changelog. **Out of scope, and saying so is
|
|
311
|
+
what keeps the track honest:** commit messages, PR descriptions, code comments, a
|
|
312
|
+
developer README, internal docs. Running a brand pack over a line in a contributors'
|
|
313
|
+
changelog is the fastest way to teach an agent to route around the track.
|
|
314
|
+
- **VISUAL track — how it looks.** Where the task has a visual surface, the visual
|
|
315
|
+
layer goes through `sheleg-design` ([`companion-skills.md`](companion-skills.md)):
|
|
316
|
+
tokens and themes, typography and rhythm, motion and how it degrades to rest, the
|
|
317
|
+
boundary with Figma (tokens as variables, never raw values carried across). Not
|
|
318
|
+
through it: a purely structural change — what sits where is the UX track's — text,
|
|
319
|
+
a backend, an internal script.
|
|
320
|
+
- **Each track's refusal is a sentence, never a silence.** *"Без дизайна" / "as is"*
|
|
321
|
+
ends the visual track; *"без бренда" / "draft"* ends the copy track. Either one is
|
|
322
|
+
the operator's to make and costs nothing — but it is **recorded in the brief and
|
|
323
|
+
said out loud in the close-out**, because a track skipped silently and a track that
|
|
324
|
+
ran are the same thing in a transcript. This is the `⊘` rule one layer up: a skip
|
|
325
|
+
nobody can see is indistinguishable from work that happened.
|
|
326
|
+
- **Three tracks, three questions, and they do not substitute for each other.** super-ux
|
|
327
|
+
decides what the interface must **do**; `copywriting` how it **sounds**;
|
|
328
|
+
`sheleg-design` how it **looks**. Until 2026-08-10 this stage named only the first,
|
|
329
|
+
so a run designed a flow, then wrote its strings by taste and picked its values at the
|
|
330
|
+
keyboard — and every gate in the pipeline reported green over both.
|
|
259
331
|
- **Spec:** write the approved design to
|
|
260
332
|
`docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` and commit it. Lock all
|
|
261
333
|
shared contracts (types, schemas, signatures, file layout). For UI tasks the
|
|
@@ -274,7 +346,11 @@ never that the work was skipped quietly.
|
|
|
274
346
|
(or an explicit v1-mode/tiny-project waiver by the operator). **With Figma on:
|
|
275
347
|
the canonical record names one file, and every `screens.md` frame link carries
|
|
276
348
|
that same `:fileKey`** — a string match, not a judgement; a differing key means
|
|
277
|
-
the run drew in a second file nobody will open.
|
|
349
|
+
the run drew in a second file nobody will open. **Every user-facing string went
|
|
350
|
+
through the COPY track or the refusal is recorded**, and **the visual layer went
|
|
351
|
+
through the VISUAL track or the refusal is recorded** — a recorded refusal passes
|
|
352
|
+
this gate and an unmentioned one does not, which is the only difference that matters.
|
|
353
|
+
No plan (stage 4)
|
|
278
354
|
starts before this — the chain comes BEFORE interface.
|
|
279
355
|
|
|
280
356
|
## 4 — Plan
|
|
@@ -308,6 +384,16 @@ never that the work was skipped quietly.
|
|
|
308
384
|
watch it fail → minimal impl → watch it pass → commit. Pin subagents to the
|
|
309
385
|
run's confirmed model (`model-tiering.md`). The plan's parallel groups fan out
|
|
310
386
|
**only** when each implementer gets its own worktree; otherwise sequential.
|
|
387
|
+
- **Web front end? The task's own surface is checked in a browser, not in the diff.**
|
|
388
|
+
Where `chrome-devtools` is connected ([`companion-skills.md`](companion-skills.md)):
|
|
389
|
+
after a task that changes a rendered surface, load it, take a snapshot and read the
|
|
390
|
+
console and the network log **before the task is marked DONE** — a component can be
|
|
391
|
+
correct and land under a fixed header, and a review of the diff cannot see that.
|
|
392
|
+
Absent, say the surface was verified by reading the diff and treat it as the weaker
|
|
393
|
+
claim it is. Stage 6 repeats this over the whole tree; this one catches it while the
|
|
394
|
+
implementer that wrote it is still dispatched. The matrix pointed this companion at
|
|
395
|
+
stages 5–6 from the day it was added and **this stage had never named it** — found by
|
|
396
|
+
the guard comparing the two, not by a reader.
|
|
311
397
|
- **Integration closes the stage:** sync with the base branch, re-run the full suite
|
|
312
398
|
on the result, land it the project's way (merge, or a PR — outward, so it needs a
|
|
313
399
|
go), remove the worktree. Stages 7–9 act on the integrated result, so a branch the
|
|
@@ -370,6 +456,14 @@ never that the work was skipped quietly.
|
|
|
370
456
|
tagging, the CI verdict for what was just pushed is READ, not assumed**
|
|
371
457
|
([`conventions.md`](conventions.md) → *The CI verdict*) — a tag on a commit whose
|
|
372
458
|
run nobody read is how a red `main` ships.
|
|
459
|
+
- **The review loop that lives here has a cap, and the cap is a measurement**
|
|
460
|
+
([`loop-guard.md`](loop-guard.md) → *The review loop*). **3 rounds** per artifact by
|
|
461
|
+
default (`pipeline.json` → `run.review.maxRounds`); at the cap the run stops reviewing
|
|
462
|
+
and prints new-versus-self-inflicted per round, and either the numbers end it or the
|
|
463
|
+
operator continues it out loud. This stage's loop was capped by nothing until
|
|
464
|
+
2026-08-10 and ran ten rounds twice in one programme, against a stated ceiling of two
|
|
465
|
+
re-entries per stage — the ceiling simply did not name a review round. Every finding
|
|
466
|
+
left open at the cap leaves as a board row with its evidence, never as a shrug.
|
|
373
467
|
|
|
374
468
|
## 8 — Post-deploy
|
|
375
469
|
- **Freedom: medium** — where the logs live varies; 'clean boot or an honest degradation report' does not ([`gates.md`](gates.md) → *Axis C*).
|
|
@@ -545,7 +639,13 @@ never that the work was skipped quietly.
|
|
|
545
639
|
list at or under its cap, every deletion logged in the archive with its commit,
|
|
546
640
|
entries older than five run stamps rotated into `docs/superpowers/retro/`, the run
|
|
547
641
|
stamped with its commit, every SHA in either file resolvable, and the
|
|
548
|
-
counts printed beside this verdict**; **
|
|
642
|
+
counts printed beside this verdict**; **where `pipeline.json` → `retro.publish` is
|
|
643
|
+
set, the skill-level insight is published as an issue on the skill's repository —
|
|
644
|
+
its body printed in full first, the printed string and the sent string being one
|
|
645
|
+
string, and the five redaction rules applied
|
|
646
|
+
([`retrospective.md`](retrospective.md) → *What may leave the project*). Absent, the
|
|
647
|
+
step does not exist and is not asked about: publishing to another repository is an
|
|
648
|
+
outward act and silence authorizes none**; **the documentation gate has been seen
|
|
549
649
|
failing once against a planted defect and its ratchet counts are printed**
|
|
550
650
|
([`gates.md`](gates.md)); **every repository is closed — the parent included:
|
|
551
651
|
`git submodule status` shows no `+`, each repo clean and pushed**; **every check this gate leans on has been seen failing
|
|
@@ -13,6 +13,7 @@ from `super-ux`.
|
|
|
13
13
|
| `carryover.md` | `docs/superpowers/specs/YYYY-MM-DD-<topic>-carryover.md` | 0 seeds, all stages append, 10 reads |
|
|
14
14
|
| `verification.md` | `docs/superpowers/verification.md` | 8 writes a row per shipped REQ, 10 requires it, a human fills `Human` |
|
|
15
15
|
| `backlog.md` | `docs/superpowers/backlog.md` | 0 seeds when absent, any stage appends, 10 resolves and re-derives |
|
|
16
|
+
| `run.md` | `.task-pipeline/run.md` — **git-ignored**, one per run | 0 seeds it, every gate appends a verdict, every repeating pass a `touch:` line |
|
|
16
17
|
| `context.md` | `CONTEXT.md` at the repo root (or per context) | 0 — grill, domain awareness |
|
|
17
18
|
| `adr.md` | `docs/adr/NNNN-<slug>.md` | 0 — grill, hard-to-reverse decisions |
|
|
18
19
|
| `docmap.md` | `docs/DOCMAP.md` — **one per project** | 0 — the documentation inventory |
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Run ledger — `.task-pipeline/run.md`
|
|
2
|
+
|
|
3
|
+
> **One file per run.** Seeded at stage 0, appended by every stage, never rewritten.
|
|
4
|
+
> Two readers depend on it and neither can work from the agent's memory: the skill's
|
|
5
|
+
> `references/loop-guard.md` reads the `touch:` lines to detect churn mechanically, and
|
|
6
|
+
> its `references/progress.md` reads the `stage:` verdicts and the `iter:` count to
|
|
7
|
+
> print the rail.
|
|
8
|
+
>
|
|
9
|
+
> **This file is the run's memory after a compaction.** Everything else about the
|
|
10
|
+
> run's position lives in a context window that will not survive one.
|
|
11
|
+
|
|
12
|
+
Run: `<topic>` · started `<YYYY-MM-DD>` · module map: `<path or "none">`
|
|
13
|
+
|
|
14
|
+
## Lines
|
|
15
|
+
|
|
16
|
+
Append-only. Three shapes, and nothing else belongs here:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
stage: <id> <name> — gate <auto|manual> — verdict <pass|fail|skip> — <ISO-8601>
|
|
20
|
+
iter: <N> — item <B-NNN or task id> — closed at gate <stage id>
|
|
21
|
+
touch: <file> — pass <N> (<stage|round|module>) — reason: <finding id / gate item>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **`stage:`** — written when a gate **returns**, not when the stage is entered. The
|
|
25
|
+
rail's `✓` is derived from this line and from nothing else; a glyph set from memory
|
|
26
|
+
is a summary that is confidently wrong exactly when it matters.
|
|
27
|
+
- **`iter:`** — one line per iteration closed. The progress line's counter is
|
|
28
|
+
`grep -c '^iter:'`, never a number anyone remembers.
|
|
29
|
+
- **`touch:`** — one line per file per pass, and the reason names **what forced the
|
|
30
|
+
edit**: a finding id, a failed gate item, an operator instruction. *"Cleanup"*,
|
|
31
|
+
*"polish"* and *"while I was there"* are not reasons; they are churn with better
|
|
32
|
+
manners.
|
|
33
|
+
|
|
34
|
+
A `skip` verdict carries its reason on the same line — a skipped stage and a stage
|
|
35
|
+
never entered look identical from outside, and they mean opposite things.
|
|
36
|
+
|
|
37
|
+
## Log
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
stage: 0 Intake — gate manual — verdict pass — 2026-08-10T11:14Z
|
|
41
|
+
iter: 1 — item B-025 — closed at gate 0
|
|
42
|
+
stage: 1 Docs study — gate auto — verdict pass — 2026-08-10T11:31Z
|
|
43
|
+
touch: src/export.ts — pass 1 (stage 5) — reason: TASK-3
|
|
44
|
+
touch: src/export.ts — pass 2 (stage 5) — reason: F-014
|
|
45
|
+
touch: src/export.ts — pass 3 (stage 5) — reason: F-014
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The last two lines are a **trip**: the same file, two consecutive passes, the same
|
|
49
|
+
reason. `references/loop-guard.md` → *Detection* item 2 — the fix did not fix it, or
|
|
50
|
+
the two passes disagree about what *fixed* means. Stop editing and run the break
|
|
51
|
+
protocol; do not dispatch a fourth pass.
|
|
52
|
+
|
|
53
|
+
## Why it is not the build ledger
|
|
54
|
+
|
|
55
|
+
`.task-pipeline/build/<plan>/progress.md` covers **one stage** — stage 5's tasks, and
|
|
56
|
+
whether a task was already dispatched (`references/build.md`). This file
|
|
57
|
+
covers **the run**: stage verdicts, iterations, and every repeating pass anywhere in
|
|
58
|
+
the pipeline, including the loops between stages that the build ledger cannot see.
|
|
59
|
+
|
|
60
|
+
Keeping them separate is deliberate. A run that has no stage-5 work still loops, still
|
|
61
|
+
re-enters stages and still needs a rail — and it would have no ledger at all if the
|
|
62
|
+
run's memory lived inside the build directory that stage 5 deletes.
|
|
63
|
+
|
|
64
|
+
## What closes it, and what survives it
|
|
65
|
+
|
|
66
|
+
**This file is git-ignored** — `.task-pipeline/` is, and this lives inside it. It is
|
|
67
|
+
the run's working memory, not its record: it exists to survive a **compaction**, which
|
|
68
|
+
is a different problem from surviving the run.
|
|
69
|
+
|
|
70
|
+
So stage 10 **reads it and copies out what outlives the run** — the pass counts and
|
|
71
|
+
any loop-guard ruling go into the acceptance file and the retro stamp, which are
|
|
72
|
+
committed. What is not carried out is gone when the directory is cleared, and that is
|
|
73
|
+
the correct outcome for a `touch:` line whose finding has been closed.
|
|
74
|
+
|
|
75
|
+
Never treat it as evidence in a later run. A file that is not in git cannot be quoted
|
|
76
|
+
at a commit, and a claim nobody can navigate to is the thing this repository's
|
|
77
|
+
documentation canon exists to refuse.
|