task-pipeline-skill 1.86.1 → 1.86.3
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 +38 -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/evidence-docs/references/hooks.md +10 -5
- package/plugins/task-pipeline/skills/task-pipeline/references/hooks.md +10 -5
- package/plugins/task-pipeline/skills/task-pipeline/templates/hooks.example.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
## v1.86.3 — the release declares the stamp it does not carry, eighth time
|
|
2
|
+
|
|
3
|
+
`v1.86.2` was tagged and refused by its own release workflow: `npm run test:all` against
|
|
4
|
+
the tag's tree found the version named nowhere in `retro.md`'s `## Releases that carry no
|
|
5
|
+
stamp`. Nothing published under it — the tag exists, the release does not, npm never
|
|
6
|
+
served it. The tree had passed `npm test` locally and CI's `validate` job; the release
|
|
7
|
+
runs `test:all`, and `R-010` says to run exactly that against the tree you are about to
|
|
8
|
+
tag. Read that evening, skipped that evening.
|
|
9
|
+
|
|
10
|
+
The v1.86.2 payload is unchanged. This release adds the declaration for both versions.
|
|
11
|
+
|
|
12
|
+
## v1.86.2 — the filter this skill exported filtered nothing
|
|
13
|
+
|
|
14
|
+
Claude Code 2.1.270 started printing `hooks.json: unknown key "if" … ignored` at session
|
|
15
|
+
start for a sibling plugin. The same shape has been in this skill's one shipped template
|
|
16
|
+
since 2026-08-03, and every project that copied it into `.claude/settings.json` got a
|
|
17
|
+
documentation gate that ran on **every** Bash call — a red gate refused `ls`, not commits.
|
|
18
|
+
|
|
19
|
+
Guards: 429 → **429**, property checks 15 → **15** — the regression for this release is
|
|
20
|
+
`test/audit_regressions/fix-hk-02.py`, run by `npm test`, and NOT a workflow step:
|
|
21
|
+
`validate.yml` sits at 511,941 of GitHub's 512,000 bytes (#91), and a 59-byte headroom holds
|
|
22
|
+
no step. It plants the old shape into a copy and requires the validator to refuse it by name.
|
|
23
|
+
|
|
24
|
+
- **`"if": "Bash(git commit *)"` sat beside `matcher`, and a matcher group is only
|
|
25
|
+
`matcher` + `hooks`.** Read out of the 2.1.270 binary's schema: `if` exists on a command
|
|
26
|
+
handler only. Moved there in `templates/hooks.example.json`; the group's `_note` moved to
|
|
27
|
+
a top-level `_filter_note` for the same reason, since the block is copied verbatim into a
|
|
28
|
+
settings file.
|
|
29
|
+
- **`references/hooks.md` said "beside `matcher`" and now says "inside the handler,
|
|
30
|
+
beside `type` and `command`"** — the worked example too; the evidence-docs mirror was
|
|
31
|
+
regenerated with `fix-ed-01.01.py --sync`. The dated 2026-08-03 documentation-track plan
|
|
32
|
+
keeps its wording.
|
|
33
|
+
- **A new validator check refuses any key the hook schema does not know** at either level
|
|
34
|
+
and requires exactly one handler-level `Bash(git commit *)`; `fix-hk-02.py` plants the
|
|
35
|
+
pre-v1.86.2 shape back and watches the check fire. `claude plugin validate
|
|
36
|
+
--strict` passes the defective file, so a repo gate is the only place this fails before a
|
|
37
|
+
session start.
|
|
38
|
+
|
|
1
39
|
## v1.86.1 — the release declares the stamp it does not carry
|
|
2
40
|
|
|
3
41
|
`v1.86.0` was tagged and refused: the run-stamp gate reads the tag's own tree, a
|
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.86.
|
|
15
|
+
| **Version** | 1.86.3 |
|
|
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.86.
|
|
3
|
+
"version": "1.86.3",
|
|
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 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.",
|
|
6
|
-
"version": "1.86.
|
|
6
|
+
"version": "1.86.3",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "ssheleg",
|
|
9
9
|
"url": "https://x.com/sshlg93"
|
|
@@ -129,8 +129,13 @@ machine, and the first surprising denial is debugged in the wrong project.
|
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
- a tool-name pattern (`Edit|Write|…`), or `"*"` for every call;
|
|
132
|
-
- for a specific shell command, add `"if": "Bash(git commit *)"`
|
|
133
|
-
`"
|
|
132
|
+
- for a specific shell command, add `"if": "Bash(git commit *)"` **inside the
|
|
133
|
+
handler object**, beside `"type"` and `"command"` — never beside `"matcher"`.
|
|
134
|
+
A matcher group is only `matcher` + `hooks`; a key Claude Code does not know
|
|
135
|
+
there is ignored, and from 2.1.270 announced at every session start as
|
|
136
|
+
`hooks.json: unknown key "if" … ignored`. This skill's own template carried it
|
|
137
|
+
at group level until v1.86.2, so its gate filtered nothing and ran on every
|
|
138
|
+
Bash call.
|
|
134
139
|
|
|
135
140
|
`if` uses **permission-rule syntax** (`Bash(git *)`, `Edit(*.ts)`) and is evaluated
|
|
136
141
|
**only on tool events** — `PreToolUse`, `PostToolUse`, `PostToolUseFailure`,
|
|
@@ -177,9 +182,9 @@ the project's `.claude/settings.json`.
|
|
|
177
182
|
|
|
178
183
|
```json
|
|
179
184
|
{ "hooks": { "PreToolUse": [
|
|
180
|
-
{ "matcher": "Bash",
|
|
181
|
-
"hooks": [{ "type": "command", "
|
|
182
|
-
"command": "bash scripts/check-docs.sh >&2 || exit 2" }] } ] } }
|
|
185
|
+
{ "matcher": "Bash",
|
|
186
|
+
"hooks": [{ "type": "command", "if": "Bash(git commit *)", "shell": "bash",
|
|
187
|
+
"timeout": 60, "command": "bash scripts/check-docs.sh >&2 || exit 2" }] } ] } }
|
|
183
188
|
```
|
|
184
189
|
|
|
185
190
|
`|| exit 2` is the contract, not a flourish: without it the gate's own `exit 1`
|
|
@@ -129,8 +129,13 @@ machine, and the first surprising denial is debugged in the wrong project.
|
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
- a tool-name pattern (`Edit|Write|…`), or `"*"` for every call;
|
|
132
|
-
- for a specific shell command, add `"if": "Bash(git commit *)"`
|
|
133
|
-
`"
|
|
132
|
+
- for a specific shell command, add `"if": "Bash(git commit *)"` **inside the
|
|
133
|
+
handler object**, beside `"type"` and `"command"` — never beside `"matcher"`.
|
|
134
|
+
A matcher group is only `matcher` + `hooks`; a key Claude Code does not know
|
|
135
|
+
there is ignored, and from 2.1.270 announced at every session start as
|
|
136
|
+
`hooks.json: unknown key "if" … ignored`. This skill's own template carried it
|
|
137
|
+
at group level until v1.86.2, so its gate filtered nothing and ran on every
|
|
138
|
+
Bash call.
|
|
134
139
|
|
|
135
140
|
`if` uses **permission-rule syntax** (`Bash(git *)`, `Edit(*.ts)`) and is evaluated
|
|
136
141
|
**only on tool events** — `PreToolUse`, `PostToolUse`, `PostToolUseFailure`,
|
|
@@ -177,9 +182,9 @@ the project's `.claude/settings.json`.
|
|
|
177
182
|
|
|
178
183
|
```json
|
|
179
184
|
{ "hooks": { "PreToolUse": [
|
|
180
|
-
{ "matcher": "Bash",
|
|
181
|
-
"hooks": [{ "type": "command", "
|
|
182
|
-
"command": "bash scripts/check-docs.sh >&2 || exit 2" }] } ] } }
|
|
185
|
+
{ "matcher": "Bash",
|
|
186
|
+
"hooks": [{ "type": "command", "if": "Bash(git commit *)", "shell": "bash",
|
|
187
|
+
"timeout": 60, "command": "bash scripts/check-docs.sh >&2 || exit 2" }] } ] } }
|
|
183
188
|
```
|
|
184
189
|
|
|
185
190
|
`|| exit 2` is the contract, not a flourish: without it the gate's own `exit 1`
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "EXAMPLE — copy this block into the project's .claude/settings.json. Doctrine: references/hooks.md. Hooks exist ONLY in Claude Code; on any other agent the same rule runs as a self-check and the run is recorded 'ungated'. Never describe a project as protected when its agents run elsewhere.",
|
|
3
3
|
"_contract": "A PreToolUse hook blocks in one of two ways: exit 2 with the reason on stderr (stdout is ignored), or exit 0 with {\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"...\"}} on stdout. ANY OTHER EXIT CODE IS NON-BLOCKING, so a crashing guard fails open and stops guarding without announcing it. That is why the command below ends in '|| exit 2' — the gate's own 'exit 1' would otherwise land in the non-blocking branch and the commit would proceed.",
|
|
4
|
+
"_filter_note": "Refuse a commit while the documentation gate is red. Matched narrowly: the matcher is free, the script is not. The `if` filter sits ON THE HANDLER, beside `type`/`command` — never beside `matcher`: a matcher group is only `matcher` + `hooks`, and a key Claude Code does not know there is ignored (and reported at session start from 2.1.270). Until v1.86.2 this template carried `if` at group level, so the gate ran on EVERY Bash call in every project that copied it, and a red docs gate refused every shell command rather than the commit.",
|
|
4
5
|
"hooks": {
|
|
5
6
|
"PreToolUse": [
|
|
6
7
|
{
|
|
7
|
-
"_note": "Refuse a commit while the documentation gate is red. Matched narrowly: the matcher is free, the script is not.",
|
|
8
8
|
"matcher": "Bash",
|
|
9
|
-
"if": "Bash(git commit *)",
|
|
10
9
|
"hooks": [
|
|
11
10
|
{
|
|
12
11
|
"type": "command",
|
|
12
|
+
"if": "Bash(git commit *)",
|
|
13
13
|
"shell": "bash",
|
|
14
14
|
"timeout": 60,
|
|
15
15
|
"command": "bash scripts/check-docs.sh >&2 || exit 2"
|