task-pipeline-skill 1.58.0 → 1.60.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 +79 -0
- package/SKILL-CARD.md +1 -1
- package/package.json +4 -3
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +6 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/progress.md +6 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +34 -5
- package/plugins/task-pipeline/skills/task-pipeline/templates/docgate.sh +43 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,84 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.60.0 — the gate this skill ships had never run on this skill
|
|
4
|
+
|
|
5
|
+
Wiring it in was one line. Running it once found five things, and each was silent in a
|
|
6
|
+
different way:
|
|
7
|
+
|
|
8
|
+
- **It was skipping itself in every submodule checkout.** The section asked `[ -d .git ]`,
|
|
9
|
+
and a submodule's `.git` is a *file* holding a `gitdir:` pointer — the same shape that
|
|
10
|
+
disarmed two negative self-tests in v1.58.0, now found a third time in two days, in the
|
|
11
|
+
shipped gate. It asks `git rev-parse --is-inside-work-tree` now, which knows all three
|
|
12
|
+
shapes.
|
|
13
|
+
- **Its corpus default still named the artifact root as it was before the 2026-08-13
|
|
14
|
+
rename**, so in every migrated project the SHA and propagation sections found nothing and
|
|
15
|
+
reported **dormant** — which reads exactly like having nothing to check. The root is
|
|
16
|
+
resolved now, new name first.
|
|
17
|
+
- **Eleven commit references could not be followed.** Nine are pre-gate history rewritten
|
|
18
|
+
early in this project's life, one is a documentation placeholder that never named a
|
|
19
|
+
commit, and two were branch commits a **squash merge** had replaced — which is the same
|
|
20
|
+
class as the amend above, arriving from a different direction. The two were repointed to
|
|
21
|
+
the commits that carry their work on `main`; the other nine are **enumerated by name**
|
|
22
|
+
in the archive with their date and reason, so the gate passes over exactly those and
|
|
23
|
+
fails on the twelfth. An exception with names, never a floor.
|
|
24
|
+
- **Two decisions named documents that never cited them.** `DEC-0001` and `DEC-0004` are
|
|
25
|
+
now cited in `progress.md` and `companion-skills.md` — which is the propagation contract
|
|
26
|
+
working the moment anything checked it.
|
|
27
|
+
- **One id was reported undefined because the checker could not tell a plant from a
|
|
28
|
+
claim.** A retro entry recording *planted `DEC-0009` while the highest defined id was
|
|
29
|
+
`DEC-0001`* was read as a citation. A line describing a planted defect is sample content
|
|
30
|
+
by the same argument as a fenced block, and `strip_asides` now treats it as one.
|
|
31
|
+
|
|
32
|
+
`npm run test:docs` is a script, and `test:all` calls it, and a guard requires both — a
|
|
33
|
+
gate nobody's aggregate command runs is a gate that goes quiet the first busy week.
|
|
34
|
+
|
|
35
|
+
Guards: 344 → **344**. The change is a gate script and its wiring; every finding above
|
|
36
|
+
was watched being produced by the gate itself, which is the only plant a script that
|
|
37
|
+
reads a project's own git history can have.
|
|
38
|
+
|
|
39
|
+
## v1.59.0 — never amend a commit a record already names
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- **The stamping procedure invited the defect it then had to repair, twice in one
|
|
44
|
+
close-out.** `retrospective.md` says stamp the run with its own commit; the only way to
|
|
45
|
+
know that commit is to make it; so the stamp gets folded in with `--amend` — and the
|
|
46
|
+
amend mints a new SHA, leaving the stamp naming a commit that resolves on the machine
|
|
47
|
+
that wrote it and reaches no clone. It happened here on 2026-08-16 and then again in the
|
|
48
|
+
umbrella twenty minutes later, which is a procedure fault rather than two lapses.
|
|
49
|
+
|
|
50
|
+
The doctrine now says it in one line — **once a file names a SHA, that commit is
|
|
51
|
+
frozen** — states the order that removes the temptation (commit the work, *then* stamp in
|
|
52
|
+
a commit of its own), and names the only repair that does not re-enter the loop: a
|
|
53
|
+
follow-up commit, never a second amend.
|
|
54
|
+
|
|
55
|
+
- **The documentation gate asked the weaker of the two questions.** It required every
|
|
56
|
+
backticked SHA in the retro to *resolve*, and an amended-away commit resolves for as long
|
|
57
|
+
as the object survives locally. It now also requires **reachability from `HEAD`**
|
|
58
|
+
(`git merge-base --is-ancestor`), which is the question a reader two months later is
|
|
59
|
+
actually asking. Watched failing on a purpose-built repository whose stamped commit had
|
|
60
|
+
been amended away: `commit ... resolves but is NOT reachable from HEAD`.
|
|
61
|
+
|
|
62
|
+
- **Three id registers that could never allocate are removed** (`B-45`). They were declared
|
|
63
|
+
over the `fs` backend, whose `reserve` refuses by design, and `agent_sync.py check` had
|
|
64
|
+
been calling it a problem for as long as they stood. A declaration that cannot be served
|
|
65
|
+
is worse than none: it reads as a capability, so nobody writes the procedure it hides —
|
|
66
|
+
and on 2026-08-15 two sessions filed a different `B-073`. Allocation is manual, documented
|
|
67
|
+
in `CLAUDE.md`, and the guard that requires that documentation now fires on the **backend**
|
|
68
|
+
rather than on the declaration, so removing the registers could not retire it.
|
|
69
|
+
|
|
70
|
+
Guards: 344 → **344**. Property checks: 9 → 9. No new plant, and that is the honest
|
|
71
|
+
number: what changed is a gate script (`templates/docgate.sh`) rather than a validator
|
|
72
|
+
guard, and it was watched failing against a purpose-built repository whose stamped commit
|
|
73
|
+
had been amended away — the plant lives in that measurement rather than in the workflow,
|
|
74
|
+
because a gate that runs over a project's own git history cannot be planted from inside a
|
|
75
|
+
copy of this one.
|
|
76
|
+
|
|
77
|
+
- **The coordination snapshot exists and is linked.** `docs/AGENT_SYNC.md` was missing
|
|
78
|
+
entirely, which `check` had also been reporting. Generated from the live configuration and
|
|
79
|
+
linked from `CLAUDE.md`; `agent_sync.py check` → **exit 0, `setup healthy`**, for the first
|
|
80
|
+
time in this repository.
|
|
81
|
+
|
|
3
82
|
## v1.58.0 — a fan-out is not finished when its branches are
|
|
4
83
|
|
|
5
84
|
The graph model this pipeline was audited against in v1.57.0 named one defect and fixed
|
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.60.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.60.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"
|
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
"test": "python3 test/validate.py",
|
|
10
10
|
"test:negatives": "python3 test/negatives.py",
|
|
11
11
|
"test:probe": "python3 test/probe.py --self-test",
|
|
12
|
-
"test:all": "python3 test/validate.py && python3 test/negatives.py && npm run test:probe && npm run test:hooks && npm run test:artifacts",
|
|
12
|
+
"test:all": "python3 test/validate.py && python3 test/negatives.py && npm run test:probe && npm run test:hooks && npm run test:artifacts && npm run test:docs",
|
|
13
13
|
"test:hooks": "python3 test/release_gate_test.py",
|
|
14
|
-
"test:artifacts": "python3 test/artifact_root_test.py && python3 test/migrate_artifacts_test.py"
|
|
14
|
+
"test:artifacts": "python3 test/artifact_root_test.py && python3 test/migrate_artifacts_test.py",
|
|
15
|
+
"test:docs": "bash plugins/task-pipeline/skills/task-pipeline/templates/docgate.sh"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"bin",
|
|
@@ -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.60.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ssheleg",
|
|
8
8
|
"url": "https://x.com/sshlg93"
|
|
@@ -8,6 +8,12 @@ something isn't installed.
|
|
|
8
8
|
What remains is a short list of **optional** companions that make individual stages
|
|
9
9
|
better, plus one that is required only for user-facing work.
|
|
10
10
|
|
|
11
|
+
|
|
12
|
+
> **Decision `DEC-0004`** — two browser channels ranked by nothing, one detection rule,
|
|
13
|
+
> stop at the first that answers. The step stays **recommended and never a gate**: a gate
|
|
14
|
+
> an environment cannot satisfy is one an agent learns to report around, and *verified by
|
|
15
|
+
> reading the diff* already prices the absence honestly (`docs/DECISIONS.md`).
|
|
16
|
+
|
|
11
17
|
## Contents
|
|
12
18
|
|
|
13
19
|
- Built in — nothing to install
|
|
@@ -18,6 +18,12 @@ maintains them and the next run reads them as current.
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
|
|
22
|
+
> **Decision `DEC-0001`** — the hand-back names what this run filed, and the join from a
|
|
23
|
+
> run to its rows already exists: the board's `Source` column. It deliberately buys no
|
|
24
|
+
> coverage number, because a required minimum is a run filing a throwaway row to make
|
|
25
|
+
> the count agree (`docs/DECISIONS.md`).
|
|
26
|
+
|
|
21
27
|
## Contents
|
|
22
28
|
|
|
23
29
|
- The two boundaries, and only those two
|
|
@@ -32,6 +32,7 @@ file exists to stop.
|
|
|
32
32
|
|
|
33
33
|
- Write the entry only for a divergence — and name the layer that owned it
|
|
34
34
|
- Every lesson carries its commit
|
|
35
|
+
- Never amend a commit a record already names
|
|
35
36
|
- The stamp table is capped at ten, and *one line per run* was never a cap
|
|
36
37
|
- `publish:` is a line in the verdict, not a silence
|
|
37
38
|
- Rotation — the archive is how pruning stops losing things
|
|
@@ -76,11 +77,39 @@ message and the parent, so `git show <sha>` reconstructs the entire incident two
|
|
|
76
77
|
months later — which is exactly when the same class comes back and somebody needs
|
|
77
78
|
to know whether this was already understood.
|
|
78
79
|
|
|
79
|
-
**Every SHA must resolve
|
|
80
|
-
document may not send a reader to something
|
|
81
|
-
mechanical: the
|
|
82
|
-
<sha>^{commit}` over every backticked SHA in the retro
|
|
83
|
-
([`gates.md`](gates.md)).
|
|
80
|
+
**Every SHA must resolve — and resolving is not enough.** This is
|
|
81
|
+
[`learned.md`](learned.md) rule 14 — *a document may not send a reader to something
|
|
82
|
+
absent* — applied to history, and it is mechanical: the documentation gate runs
|
|
83
|
+
`git rev-parse --verify --quiet <sha>^{commit}` over every backticked SHA in the retro
|
|
84
|
+
and its archive ([`gates.md`](gates.md)).
|
|
85
|
+
|
|
86
|
+
**But a commit that was amended away still resolves on the machine that amended it**,
|
|
87
|
+
and exists in no clone. The gate therefore also requires each SHA to be **reachable
|
|
88
|
+
from `HEAD`** — `git merge-base --is-ancestor <sha> HEAD` — because that is the
|
|
89
|
+
question a reader two months from now is actually asking, and the weaker one passes
|
|
90
|
+
for as long as the object survives locally.
|
|
91
|
+
|
|
92
|
+
## Never amend a commit a record already names
|
|
93
|
+
|
|
94
|
+
Measured 2026-08-16, twice in one close-out and twenty minutes apart. The sequence is
|
|
95
|
+
seductive because each step is right on its own: stamp the run with its commit → the
|
|
96
|
+
stamp is part of the run, so fold it in with `--amend` → the amend mints a new SHA →
|
|
97
|
+
the stamp now names a commit that will never reach the remote.
|
|
98
|
+
|
|
99
|
+
The rule is one line and it is absolute: **once a file names a SHA, that commit is
|
|
100
|
+
frozen.** A correction goes in a *follow-up commit*, never a second amend — amending to
|
|
101
|
+
repair a stamp is the loop that produced the problem, and the second attempt lands in the
|
|
102
|
+
same place as the first.
|
|
103
|
+
|
|
104
|
+
Practically, that makes the order:
|
|
105
|
+
|
|
106
|
+
1. commit the work;
|
|
107
|
+
2. **then** stamp, in a commit of its own, naming the commit from step 1;
|
|
108
|
+
3. prune and write the entry in that same second commit, or a third.
|
|
109
|
+
|
|
110
|
+
The stamp costs one line and one commit. A run that folds it back into the work to keep
|
|
111
|
+
the history tidy is trading a reader's ability to find the incident for the appearance of
|
|
112
|
+
tidiness — and the reader is the entire reason the stamp exists.
|
|
84
113
|
|
|
85
114
|
## The stamp table is capped at ten, and *one line per run* was never a cap
|
|
86
115
|
|
|
@@ -34,7 +34,18 @@ DEC_FILE=${DEC_FILE:-$DOCS_DIR/DECISIONS.md}
|
|
|
34
34
|
ADR_DIR=${ADR_DIR:-$DOCS_DIR/adr}
|
|
35
35
|
OQ_FILE=${OQ_FILE:-$DOCS_DIR/OPEN_QUESTIONS.md}
|
|
36
36
|
MAP_FILE=${MAP_FILE:-$DOCS_DIR/DOCMAP.md}
|
|
37
|
-
|
|
37
|
+
# The artifact root is RESOLVED, not assumed. It was renamed `superpowers` → `evidence`
|
|
38
|
+
# on 2026-08-13 (v1.53.0 made it resolvable, v0.46.0 moved the family), and this default
|
|
39
|
+
# still named the old one — so in every migrated project the SHA and propagation sections
|
|
40
|
+
# below found no corpus and went **dormant**, which reads exactly like having nothing to
|
|
41
|
+
# check. Measured 2026-08-16 on this skill's own repository. Prefer the new name, fall
|
|
42
|
+
# back to the old, and a project that has neither gets the dormant message it deserves.
|
|
43
|
+
if [ -z "${RETRO_GLOB:-}" ]; then
|
|
44
|
+
if [ -d "$DOCS_DIR/evidence" ]; then RETRO_GLOB="$DOCS_DIR/evidence"
|
|
45
|
+
elif [ -d "$DOCS_DIR/superpowers" ]; then RETRO_GLOB="$DOCS_DIR/superpowers"
|
|
46
|
+
else RETRO_GLOB="$DOCS_DIR/evidence"
|
|
47
|
+
fi
|
|
48
|
+
fi
|
|
38
49
|
|
|
39
50
|
# ---------- ratchets: a floor may only fall. Raising one is a decision. ----------
|
|
40
51
|
# THE TWO FLOORS ARE DIFFERENT KINDS. Mixing them up is why this is spelled out.
|
|
@@ -68,6 +79,13 @@ strip_asides() {
|
|
|
68
79
|
awk '
|
|
69
80
|
/^[ \t]*(```|~~~)/ { infence = !infence; print ""; next }
|
|
70
81
|
infence { print ""; next }
|
|
82
|
+
# A line describing a PLANTED defect quotes ids that were never meant to exist —
|
|
83
|
+
# that is the payload of a negative self-test, written down so the incident can be
|
|
84
|
+
# read later. It is sample content by the same argument as a fenced block, and the
|
|
85
|
+
# checker cannot otherwise tell an id being USED from an id being DISCUSSED. Found
|
|
86
|
+
# 2026-08-16: a retro entry recording `planted DEC-0009 while the highest defined id
|
|
87
|
+
# was DEC-0001` was reported as citing an undefined decision.
|
|
88
|
+
/planted/ { print ""; next }
|
|
71
89
|
{
|
|
72
90
|
line = $0
|
|
73
91
|
# A comment carried over from an earlier line.
|
|
@@ -430,25 +448,45 @@ fi
|
|
|
430
448
|
# ---------- 9. every commit SHA named in the retro resolves ----------
|
|
431
449
|
# A file:line rots at the next edit; a SHA carries the diff, the message and the
|
|
432
450
|
# parent forever. A document may not send a reader to something absent.
|
|
433
|
-
|
|
451
|
+
# `[ -d .git ]` is the wrong question and it silently disabled this whole section for
|
|
452
|
+
# every submodule and every linked worktree — where `.git` is a FILE holding a `gitdir:`
|
|
453
|
+
# pointer. Measured 2026-08-16 on this skill's own repository, checked out as a submodule:
|
|
454
|
+
# the section printed `skip` while five SHAs in the archive did not resolve at all. Ask git
|
|
455
|
+
# whether it is inside a work tree; it knows about all three shapes and this does not.
|
|
456
|
+
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
434
457
|
skipmsg "commit-SHA resolution — not a git working tree"
|
|
435
458
|
elif [ ! -d "$RETRO_GLOB" ]; then
|
|
436
459
|
dormant "commit-SHA resolution — no $RETRO_GLOB yet"
|
|
437
460
|
else
|
|
438
461
|
: > "$TMP/sha"
|
|
462
|
+
# An enumerated exception, never a floor. A commit whose history was rewritten before any
|
|
463
|
+
# of this was gated cannot be repaired without inventing a mapping, and a frozen record of
|
|
464
|
+
# a past run is not rewritten. Such SHAs are listed by name in a `docgate:known-dead`
|
|
465
|
+
# marker inside the retro corpus itself — one home, with the reason in prose beside it —
|
|
466
|
+
# so this passes over exactly those and still fails on the next one.
|
|
467
|
+
DEAD=$(grep -rho 'docgate:known-dead[^>]*' "$RETRO_GLOB" 2>/dev/null | sed 's/docgate:known-dead//' | tr -s ' \n' ' ')
|
|
439
468
|
find "$RETRO_GLOB" -type f -name '*.md' 2>/dev/null | sort | while IFS= read -r f; do
|
|
440
469
|
grep -n -o '`[0-9a-f][0-9a-f]*`' "$(flat_of "$f")" 2>/dev/null |
|
|
441
470
|
while IFS=: read -r ln tok; do
|
|
442
471
|
s=$(echo "$tok" | tr -d '`')
|
|
443
472
|
case ${#s} in 7|8|9|10|11|12|40) ;; *) continue ;; esac
|
|
444
|
-
|
|
473
|
+
case " $DEAD " in *" $s "*) continue ;; esac
|
|
474
|
+
if ! git rev-parse --verify --quiet "$s^{commit}" >/dev/null 2>&1; then
|
|
445
475
|
echo "$f:$ln: commit \`$s\` does not resolve" >> "$TMP/sha"
|
|
476
|
+
# Resolving is the weaker half. A commit that was AMENDED AWAY still resolves on
|
|
477
|
+
# the machine that amended it and reaches no clone — measured 2026-08-16, twice in
|
|
478
|
+
# one close-out: the stamp named the run's commit, the commit was amended to carry
|
|
479
|
+
# the stamp, and the SHA the stamp recorded stopped being reachable. Ask the
|
|
480
|
+
# question a reader actually has: is it in this history at all.
|
|
481
|
+
elif ! git merge-base --is-ancestor "$s^{commit}" HEAD >/dev/null 2>&1; then
|
|
482
|
+
echo "$f:$ln: commit \`$s\` resolves but is NOT reachable from HEAD — amended away, or on a branch this checkout does not have" >> "$TMP/sha"
|
|
483
|
+
fi
|
|
446
484
|
done
|
|
447
485
|
done
|
|
448
486
|
if [ -s "$TMP/sha" ] 2>/dev/null; then
|
|
449
|
-
err "
|
|
487
|
+
err "commit reference(s) a clone could not follow:"; sed 's/^/ /' "$TMP/sha"
|
|
450
488
|
else
|
|
451
|
-
ok "every commit reference in $RETRO_GLOB resolves"
|
|
489
|
+
ok "every commit reference in $RETRO_GLOB resolves AND is reachable from HEAD"
|
|
452
490
|
fi
|
|
453
491
|
fi
|
|
454
492
|
|