task-pipeline-skill 1.102.3 → 1.102.4
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 +23 -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/hooks/gate-observer.sh +3 -1
- package/plugins/task-pipeline/hooks/memory-nudge.sh +8 -1
- package/plugins/task-pipeline/hooks/release-gate.sh +31 -5
- package/plugins/task-pipeline/skills/evidence-docs/references/hooks.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/hooks.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
## v1.102.4: the Bash hooks start no process in a project with no run
|
|
2
|
+
|
|
3
|
+
- **Fewer processes per Bash call, same verdicts** (hub board row B-310). The plugin's Bash
|
|
4
|
+
hooks run on every Bash call in every project, and they started processes before learning
|
|
5
|
+
there was no run. Measured by PID delta (macOS allocates PIDs in order; minimum of 25 runs,
|
|
6
|
+
the hook's own bash included): `release-gate.sh` 14, `gate-observer.sh` 3 and
|
|
7
|
+
`memory-nudge.sh` 1, so 18 per Bash call in a project with no `.task-pipeline/run.md`, and 23
|
|
8
|
+
with a run in flight (14, 4 and 5). Now 3 (1, 1, 1) and 11 (5, 4, 2). Three changes:
|
|
9
|
+
`release-gate.sh` tests for the ledger before it reads stdin or starts python3 (`-e`, as
|
|
10
|
+
the python asks `os.path.exists`, so a ledger path that is a directory is still refused as
|
|
11
|
+
unreadable); it splits its `state`, `act`, `why` verdict with parameter expansion instead
|
|
12
|
+
of three `printf | cut` pipelines, keeping `cut`'s field rules, and a verdict of more than
|
|
13
|
+
one line still goes through the pipelines; `gate-observer.sh` reads stdin after the ledger
|
|
14
|
+
test; `memory-nudge.sh` finds its scripts directory from `${BASH_SOURCE[0]}` without
|
|
15
|
+
`$(cd "$(dirname …)" && pwd)`. Behaviour is unchanged: a differential run of the old and
|
|
16
|
+
new hooks over 4,950 cases (eight ledger states, five flows, 30 payloads, python3 working
|
|
17
|
+
and broken) gave 0 differences in exit code, stdout, stderr and ledger contents.
|
|
18
|
+
`test/release_gate_test.py` (74, three new): with no ledger each Bash hook exits 0 silent and starts
|
|
19
|
+
none of python3, cat, cut, dirname (PATH shims log any start; red on 1.102.3, which started
|
|
20
|
+
cat and python3), a negative control that the shims do see python3, and a refusal that
|
|
21
|
+
carries its act and whole reason. `test/memory_nudge_test.py` (43, two new): the run marker is still
|
|
22
|
+
honoured when the hook is started by a bare name or a relative path.
|
|
23
|
+
|
|
1
24
|
## v1.102.3: stamp rows keep their table's shape, one rotation line per quarter, apply_patch gated
|
|
2
25
|
|
|
3
26
|
Guards: 531 → **531**; property checks 15 → **15**. No negative was added: the new checks are
|
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.102.
|
|
15
|
+
| **Version** | 1.102.4 |
|
|
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. The engine is WebKit (Safari) first; `chrome-devtools` is Chrome-only, a stated exception. Every stage's doctrine ships in-repo; user-facing stage 3 requires a valid scenario artifact; super-ux is preferred, with equivalent-provider and inline-fallback paths under the provider contract |
|
|
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.102.
|
|
3
|
+
"version": "1.102.4",
|
|
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"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "task-pipeline",
|
|
4
4
|
"displayName": "Task Pipeline",
|
|
5
5
|
"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/judgment/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 proportional short path for small changes, a loop guard whose ceilings stop and record a blocker, 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); a third, `waves`, takes the whole board and closes it in waves that each finish in one pass. Retro insights can publish upstream as issues, opt-in and redacted.",
|
|
6
|
-
"version": "1.102.
|
|
6
|
+
"version": "1.102.4",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "ssheleg",
|
|
9
9
|
"url": "https://x.com/sshlg93"
|
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
# running a pipeline.
|
|
27
27
|
set -uo pipefail
|
|
28
28
|
|
|
29
|
-
input=$(cat 2>/dev/null || true)
|
|
30
29
|
project="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
31
30
|
ledger="$project/.task-pipeline/run.md"
|
|
31
|
+
# The ledger test comes before stdin is read (hub B-310): with no run, reading the
|
|
32
|
+
# payload starts `cat` for nothing. memory-nudge.sh has always exited unread here.
|
|
32
33
|
[ -f "$ledger" ] || exit 0
|
|
34
|
+
input=$(cat 2>/dev/null || true)
|
|
33
35
|
|
|
34
36
|
HOOK_INPUT="$input" python3 - "$ledger" "$project" <<'PY' 2>/dev/null || true
|
|
35
37
|
import json, os, re, sys, datetime
|
|
@@ -20,7 +20,14 @@
|
|
|
20
20
|
set -uo pipefail
|
|
21
21
|
ledger="${CLAUDE_PROJECT_DIR:-$PWD}/.task-pipeline/run.md"
|
|
22
22
|
[ -f "$ledger" ] || exit 0
|
|
23
|
-
|
|
23
|
+
# The scripts directory without `$(cd "$(dirname …)" && pwd)`, which started two
|
|
24
|
+
# processes per call (hub B-310). `dirname` of a bare name is `.`; a directory that
|
|
25
|
+
# does not exist leaves TP_SCRIPTS empty, as the failed `cd` did.
|
|
26
|
+
here=${BASH_SOURCE[0]}
|
|
27
|
+
case "$here" in */*) here=${here%/*} ;; *) here=. ;; esac
|
|
28
|
+
TP_SCRIPTS="$here/../skills/task-pipeline/scripts"
|
|
29
|
+
[ -d "$TP_SCRIPTS" ] || TP_SCRIPTS=
|
|
30
|
+
TP_SCRIPTS="$TP_SCRIPTS" \
|
|
24
31
|
python3 - "$ledger" <<'PY' 2>/dev/null || true
|
|
25
32
|
import hashlib, json, os, re, sys
|
|
26
33
|
ledger = sys.argv[1]
|
|
@@ -43,11 +43,19 @@
|
|
|
43
43
|
# crashing gate that fails open is worse than no gate, because it reads as one.
|
|
44
44
|
set -uo pipefail
|
|
45
45
|
|
|
46
|
-
input=$(cat 2>/dev/null || true)
|
|
47
|
-
|
|
48
46
|
project="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
49
47
|
ledger="$project/.task-pipeline/run.md"
|
|
50
48
|
|
|
49
|
+
# Narrowness 2, before anything else starts (hub B-310): with no ledger every path
|
|
50
|
+
# below ends in `skip` or `exit 0` with no output, so the answer is known without
|
|
51
|
+
# reading stdin or starting python3. `-e`, not `-f`: the python below asks
|
|
52
|
+
# `os.path.exists`, so a ledger path that is a directory still reaches it and is
|
|
53
|
+
# still refused as unreadable. Leaving stdin unread is what memory-nudge.sh has
|
|
54
|
+
# always done on a project with no run.
|
|
55
|
+
[ -e "$ledger" ] || exit 0
|
|
56
|
+
|
|
57
|
+
input=$(cat 2>/dev/null || true)
|
|
58
|
+
|
|
51
59
|
decide() {
|
|
52
60
|
# The payload travels in the environment, NOT on stdin: the heredoc below IS
|
|
53
61
|
# stdin for `python3 -`, so a script fed that way can never also read the hook's
|
|
@@ -265,9 +273,27 @@ if [ $status -ne 0 ] || [ -z "$verdict" ]; then
|
|
|
265
273
|
exit 2
|
|
266
274
|
fi
|
|
267
275
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
276
|
+
# The verdict is `state<TAB>act<TAB>why`, split in the shell itself rather than by
|
|
277
|
+
# three `printf | cut` pipelines (nine processes per call, hub B-310). Each value is
|
|
278
|
+
# what `cut -fN` gives on one line: a line with no tab is its own field 1, 2 and 3;
|
|
279
|
+
# a line with one tab has an empty field 3; a field ends at the next tab. A verdict
|
|
280
|
+
# of more than one line (a newline inside a declared command or stage id) keeps the
|
|
281
|
+
# original pipelines, so that case reads exactly as before.
|
|
282
|
+
case "$verdict" in
|
|
283
|
+
*$'\n'*)
|
|
284
|
+
state=$(printf '%s' "$verdict" | cut -f1)
|
|
285
|
+
act=$(printf '%s' "$verdict" | cut -f2)
|
|
286
|
+
why=$(printf '%s' "$verdict" | cut -f3) ;;
|
|
287
|
+
*$'\t'*)
|
|
288
|
+
state=${verdict%%$'\t'*}
|
|
289
|
+
rest=${verdict#*$'\t'}
|
|
290
|
+
act=${rest%%$'\t'*}
|
|
291
|
+
case "$rest" in
|
|
292
|
+
*$'\t'*) rest=${rest#*$'\t'}; why=${rest%%$'\t'*} ;;
|
|
293
|
+
*) why= ;;
|
|
294
|
+
esac ;;
|
|
295
|
+
*) state=$verdict act=$verdict why=$verdict ;;
|
|
296
|
+
esac
|
|
271
297
|
|
|
272
298
|
case "$state" in
|
|
273
299
|
skip|ok) exit 0 ;;
|
|
@@ -254,7 +254,7 @@ reusable part:
|
|
|
254
254
|
| Narrowness | Why it is not a smaller feature |
|
|
255
255
|
|---|---|
|
|
256
256
|
| Only outward acts, never ordinary commits | stage 5 commits per task by design; a gate that fights the build loop is removed within a day |
|
|
257
|
-
| Silent where no `.task-pipeline/run.md` exists | enabling the plugin must change nothing in a repository that runs no pipeline |
|
|
257
|
+
| Silent where no `.task-pipeline/run.md` exists, before python3 starts | enabling the plugin must change nothing in a repository that runs no pipeline, and every Bash call there pays these hooks: each Bash hook tests for the ledger before it reads stdin or starts python3, so one Bash call costs three bash processes instead of eighteen (hub B-310; `test/release_gate_test.py`, "with no ledger, the Bash hooks exit 0 silent and start no process") |
|
|
258
258
|
| Reads the ledger, never reruns a suite | `progress.md` already makes the ledger append-only; a second source of truth about "did stage 6 pass" is the failure this file warns about below |
|
|
259
259
|
|
|
260
260
|
**Fail-closed, deliberately.** Every non-zero exit code other than `2` is
|
|
@@ -254,7 +254,7 @@ reusable part:
|
|
|
254
254
|
| Narrowness | Why it is not a smaller feature |
|
|
255
255
|
|---|---|
|
|
256
256
|
| Only outward acts, never ordinary commits | stage 5 commits per task by design; a gate that fights the build loop is removed within a day |
|
|
257
|
-
| Silent where no `.task-pipeline/run.md` exists | enabling the plugin must change nothing in a repository that runs no pipeline |
|
|
257
|
+
| Silent where no `.task-pipeline/run.md` exists, before python3 starts | enabling the plugin must change nothing in a repository that runs no pipeline, and every Bash call there pays these hooks: each Bash hook tests for the ledger before it reads stdin or starts python3, so one Bash call costs three bash processes instead of eighteen (hub B-310; `test/release_gate_test.py`, "with no ledger, the Bash hooks exit 0 silent and start no process") |
|
|
258
258
|
| Reads the ledger, never reruns a suite | `progress.md` already makes the ledger append-only; a second source of truth about "did stage 6 pass" is the failure this file warns about below |
|
|
259
259
|
|
|
260
260
|
**Fail-closed, deliberately.** Every non-zero exit code other than `2` is
|