task-pipeline-skill 1.65.0 → 1.67.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 +60 -0
- package/SKILL-CARD.md +1 -1
- package/package.json +1 -1
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/backlog.md +27 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/verification.md +34 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/exposure.sh +23 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.67.0 — a ledger records two different things, and most record only one
|
|
4
|
+
|
|
5
|
+
**A ledger records two different things, and most record only one.** *What confirmed it*
|
|
6
|
+
is evidence — a command, a CI run id, a fixture name. *Whether a person looked* is the
|
|
7
|
+
`Human` axis, and it is the only one the exposure line is defined over.
|
|
8
|
+
|
|
9
|
+
Measured across this family: nine repositories, **ten** header shapes, **815** rows.
|
|
10
|
+
|
|
11
|
+
| what the state column can say | rows | repositories |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| whether a **person** looked (`Human`) | **126** | 1 |
|
|
14
|
+
| a date and what was watched (`Last verified`) | 180 | 1 |
|
|
15
|
+
| `verified` — by a person **or** a command, indistinguishable | 391 | 4 |
|
|
16
|
+
| nothing: evidence recorded, no state column at all | 118 | 3 |
|
|
17
|
+
|
|
18
|
+
So `never` is measurable in **one repository of nine, over 15% of the rows**, and the
|
|
19
|
+
number this doctrine is written around is undefined in the rest. That is not a defect in
|
|
20
|
+
those ledgers — recording what confirmed something is the Auto job done properly. **The
|
|
21
|
+
defect is doctrine that speaks as though the column were there**, so `references/verification.md`
|
|
22
|
+
now states the split, and three rules follow from it: where there is no state column the
|
|
23
|
+
line says so and prints no number; a `verified` that cannot separate a person from a
|
|
24
|
+
command may not be reported as human confirmation; and adding the column later never
|
|
25
|
+
reaches backwards, because a back-filled ledger answers the question wrongly instead of not
|
|
26
|
+
at all.
|
|
27
|
+
|
|
28
|
+
`exposure.sh` also stops calling a self-explaining status unreadable. `**observed** — the
|
|
29
|
+
row exists because the miss happened in this run` is an ordinary way to write a state, and
|
|
30
|
+
four rows in this family were reported unparseable for explaining themselves. The
|
|
31
|
+
vocabulary now matches the **leading word**, with the empty cell tested before the word is
|
|
32
|
+
taken so a blank still counts as unconfirmed.
|
|
33
|
+
|
|
34
|
+
Guards: 351 → **351**. Fixtures 20 → **20**; these are behaviours the existing cases
|
|
35
|
+
exercise by running the script, and all nine family ledgers were run through it by hand.
|
|
36
|
+
|
|
37
|
+
## v1.66.0 — the shape is not fixed, so nothing may assume it
|
|
38
|
+
|
|
39
|
+
**The check-list printed the size of the work labelled as who it hurts, in every seeded
|
|
40
|
+
project.** `exposure.sh` read the board's blast radius from column 5. That is `Blast` in the
|
|
41
|
+
family umbrella's eight-column board and **`Size`** in the ten-column board this repository
|
|
42
|
+
seeds, so a host project got `[blast L]` — a work-size letter presented as a severity.
|
|
43
|
+
|
|
44
|
+
It shipped for a full release **two lines away from where the same lesson had just been
|
|
45
|
+
applied to the ledger's status column**. Fixing one instance of a class and leaving the
|
|
46
|
+
other in the same file is the recurrence this repository's retro already names.
|
|
47
|
+
|
|
48
|
+
Blast is resolved by header now, and two fixtures hold both shapes: the ten-column board
|
|
49
|
+
must yield `[blast 3]` and not `[blast L]`, and the eight-column one must not regress. A
|
|
50
|
+
third case asserts that a board with **no** blast column prints no blast at all — an
|
|
51
|
+
invented weight is worse than a missing one, because it looks like data.
|
|
52
|
+
|
|
53
|
+
**The rule is written down rather than left as two fixes.** `references/backlog.md` gains
|
|
54
|
+
*The shape is not fixed, so nothing may assume it*: resolve every column by header name,
|
|
55
|
+
once per section and knowing a file may hold more than one shape; treat an absent column as
|
|
56
|
+
absent; and name the column in the output where the reading depends on it. Two board shapes
|
|
57
|
+
exist in this family and five ledger shapes, all documented in their own headers, and none
|
|
58
|
+
of them is wrong — reading any of them by position is.
|
|
59
|
+
|
|
60
|
+
Fixtures 18 → **20**. Guards: 351 → **351**; these are behaviours of the seeded script,
|
|
61
|
+
which the fixtures exercise by running it.
|
|
62
|
+
|
|
3
63
|
## v1.65.0 — a decision is not debt
|
|
4
64
|
|
|
5
65
|
**`open` is work not done, `dropped` is an idea abandoned, and neither fits a deliberate
|
package/SKILL-CARD.md
CHANGED
|
@@ -12,7 +12,7 @@ harmless.
|
|
|
12
12
|
|---|---|
|
|
13
13
|
| **Purpose** | Runs a substantial task through ten gated delivery stages — intake grill, docs study, brainstorm, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs+registers, acceptance — refusing to advance until each gate passes |
|
|
14
14
|
| **Owner** | ssheleg ([github.com/ssheleg/task-pipeline](https://github.com/ssheleg/task-pipeline)) |
|
|
15
|
-
| **Version** | 1.
|
|
15
|
+
| **Version** | 1.67.0 |
|
|
16
16
|
| **Surface** | Claude Code (filesystem skill + plugin) and the vercel `skills` CLI. **Not** uploaded to the Skills API; custom Skills do not sync across surfaces |
|
|
17
17
|
| **Dependencies** | None required. Optional: `context7` (MCP), `figma` (MCP), super-ux, agent-sync, graphify, obsidian-wiki, and **one of two browser channels** — `playwright` (CLI or MCP) or `chrome-devtools` (MCP); either satisfies the browser step and neither is required. Every stage's doctrine ships in-repo; the one conditional requirement is super-ux for the stage-3 UX track on a user-facing task |
|
|
18
18
|
| **Evaluation status** | Suite authored, 5 categories. One recorded run, **self-observed by the author**; **zero blind runs on zero of three models** — the split, and the numbers, live in [`evals/RESULTS.md`](evals/RESULTS.md) and are computed by `evals/run.py` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "task-pipeline-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.67.0",
|
|
4
4
|
"description": "Full-cycle delivery pipeline for coding agents: a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine ships inside the skill — no companion plugin required. This package is the installer CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"task-pipeline": "bin/task-pipeline.js"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "task-pipeline",
|
|
3
3
|
"displayName": "Task Pipeline",
|
|
4
4
|
"description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/manual gates, a frozen requirement spine that closes with evidence, a work board and a verification ledger that outlive a run, an exposure line naming what shipped unconfirmed, a progress rail computed from the project's own config, a loop guard whose review ceiling measures rather than stops, and stage-3 tracks for what a product does, how it sounds and how it looks. Two modes need no task: `checkup` (what is unverified) and `setup` (audit existing docs). Retro insights can publish upstream as issues, opt-in and redacted.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.67.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ssheleg",
|
|
8
8
|
"url": "https://x.com/sshlg93"
|
|
@@ -20,6 +20,7 @@ exactly one seam, and that seam already existed as a dangling pointer.
|
|
|
20
20
|
- Seeded or picked up
|
|
21
21
|
- A row that says work exists names where it lives
|
|
22
22
|
- Priority is computed, not assigned
|
|
23
|
+
- The shape is not fixed, so nothing may assume it
|
|
23
24
|
- A decision is not debt — `waived`
|
|
24
25
|
- What a loop iteration does with it
|
|
25
26
|
- Rationalizations
|
|
@@ -121,6 +122,32 @@ Two consequences worth stating, because both are the point:
|
|
|
121
122
|
`sev` and `blast` are judgement, and they are written down *as* judgement: two small
|
|
122
123
|
integers a reader can disagree with, rather than a ranking they can only accept.
|
|
123
124
|
|
|
125
|
+
## The shape is not fixed, so nothing may assume it
|
|
126
|
+
|
|
127
|
+
This template ships one shape. Projects change it, and they are right to — the family
|
|
128
|
+
umbrella dropped `Size`, `Sev` and `Home`, added `Effort`, and divides by it, which ranks
|
|
129
|
+
cheap-and-old above expensive-and-old in a way `sev × blast` cannot. Two shapes, both
|
|
130
|
+
documented in their own headers, neither wrong.
|
|
131
|
+
|
|
132
|
+
**What is wrong is reading either one by position.** `$5` is `Blast` in an eight-column
|
|
133
|
+
board and `Size` in this ten-column one, so a check-list that read index 5 printed
|
|
134
|
+
`[blast L]` in every seeded project — the *size* of the work, labelled as who it hurts.
|
|
135
|
+
It shipped for a full release, two lines from where the same lesson had just been applied
|
|
136
|
+
to a different column.
|
|
137
|
+
|
|
138
|
+
So the rule, for anything that reads a board or a ledger:
|
|
139
|
+
|
|
140
|
+
- **Resolve every column by its header name**, once per section, and remember that a file
|
|
141
|
+
may hold more than one shape.
|
|
142
|
+
- **A column that is absent is absent.** Print nothing rather than a default — an invented
|
|
143
|
+
weight is worse than a missing one, because it looks like data.
|
|
144
|
+
- **Name the column in the output** where the reading depends on it. `[blast 3]` says which
|
|
145
|
+
number that is; a bare `3` does not.
|
|
146
|
+
|
|
147
|
+
The same rule governs the verification ledger, where five shapes exist across this family
|
|
148
|
+
and only one carries a column that can say a *person* looked
|
|
149
|
+
([`exposure.md`](exposure.md)).
|
|
150
|
+
|
|
124
151
|
## A decision is not debt — `waived`
|
|
125
152
|
|
|
126
153
|
`open` is work not done. `dropped` is an idea abandoned. Neither fits a deliberate **no**
|
|
@@ -22,6 +22,7 @@ the run*. Three things it does not say, and each is why this file exists:
|
|
|
22
22
|
|
|
23
23
|
- Why it keys to the brief, not to the coverage table
|
|
24
24
|
- `never` is a fact
|
|
25
|
+
- A ledger records two different things, and most record only one
|
|
25
26
|
- What stage 8 writes and what stage 10 refuses
|
|
26
27
|
- Rationalizations
|
|
27
28
|
|
|
@@ -53,6 +54,39 @@ So the count has **no floor, no direction, and may never be given a target**, ex
|
|
|
53
54
|
like the disclosures in [`gates.md`](gates.md). A project with forty `never` rows is not
|
|
54
55
|
failing; it is a project that now knows something it could not previously ask.
|
|
55
56
|
|
|
57
|
+
## A ledger records two different things, and most record only one
|
|
58
|
+
|
|
59
|
+
**What confirmed it** and **whether a person looked** are separate facts. The first is
|
|
60
|
+
evidence: a command, a CI run id, a fixture name. The second is the `Human` axis, and it is
|
|
61
|
+
the one the exposure line is defined over.
|
|
62
|
+
|
|
63
|
+
A ledger may carry either or both, and most carry only the first. Measured across this
|
|
64
|
+
family on 2026-08-16 — nine repositories, **ten** header shapes, **815** rows:
|
|
65
|
+
|
|
66
|
+
| what the state column can say | rows | repositories |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| whether a **person** looked (`Human`) | **126** | 1 |
|
|
69
|
+
| a date and what was watched (`Last verified`) | 180 | 1 |
|
|
70
|
+
| `verified` — by a person **or** a command, indistinguishable | 391 | 4 |
|
|
71
|
+
| nothing: the ledger records evidence and carries no state column | 118 | 3 |
|
|
72
|
+
|
|
73
|
+
So **`never` is measurable in one repository of nine, over 15% of the rows**, and the exposure line — which this
|
|
74
|
+
doctrine defines over it — is undefined in the rest. That is not a defect in those
|
|
75
|
+
ledgers. Recording *what confirmed it* is the Auto job done properly, and a project that
|
|
76
|
+
never asks the human question is making a choice.
|
|
77
|
+
|
|
78
|
+
What is a defect is **doctrine that speaks as though the column were there**. So:
|
|
79
|
+
|
|
80
|
+
- **Where there is no state column, the exposure line says so** and prints no number.
|
|
81
|
+
`templates/exposure.sh` reports `dormant` and names the column headings it looked for.
|
|
82
|
+
A zero would be the reassuring answer to a question nobody asked.
|
|
83
|
+
- **A `verified` that cannot separate a person from a command may not be reported as
|
|
84
|
+
human confirmation.** The script names the column it read, for exactly this reason.
|
|
85
|
+
- **Adding the column later never reaches backwards.** New rows start at `never`;
|
|
86
|
+
retrospective statuses for work nobody actually checked are the failure the
|
|
87
|
+
`evidence-docs` router exists to name, and a back-filled ledger is worse than an absent
|
|
88
|
+
one because it answers the question wrongly instead of not at all.
|
|
89
|
+
|
|
56
90
|
## What stage 8 writes and what stage 10 refuses
|
|
57
91
|
|
|
58
92
|
**A coverage verdict of `review` becomes `none`.** *No check can decide this* is not
|
|
@@ -123,9 +123,15 @@ fi
|
|
|
123
123
|
# file's purpose.
|
|
124
124
|
# NORMALISED first: these ledgers write `**never**`, not `never`. Bold hid three real
|
|
125
125
|
# unverified rows in one member and seven in another, and both reported zero.
|
|
126
|
+
# THE LEADING WORD, not the whole cell. `**observed** — the row exists because …` is a
|
|
127
|
+
# normal way to write a status, and four rows in this family were reported unreadable for
|
|
128
|
+
# explaining themselves. An empty cell still counts, which is why the emptiness test comes
|
|
129
|
+
# before the word is taken.
|
|
126
130
|
awk -F'\t' '{ s=tolower($2); gsub(/[*`]/, "", s); gsub(/^[ \t]+|[ \t]+$/, "", s);
|
|
127
|
-
if (s=="
|
|
128
|
-
|
|
131
|
+
if (s=="") { print; next }
|
|
132
|
+
w=s; sub(/[ \t].*$/, "", w); sub(/[.,;:—-]+$/, "", w);
|
|
133
|
+
if (w=="never" || w=="-" || w=="no" || w=="unverified" ||
|
|
134
|
+
w=="pending" || w=="none") print }' \
|
|
129
135
|
"$TMP/rows" > "$TMP/unverified"
|
|
130
136
|
UNVERIFIED=$(grep -c '' "$TMP/unverified" 2>/dev/null) || UNVERIFIED=0
|
|
131
137
|
|
|
@@ -134,11 +140,13 @@ UNVERIFIED=$(grep -c '' "$TMP/unverified" 2>/dev/null) || UNVERIFIED=0
|
|
|
134
140
|
# it as confirmed is how a shrug becomes a clean bill, which the fixture for this line
|
|
135
141
|
# caught the moment it was written.
|
|
136
142
|
awk -F'\t' '{ s=tolower($2); gsub(/[*`]/, "", s); gsub(/^[ \t]+|[ \t]+$/, "", s);
|
|
137
|
-
if (s=="
|
|
138
|
-
|
|
143
|
+
if (s=="") next;
|
|
144
|
+
w=s; sub(/[ \t].*$/, "", w); sub(/[.,;:—-]+$/, "", w);
|
|
145
|
+
if (w=="never" || w=="-" || w=="no" || w=="unverified" ||
|
|
146
|
+
w=="pending" || w=="none") next;
|
|
139
147
|
if ($2 ~ /[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/) next;
|
|
140
|
-
if (
|
|
141
|
-
|
|
148
|
+
if (w=="pass" || w=="yes" || w=="verified" || w=="ok" || w=="observed" ||
|
|
149
|
+
w=="confirmed" || w=="green" || w=="planted") next;
|
|
142
150
|
print }' "$TMP/rows" > "$TMP/unreadable"
|
|
143
151
|
UNREADABLE=$(grep -c '' "$TMP/unreadable" 2>/dev/null) || UNREADABLE=0
|
|
144
152
|
|
|
@@ -273,7 +281,15 @@ head -"$LIST_MAX" "$TMP/sorted" | while IFS="$(printf '\t')" read -r ship req wh
|
|
|
273
281
|
# than inventing a weight here. Absent is printed as absent, never as a default.
|
|
274
282
|
blast=""
|
|
275
283
|
if [ -f "$BOARD" ]; then
|
|
276
|
-
blast=$(
|
|
284
|
+
blast=$(awk -F'|' -v req="$req" '
|
|
285
|
+
function trim(s) { gsub(/^[ \t]+|[ \t]+$/, "", s); return s }
|
|
286
|
+
# BY HEADER, not by index — the same lesson as the status column, and it was left
|
|
287
|
+
# two lines away for a whole release. `$5` is `Blast` in an eight-column board and
|
|
288
|
+
# `Size` in the ten-column one this repository SEEDS, so a host project`s check-list
|
|
289
|
+
# printed `[blast L]`: the size of the work, labelled as who it hurts.
|
|
290
|
+
tolower(trim($2)) == "id" { for (i = 2; i < NF; i++) if (tolower(trim($i)) == "blast") bcol = i; next }
|
|
291
|
+
bcol && trim($2) == req { print trim($(bcol)); exit }
|
|
292
|
+
' "$BOARD" 2>/dev/null)
|
|
277
293
|
fi
|
|
278
294
|
if [ -n "$blast" ]; then
|
|
279
295
|
printf ' %-10s %-12s %s [blast %s]\n' "$ship" "$req" "$what" "$blast"
|