task-pipeline-skill 1.8.0 → 1.8.1

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 CHANGED
@@ -1,5 +1,63 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.8.1 — 2026-08-03
4
+
5
+ ### Fixed — eight findings from a code-and-contradiction audit of 1.8.0
6
+
7
+ A third pass, on a third axis: the first read for contradictions, the second measured
8
+ against Anthropic's guidance, this one went after the **code** and the **invariants
9
+ between files**. Everything below was proven before the fix and again after.
10
+
11
+ **Fifteen broken cross-references, eleven of them pointing at a section about
12
+ something else.** Every per-stage freedom label cited `gates.md → Axis B` — which is
13
+ the *enforcement ladder* and contains no mention of degrees of freedom. Two more
14
+ cited sections that do not exist at all (`gates.md → progressive arming`,
15
+ `review.md → Final review`). This is the failure `references/learned.md` keeps as a
16
+ review question rather than a rule: *"a stale reference was replaced with a FALSE
17
+ one — the new target existed and said nothing about the subject."* The link checker
18
+ proved every file resolved and could not see it.
19
+
20
+ It is a rule now. `gates.md` gained the two sections the citations were reaching for
21
+ — **Axis C — degrees of freedom** and **Progressive arming** — and a guard checks
22
+ every ``file.md → *Section*`` pointer against the target's actual headings. Measured
23
+ before shipping: whitespace is normalised first, because a citation wrapped across
24
+ two lines is not a defect and six were reported as such.
25
+
26
+ **Both installers created the shadow copy this family exists to prune.**
27
+ `install.sh` and `bin/task-pipeline.js` write a plain copy to
28
+ `~/.claude/skills/task-pipeline`; the launcher (`sshlg-skills`) deletes exactly those
29
+ because while the plugin channel is active a plain copy **shadows it and keeps
30
+ serving the version it was copied from**. `CLAUDE.md` documented the shadow-creating
31
+ form (`--force`) as the local install path. Both installers now **refuse when a
32
+ plugin install is detected**, name the plugin commands instead, and take `--force`
33
+ only as a deliberate override.
34
+
35
+ **The npm package did not contain what the README points at.** `SKILL-CARD.md` and
36
+ the whole `evals/` directory were outside `files[]` while the shipped README linked
37
+ both — and `CONTRIBUTING.md`, `SECURITY.md` and `CODE_OF_CONDUCT.md` had been
38
+ dangling for npm consumers far longer. Rule 14 — *a document may not send a reader
39
+ to something absent* — applied to the artefact that is actually published. All are
40
+ packaged now, and a guard holds every relative README link to `files[]`.
41
+
42
+ **Living documents restated a guard count that had moved.** `SKILL-CARD.md` and
43
+ `evals/RESULTS.md` claimed 46 after the suite reached 50. Rule 8 — *compute, never
44
+ restate* — had never been applied to this repository's own prose. It is now: the
45
+ count is compared against the negative self-tests the workflow defines, and the
46
+ guard caught its own author within the minute, when adding three tests made the
47
+ freshly-corrected numbers stale again. CHANGELOG entries are exempt; they record
48
+ what a past release shipped.
49
+
50
+ **The contributor invariants were numbered 1,2,3,4,5,6,10,7,8,9 — and number 8
51
+ documented the opposite of what is enforced**, still requiring the description to
52
+ *open* with `Use when` after v1.8.0 made that a failure. Rewritten: sixteen
53
+ invariants, in order, each matching a guard that exists.
54
+
55
+ **Smaller:** the seeded gate's empty-project failure named only `docs/` while it also
56
+ scans the repository root, and offered no remedy — it now names both and says what to
57
+ do; `CLAUDE.md` gained the `evals/run.py` row it never had.
58
+
59
+ Three new guards, each with a negative self-test watched failing.
60
+
3
61
  ## v1.8.0 — 2026-08-03
4
62
 
5
63
  ### Added — the skill now meets Anthropic's own authoring guidance, measurably
@@ -0,0 +1,38 @@
1
+ # Code of conduct
2
+
3
+ ## The short version
4
+
5
+ Be decent. Argue with the idea, never with the person. Assume the other side read
6
+ the docs and still disagrees for a reason.
7
+
8
+ ## Expected
9
+
10
+ - **Technical criticism is welcome and wanted** — this repo is opinionated prose,
11
+ and the opinions get better under pressure. Bring the failure case, the file and
12
+ the line.
13
+ - Accept that a maintainer may decline a change and say why. "Out of scope" is a
14
+ legitimate answer.
15
+ - Respect that contributors work in different languages, time zones and
16
+ experience levels. English is the working language here; imperfect English is
17
+ never a reason to dismiss a point.
18
+
19
+ ## Not accepted
20
+
21
+ Personal attacks, harassment of any kind, demeaning or discriminatory comments,
22
+ sexualized language or imagery, publishing someone's private information, and
23
+ sustained disruption of discussions.
24
+
25
+ ## Scope
26
+
27
+ Applies to issues, pull requests, discussions, commit messages and any other
28
+ project space, and to public spaces when someone is representing the project.
29
+
30
+ ## Enforcement
31
+
32
+ Report anything that crosses the line to **[@sshlg on Telegram](https://t.me/sshlg)**
33
+ or via [GitHub's report abuse](https://github.com/contact/report-abuse) flow. Reports
34
+ are handled privately. Depending on severity the response is a warning, removal of
35
+ the offending content, or a block from the project.
36
+
37
+ Maintainers hold themselves to the same standard; a maintainer who breaks it should
38
+ expect to hear about it publicly.
@@ -0,0 +1,215 @@
1
+ # Contributing to task-pipeline
2
+
3
+ Thanks for taking the time. This repo ships a **skill**, not a program: almost
4
+ everything in it is prose that an agent reads and acts on. That makes two things
5
+ unusually important — the doctrine must not contradict itself across surfaces, and
6
+ the structural validator must stay able to fail.
7
+
8
+ ## Getting set up
9
+
10
+ No build step, no dependencies. You need `python3` (validator), `node` ≥ 16 (npm
11
+ installer), and `bash`.
12
+
13
+ ```bash
14
+ git clone https://github.com/ssheleg/task-pipeline
15
+ cd task-pipeline
16
+ npm test # == python3 test/validate.py
17
+ ```
18
+
19
+ `npm test` must print `PASS: task-pipeline structure valid` before you open a PR.
20
+
21
+ That proves the repo is well-formed. It does **not** prove the validator is
22
+ anything more than a decoration — for that, every guard has to be watched
23
+ rejecting a planted defect:
24
+
25
+ ```bash
26
+ npm run test:negatives # python3 test/negatives.py
27
+ npm run test:all # both, in order
28
+ ```
29
+
30
+ The corruptions live in [`.github/workflows/validate.yml`](.github/workflows/validate.yml)
31
+ and `test/negatives.py` reads them from there — never duplicated, because a second
32
+ copy of a corruption is a second thing to drift. The runner also tells a **broken
33
+ test** from a **guard that didn't fire**: if a planted defect changed nothing, the
34
+ validator passing means the test proved nothing, and it is reported as `BROKEN`
35
+ rather than as a failure of the guard.
36
+
37
+ **Corrupt files in python, never with `sed -i`.** BSD sed needs an argument GNU sed
38
+ refuses, and `0,/re/` does not exist on BSD at all — there it edits nothing
39
+ silently, and the test reads as a guard that failed. The validator rejects `sed -i`
40
+ in the workflow for exactly this reason: a self-test that only runs on CI cannot be
41
+ used while you are writing the guard, which is the moment it is worth most.
42
+
43
+ To try your change in a real agent:
44
+
45
+ ```bash
46
+ ./install.sh --force # ~/.claude/skills/task-pipeline + the command
47
+ node bin/task-pipeline.js --force # the same, through the npm installer
48
+ ```
49
+
50
+ ## Repository layout
51
+
52
+ | Path | What it is |
53
+ |---|---|
54
+ | `plugins/task-pipeline/skills/task-pipeline/SKILL.md` | the orchestrator — the entry point every agent reads first |
55
+ | `…/references/*.md` | the built-in stage doctrine (one file per stage or concern) |
56
+ | `…/templates/*.md` | skeletons seeded into a host project (brief, carry-over, `CONTEXT.md`, ADR) |
57
+ | `…/pipeline.schema.json` | the universal pipeline-config contract |
58
+ | `…/pipeline.example.json` | this plugin's own flow expressed against that contract |
59
+ | `plugins/task-pipeline/commands/task-pipeline.md` | the `/task-pipeline` slash command |
60
+ | `cursor/rules/task-pipeline.mdc` | the Cursor channel — **self-contained**, no relative links |
61
+ | `bin/task-pipeline.js`, `install.sh` | the two installers |
62
+ | `test/validate.py` | the structural validator |
63
+
64
+ ## The invariants
65
+
66
+ These are what the validator enforces. Breaking one is not a style disagreement —
67
+ it ships a wrong pipeline to every install. Numbered in reading order; the numbers
68
+ are labels, not priorities.
69
+
70
+ **1. Four-way version sync.** `package.json`, `.claude-plugin/marketplace.json`
71
+ (`plugins[0].version`), `plugins/task-pipeline/.claude-plugin/plugin.json` and the
72
+ top `## vX.Y.Z` heading in `CHANGELOG.md` must all carry the same version.
73
+ `SKILL-CARD.md`'s Version row is held to it too.
74
+
75
+ **2. The stage list lives on three surfaces and may not drift.** `SKILL.md`'s
76
+ table, `references/stages.md`'s per-stage sections, and `pipeline.example.json`.
77
+ Stage ids, names and **gate types** are compared across all three. Each stage's own
78
+ doctrine file states its gate type too and must agree with the config.
79
+
80
+ **3. Every human-facing description must name the flow's final stage, last.** The
81
+ package, marketplace, plugin, skill, command, Cursor-rule and README blurbs are the
82
+ only thing most people ever read. The validator derives the last stage from
83
+ `pipeline.example.json` and holds every blurb to it.
84
+
85
+ **4. No hardcoded vendor model ids.** Anywhere in the shipped skill, the README, the
86
+ command or the Cursor rule. Name the **tier**, never a string; stage configs use the
87
+ provider-agnostic tokens `default` / `inherit`.
88
+
89
+ **5. Every `references/*.md` must be reachable from `SKILL.md`**, directly or
90
+ transitively. An unreferenced file is dead context that ships and is never read.
91
+
92
+ **6. No external provider may substitute for built-in stage doctrine.**
93
+ `pipeline.example.json`'s `skills[]` may not name one for the stages whose doctrine
94
+ ships here (2, 3-spec, 4, 5, 6, 10). The optional tools — `context7`, `figma`,
95
+ `graphify`, `wiki-query` / `wiki-update` — and the UI-required `super-ux:*` track are
96
+ the enumerated exceptions, named deliberately.
97
+
98
+ **7. Stage 0 is mandatory and manual; stage 10 is manual and demands evidence; the
99
+ stage-4 gate is a set comparison.** These three are the spine, asserted in the
100
+ shipped config.
101
+
102
+ **8. `SKILL.md` frontmatter stays under 1024 characters, and the description says
103
+ WHAT before WHEN.** Anthropic's authoring guidance requires both halves — a
104
+ capability statement in third person, then the `Use when …` trigger — and Russian
105
+ trigger aliases ride beside the English ones. *(Before v1.8.0 this invariant demanded
106
+ the description **open** with `Use when`, which enforced the trigger half and left
107
+ the capability optional. The validator now rejects that shape.)*
108
+
109
+ **9. Relative links resolve.** Every relative markdown link in every file outside a
110
+ fenced code block must point at a path that exists.
111
+
112
+ **10. A seeded template must keep the seeded gate green — in both register shapes.**
113
+ `templates/docgate.sh` is run by `npm test` over two scratch projects: one seeded
114
+ from `docmap.md` / `decisions.md` / `open-questions.md` / `retro.md`, and one built
115
+ from `adr.md`'s own fenced example. Each must exit `0`, **report the shape it
116
+ found**, and run a minimum of live checks — because every section can go `dormant`,
117
+ and a gate blind to a shape passes exactly like one that reads it. Change a template
118
+ → run `npm test`, not just your eyes.
119
+
120
+ **11. Every reference over 100 lines carries a `## Contents` list**, and the list is
121
+ compared against that file's own `##` headings. The guidance asks for it because a
122
+ long file gets previewed with a partial read; the comparison is because a hand-kept
123
+ list is a second source that goes stale on the next heading.
124
+
125
+ **12. A section-qualified citation must name a section that exists.**
126
+ A citation of the form `file.md → *Section*` is checked against the target's headings. The
127
+ link checker proves the file resolves; only this proves the pointer is not false.
128
+
129
+ **13. Numbers stated in living documents are computed, not restated.** The guard
130
+ count in `README.md`, `SKILL-CARD.md` and `evals/RESULTS.md` is compared against the
131
+ negative self-tests the workflow defines. CHANGELOG entries are exempt — they record
132
+ what a past release shipped.
133
+
134
+ **14. Every relative link in `README.md` resolves inside the published package.**
135
+ `package.json` → `files[]` must ship whatever the README points at, or the link
136
+ dangles for every npm consumer.
137
+
138
+ **15. `SKILL-CARD.md` answers every risk indicator** and carries the current
139
+ version. It is the registry entry a consumer reviews before deploying, and an
140
+ omitted row reads as "does not apply".
141
+
142
+ **16. The evaluation suite covers all five dimensions** and `evals/run.py` accepts
143
+ it. Running it is a human step; the suite existing is not.
144
+
145
+ ## Adding or changing doctrine
146
+
147
+ - **Change one idea per PR.** These files are read by agents under load; a PR that
148
+ edits eight references for three unrelated reasons is unreviewable.
149
+ - **Update every surface in the same change.** If you touch the stage list, the
150
+ gate types or the review verdict count, walk `SKILL.md`, `references/stages.md`,
151
+ `pipeline.example.json`, the command, the Cursor rule and the README before you
152
+ commit. The validator catches much of this — do not rely on it to think for you.
153
+ - **A new guard needs a negative self-test.** If you teach `test/validate.py` a new
154
+ rule, add a step to `.github/workflows/validate.yml` that corrupts a copy and
155
+ asserts the validator fails, then watch it with `npm run test:negatives`. A guard
156
+ nobody proved can fail is decoration. **Check the base is green first** — if the
157
+ repo already fails your new rule, the self-test passes for the wrong reason and
158
+ proves nothing.
159
+ - **Keep the Cursor rule self-contained.** It gets copied into foreign projects;
160
+ relative links break there. Restate, don't link.
161
+ - **Prose style:** state the rule, then the failure it prevents. Every doctrine
162
+ file ends with a *Rationalizations* table for a reason — the excuse an agent will
163
+ reach for is more useful to write down than the rule itself.
164
+
165
+ ## Commits and pull requests
166
+
167
+ - **Conventional commits:** `feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`.
168
+ Append the version when the change ships one: `feat: … ; v0.19.0`.
169
+ - Fill in the PR template: what changed, which surfaces you updated, validator
170
+ output.
171
+ - CI must be green. It is fast and dependency-light on purpose.
172
+
173
+ ## Releasing (maintainers)
174
+
175
+ 1. Bump the version in **all four** places (see invariant 1) and write the
176
+ `CHANGELOG.md` section — what changed and *why it mattered*, not a diff summary.
177
+ 2. `npm test` green, commit, push.
178
+ 3. Tag `vX.Y.Z` and push the tag. With the repo variable `RELEASE_ENABLED=true`,
179
+ [`.github/workflows/release.yml`](.github/workflows/release.yml) re-runs the
180
+ validator, checks the tag against the manifests, cuts a GitHub release from that
181
+ CHANGELOG section, and smoke-tests `npx` from a clean checkout.
182
+ 4. **`npm publish` runs in the same workflow**, in a second job armed by the repo
183
+ variable `PUBLISH_NPMJS=true` — it was the one human step in every release, and
184
+ the registry drifted behind the tags because of it. Auth is either the
185
+ `NPM_TOKEN` secret (a **granular automation** token; a classic one is still
186
+ refused by 2FA) or npm trusted publishing via OIDC, which needs no long-lived
187
+ credential. With `PUBLISH_NPMJS` unset or false it stays manual, and 2FA makes
188
+ that a human step.
189
+ 5. Refresh the local installs: `claude plugin marketplace update task-pipeline` →
190
+ `claude plugin update task-pipeline@task-pipeline` →
191
+ `npx skills update task-pipeline --global --yes`, then restart the agent.
192
+
193
+
194
+ ### The family catalogue moves with the release
195
+
196
+ `sshlg-skills` — the launcher that installs and updates the whole ssheleg family — pins every
197
+ member's version in its own `skills.json`. **A release that does not bump that pin is invisible.**
198
+ `npx sshlg-skills list` keeps reporting the previous version, `update` keeps installing it, and
199
+ anyone comparing their install against `list` is told the wrong number with nothing to reveal it.
200
+
201
+ So a release is not finished at `npm publish`:
202
+
203
+ ```bash
204
+ # in ssheleg/sshlg-skills
205
+ # 1. bump this member's "version" in skills.json
206
+ # 2. bump the launcher's own version, changelog, tag
207
+ npm publish --access public
208
+ npx --yes sshlg-skills@latest list # the new number must appear here
209
+ ```
210
+
211
+ ## License
212
+
213
+ By contributing you agree that your contributions are licensed under the
214
+ [MIT License](LICENSE), and that any third-party material you bring in is
215
+ compatible and gets its notice added to `LICENSE` → *Third-party*.
package/README.md CHANGED
@@ -630,7 +630,7 @@ framework bakes in no fixed stage count and no opinion on which gates are manual
630
630
  A pipeline config may declare an optional `release` block: a master `enabled`
631
631
  toggle, a `trigger`, project-defined `steps`, and `verify` smoke-checks. It's **off
632
632
  unless a project turns it on**, and every project configures its own. This repo's
633
- own instance is [`.github/workflows/release.yml`](.github/workflows/release.yml) —
633
+ own instance is [`.github/workflows/release.yml`](https://github.com/ssheleg/task-pipeline/blob/main/.github/workflows/release.yml) —
634
634
  armed per repo by the `RELEASE_ENABLED` variable (unset = off), it validates the tag
635
635
  against the manifests, cuts a GitHub release from the CHANGELOG, and smoke-tests
636
636
  `npx` from a clean checkout. Copy and adapt it; nothing is hardcoded.
package/SECURITY.md ADDED
@@ -0,0 +1,67 @@
1
+ # Security policy
2
+
3
+ ## What this project is
4
+
5
+ `task-pipeline` ships **markdown doctrine plus two small installers**. There is no
6
+ server, no network client and no runtime service. The executable surface is:
7
+
8
+ | Surface | What it does |
9
+ |---|---|
10
+ | `bin/task-pipeline.js` | copies the skill directory into `~/.claude/` (zero dependencies) |
11
+ | `install.sh` | the same, in POSIX shell |
12
+ | `test/validate.py` | reads repo files and exits 0/1; run in CI |
13
+ | `.github/workflows/*.yml` | CI and the toggleable release job |
14
+
15
+ The skill's doctrine, however, is **instructions an agent will act on** inside your
16
+ repository — including running your test and lint commands and, at stage 7, your
17
+ deploy. Treat a change to `references/*.md` with the same care as a change to a
18
+ deploy script.
19
+
20
+ ## Supported versions
21
+
22
+ The latest released version is supported. Fixes ship in a new release rather than
23
+ as patches to older tags.
24
+
25
+ ## Reporting a vulnerability
26
+
27
+ **Do not open a public issue for a security problem.**
28
+
29
+ - Preferred: [GitHub private vulnerability reporting](https://github.com/ssheleg/task-pipeline/security/advisories/new)
30
+ (Security → Report a vulnerability).
31
+ - Alternative: Telegram [@sshlg](https://t.me/sshlg).
32
+
33
+ Please include what you found, how to reproduce it, and the impact you see. You'll
34
+ get an acknowledgement within **72 hours** and a fix or a decision with reasoning
35
+ within **14 days** for anything confirmed. Coordinated disclosure is welcome — tell
36
+ me the timeline you'd like and I'll work to it.
37
+
38
+ ## In scope
39
+
40
+ - The installers writing outside `~/.claude/skills/task-pipeline` and
41
+ `~/.claude/commands/task-pipeline.md`, or overwriting files without `--force`.
42
+ - Anything in the shipped doctrine that would lead an agent to exfiltrate secrets,
43
+ push to a repository the task never named, deploy without the operator's go, or
44
+ bypass a gate that exists to require one.
45
+ - Command injection or path traversal through the validator or the workflows.
46
+ - A CI workflow that could be made to leak repository secrets.
47
+
48
+ ## Out of scope
49
+
50
+ - The behavior of the AI agent that reads the skill. Agents are non-deterministic;
51
+ a model ignoring an instruction is a doctrine-quality bug — please file it as a
52
+ normal issue.
53
+ - Third-party companions (`super-ux`, `context7`, `obsidian-wiki`). Report those to
54
+ their own maintainers.
55
+ - Anything requiring an attacker who already controls the operator's machine or
56
+ their agent's configuration.
57
+
58
+ ## Hardening notes for operators
59
+
60
+ - **Deploy authorization has a floor by design.** The pipeline treats deploy,
61
+ publish and PR-opening as outward actions that need an explicit go, or a standing
62
+ authorization that names the target *and* the preconditions. Do not record a
63
+ blanket "do everything" in a brief — it is specifically rejected.
64
+ - **Writes to another repository are always proposal + PR**, never a direct push.
65
+ - The build stage keeps its scratch state in a git-ignored `.task-pipeline/`
66
+ directory; confirm that directory is ignored before you run it in a repo with
67
+ strict commit hooks.
package/SKILL-CARD.md ADDED
@@ -0,0 +1,60 @@
1
+ # Skill card — task-pipeline
2
+
3
+ **What a reviewer needs before deploying this skill, in one page.** The fields are
4
+ the registry entry Anthropic's [Skills for enterprise](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/enterprise)
5
+ guidance asks every organisation to keep, plus an honest pass over its risk-tier
6
+ table. Written so somebody who did not build this can decide, not so it looks
7
+ harmless.
8
+
9
+ ## Registry entry
10
+
11
+ | Field | Value |
12
+ |---|---|
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
+ | **Owner** | ssheleg ([github.com/ssheleg/task-pipeline](https://github.com/ssheleg/task-pipeline)) |
15
+ | **Version** | 1.8.1 |
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
+ | **Dependencies** | None required. Optional: `context7` (MCP), `figma` (MCP), super-ux, agent-sync, graphify, obsidian-wiki. 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
+ | **Evaluation status** | Suite authored (13 evals, 5 categories). **Never executed** — see [`evals/RESULTS.md`](evals/RESULTS.md) |
19
+
20
+ ## Risk-tier disclosure
21
+
22
+ Every indicator from the enterprise risk table, answered — including the ones that
23
+ apply.
24
+
25
+ | Indicator | Applies? | What exactly |
26
+ |---|---|---|
27
+ | **Code execution** | **Yes — High** | Ships `templates/docgate.sh` (seeded into the host project as its documentation gate), `bin/task-pipeline.js` and `install.sh` (installers), `test/*.py` and `evals/run.py` (repo checks). None run automatically; the gate is seeded and run by the host project |
28
+ | **MCP server references** | **Yes — High** | Instructions name `context7`, `figma`, `graphify`, `wiki-query`, `wiki-update`. All optional; absence degrades a stage, never blocks one, except super-ux on a UI task |
29
+ | **Tool invocations** | **Yes — Medium** | Instructs bash (git, test runners, the host's lint/deploy commands), file reads and writes, and a `PreToolUse` hook example that runs the docs gate before a commit |
30
+ | **Filesystem access scope** | **Yes — Medium** | Reads and writes inside the host project: `docs/`, `scripts/check-docs.sh`, `.task-pipeline/` scratch, `CONTEXT.md`. Stage 5 creates and removes git worktrees. Writing to **another repository** is treated as outward and requires an explicit go |
31
+ | **Instruction manipulation** | No | Nothing instructs Claude to bypass safety rules, hide actions, or behave conditionally on hidden inputs. Outward and irreversible actions (deploy, publish, PR, editing a shared design file) explicitly require operator authorization |
32
+ | **Network access patterns** | Minimal | No `curl`/`fetch`/`requests` in shipped code. The doctrine tells the agent to fetch **library documentation** at stage 1 and to re-fetch the hook contract; both are reads of vendor docs, named in the text |
33
+ | **Hardcoded credentials** | No | None. Release automation uses repository secrets in CI, never files in the skill |
34
+
35
+ ## What to check before you trust it
36
+
37
+ 1. Read `SKILL.md` and the 23 files under `references/` — that is the whole
38
+ instruction surface, and every one is linked directly from `SKILL.md`.
39
+ 2. Read `templates/docgate.sh` before seeding it; it is the only shipped script a
40
+ host project will run on its own repository.
41
+ 3. Run `npm run test:all` — 53 guards, each with a negative self-test that plants a
42
+ defect and requires rejection.
43
+ 4. Run `python3 evals/run.py` for the behavioural protocol, and read
44
+ `evals/RESULTS.md` for what has actually been observed.
45
+
46
+ ## Posture, stated rather than implied
47
+
48
+ - **Separation of duties is not in place.** The author and the reviewer are the same
49
+ person. The enterprise guidance asks for separation; a consumer should treat this
50
+ repository's own review as an author's self-review and do their own.
51
+ - **Commits are unsigned**, so provenance rests on GitHub account control rather than
52
+ cryptographic signature. Integrity verification by checksum is possible today
53
+ (`npm pack` / tag archives) and is not automated.
54
+ - **Versions are pinned by git tag** and mirrored into `sshlg-skills`'s catalogue.
55
+ Rollback is `git checkout v<previous>` or pinning the previous plugin version;
56
+ the previous version is never deleted.
57
+ - **Behavioural evidence is missing, not merely thin.** 53 structural guards prove
58
+ the skill is well-formed. Until `evals/RESULTS.md` carries a dated run, nothing in
59
+ this repository proves it *behaves* — triggers correctly, stays quiet on a
60
+ question, or performs the steps it documents.
@@ -78,6 +78,29 @@ function main(argv) {
78
78
  }
79
79
 
80
80
  const home = os.homedir(); // respects $HOME on POSIX — tests override via env
81
+
82
+ // One channel per agent. This installer writes a PLAIN copy to
83
+ // ~/.claude/skills/<id>, and while the Claude Code PLUGIN channel is active that
84
+ // copy SHADOWS the plugin — silently serving whatever version was copied, forever.
85
+ // The family launcher (sshlg-skills) prunes exactly these copies for that reason,
86
+ // so creating one without saying so undoes the thing it is paired with.
87
+ const pluginDirs = [
88
+ path.join(home, '.claude', 'plugins', 'marketplaces', 'task-pipeline'),
89
+ path.join(home, '.claude', 'plugins', 'cache', 'task-pipeline'),
90
+ ];
91
+ if (!force && pluginDirs.some((d) => fs.existsSync(d))) {
92
+ console.error(`refusing: task-pipeline is already installed as a Claude Code PLUGIN.
93
+
94
+ A plain copy in ~/.claude/skills/ shadows the plugin and keeps serving the version
95
+ it was copied from — the failure this family prunes for. Prefer the plugin:
96
+
97
+ claude plugin marketplace update task-pipeline
98
+ claude plugin update task-pipeline@task-pipeline
99
+
100
+ Rerun with --force if you deliberately want the plain copy instead.`);
101
+ return 3;
102
+ }
103
+
81
104
  installOne(
82
105
  'task-pipeline skill ',
83
106
  skillSrc,
@@ -0,0 +1,47 @@
1
+ # Evaluation results — task-pipeline
2
+
3
+ **Status: the suite is authored and has not been executed.** Recorded here rather
4
+ than left blank, because an empty results file and an unrun suite look identical,
5
+ and this repository's own doctrine calls that the failure — a skip is not a pass.
6
+
7
+ Running these needs a fresh session per query, per model. That is a human or agent
8
+ step; `evals/run.py` prints the protocol and deliberately never reports a pass it
9
+ did not observe.
10
+
11
+ ## How to record a run
12
+
13
+ One table per date + model. Verdict is `pass` / `fail` / `partial`, and a `fail`
14
+ carries what actually happened, not a shrug.
15
+
16
+ ```markdown
17
+ ## 2026-08-10 · sonnet
18
+
19
+ | id | verdict | what happened |
20
+ |---|---|---|
21
+ | TRIG-01 | pass | harvest ran first, ledger written, no code before the brief |
22
+ | NOTRIG-02 | fail | invoked the skill for a one-character README fix |
23
+ ```
24
+
25
+ Then act on the result the way the enterprise guidance says: declining trigger
26
+ accuracy → change the description; coexistence conflicts → narrow it or consolidate;
27
+ persistent instruction-following failures → the instruction is not prominent enough,
28
+ or it belongs in a check.
29
+
30
+ ## Ratchet
31
+
32
+ | Metric | Value | As of |
33
+ |---|---|---|
34
+ | Evals authored | 13 | 2026-08-03 |
35
+ | Categories covered | 5 of 5 | 2026-08-03 |
36
+ | Models exercised | **0 of 3** | 2026-08-03 |
37
+ | Dated runs recorded | **0** | 2026-08-03 |
38
+
39
+ The bottom two numbers are the honest state of this skill's behavioural evidence.
40
+ Everything else in this repository is proven by 53 structural guards that check the
41
+ *form*; these are the only checks that would speak to the *behaviour*, and they have
42
+ not been run yet. Printed here so "53 of 53 green" is never read as "the skill is
43
+ known to work".
44
+
45
+ ## Runs
46
+
47
+ _(none yet)_
package/evals/run.py ADDED
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env python3
2
+ """Validate the evaluation suite and print the run protocol.
3
+
4
+ **This script does not run a model, and it never reports a pass.** Anthropic's
5
+ guidance ships no runner for Skill evaluations ("There is not currently a built-in
6
+ way to run these evaluations"), and a script that claimed to have executed one
7
+ would be the exact failure this repository's own doctrine is written against — a
8
+ tool describing a world it is not looking at.
9
+
10
+ What it does:
11
+ * checks the suite is well-formed and covers every required category;
12
+ * prints each query with its expected behaviours, ready to run;
13
+ * checks RESULTS.md exists and says, honestly, when the suite last ran.
14
+
15
+ python3 evals/run.py # validate + print the protocol
16
+ python3 evals/run.py --list # ids and categories only
17
+
18
+ Zero dependencies, same as the validator.
19
+ """
20
+ import json
21
+ import os
22
+ import re
23
+ import sys
24
+
25
+ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
26
+ SUITE = os.path.join(ROOT, "evals", "task-pipeline.evals.json")
27
+ RESULTS = os.path.join(ROOT, "evals", "RESULTS.md")
28
+
29
+ # The enterprise guidance requires coverage of triggering (both directions) and
30
+ # ambiguity. The last two are ours: instruction following is where a ten-stage
31
+ # skill actually fails, and coexistence is what a broad description breaks.
32
+ REQUIRED = ("should_trigger", "should_not_trigger", "ambiguous",
33
+ "instruction_following", "coexistence")
34
+ MIN_EVALS = 3 # Anthropic: "At least three evaluations created"
35
+
36
+
37
+ def main(argv):
38
+ errors = []
39
+ if not os.path.isfile(SUITE):
40
+ print(f"FAIL: no suite at {os.path.relpath(SUITE, ROOT)}")
41
+ return 2
42
+ suite = json.load(open(SUITE, encoding="utf-8"))
43
+ evals = suite.get("evals") or []
44
+
45
+ seen = set()
46
+ for e in evals:
47
+ where = e.get("id", "<no id>")
48
+ if not e.get("id"):
49
+ errors.append("an eval has no id")
50
+ elif e["id"] in seen:
51
+ errors.append(f"duplicate eval id {e['id']}")
52
+ seen.add(e.get("id"))
53
+ if e.get("category") not in REQUIRED:
54
+ errors.append(f"{where}: category {e.get('category')!r} is not one of {list(REQUIRED)}")
55
+ if not (e.get("query") or "").strip():
56
+ errors.append(f"{where}: empty query")
57
+ beh = e.get("expected_behavior") or []
58
+ if len(beh) < 2:
59
+ errors.append(f"{where}: needs at least two expected behaviours — one is a hope, "
60
+ "two is a rubric")
61
+ if not (e.get("why") or "").strip():
62
+ errors.append(f"{where}: no `why` — an eval whose failure mode is unstated "
63
+ "cannot tell you what broke")
64
+
65
+ if len(evals) < MIN_EVALS:
66
+ errors.append(f"{len(evals)} eval(s); at least {MIN_EVALS} are required")
67
+ covered = {e.get("category") for e in evals}
68
+ for cat in REQUIRED:
69
+ if cat not in covered:
70
+ errors.append(f"no eval covers {cat!r}")
71
+
72
+ if errors:
73
+ print("FAIL: evaluation suite invalid")
74
+ for e in errors:
75
+ print(" - " + e)
76
+ return 1
77
+
78
+ by_cat = {}
79
+ for e in evals:
80
+ by_cat.setdefault(e["category"], []).append(e)
81
+
82
+ if "--list" in argv:
83
+ for cat in REQUIRED:
84
+ for e in by_cat.get(cat, []):
85
+ print(f" {e['id']:<10} {cat:<22} {e['query'][:60]}")
86
+ print(f"\n{len(evals)} evals across {len(by_cat)} categories")
87
+ return 0
88
+
89
+ print("=" * 72)
90
+ print("task-pipeline evaluation protocol")
91
+ print("=" * 72)
92
+ print("Run each query in a FRESH session with the skill installed, once per")
93
+ print("model in", suite.get("models", []), "— effectiveness varies by model.")
94
+ print("Record every verdict in evals/RESULTS.md with the date and the model.")
95
+ print("A query you did not run is not a pass; leave it blank and say so.\n")
96
+ for cat in REQUIRED:
97
+ print(f"\n--- {cat} ---")
98
+ for e in by_cat.get(cat, []):
99
+ print(f"\n[{e['id']}] {e['query']}")
100
+ print(f" why: {e['why']}")
101
+ for b in e["expected_behavior"]:
102
+ print(f" [ ] {b}")
103
+
104
+ print("\n" + "=" * 72)
105
+ if not os.path.isfile(RESULTS):
106
+ print("NO RESULTS FILE — the suite has never been recorded as run.")
107
+ return 1
108
+ body = open(RESULTS, encoding="utf-8").read()
109
+ # Count RUN HEADINGS only, outside fenced blocks. Counting every date in the
110
+ # file swept up the ratchet table and the fenced example and reported five runs
111
+ # against zero — a reporting tool that overstates its own subject, which is the
112
+ # one thing this script exists not to do.
113
+ outside, infence = [], False
114
+ for ln in body.split("\n"):
115
+ if re.match(r"^\s*(```|~~~)", ln):
116
+ infence = not infence
117
+ continue
118
+ if not infence:
119
+ outside.append(ln)
120
+ runs = [l for l in outside if re.match(r"^## 20\d{2}-\d{2}-\d{2}\b", l)]
121
+ print(f"suite: {len(evals)} evals · recorded runs: {len(runs)}")
122
+ if not runs:
123
+ print("RESULTS.md carries no dated run — the suite is authored and unexecuted.")
124
+ print("OK: suite valid. Execution is a human/agent step; this script never")
125
+ print(" reports a pass it did not observe.")
126
+ return 0
127
+
128
+
129
+ if __name__ == "__main__":
130
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,166 @@
1
+ {
2
+ "_note": "Behavioural evaluations for the task-pipeline skill. Format follows Anthropic's Skill authoring guidance (skills, query, expected_behavior), extended with `id`, `category` and `why` so a failure says which dimension broke. There is no built-in runner for these upstream; `run.py` validates the suite and prints the protocol, and results are recorded in RESULTS.md. Dimensions come from the enterprise guidance: triggering accuracy, isolation, coexistence, instruction following, output quality.",
3
+ "skill": "task-pipeline",
4
+ "models": ["haiku", "sonnet", "opus"],
5
+ "evals": [
6
+ {
7
+ "id": "TRIG-01",
8
+ "category": "should_trigger",
9
+ "skills": ["task-pipeline"],
10
+ "query": "run this through the pipeline: add per-tenant rate limiting to the public API",
11
+ "expected_behavior": [
12
+ "Invokes the task-pipeline skill rather than starting to design or code inline",
13
+ "Runs the stage-0 knowledge harvest BEFORE the first interview question, and writes a source ledger",
14
+ "Asks interview questions one at a time, each with a recommended answer",
15
+ "Writes no implementation code before a brief is committed and confirmed"
16
+ ],
17
+ "why": "The explicit invocation phrase is the primary trigger; the failure it guards is jumping to code."
18
+ },
19
+ {
20
+ "id": "TRIG-02",
21
+ "category": "should_trigger",
22
+ "skills": ["task-pipeline"],
23
+ "query": "полный цикл: перенести биллинг на нового провайдера",
24
+ "expected_behavior": [
25
+ "Invokes the task-pipeline skill from the Russian trigger alias",
26
+ "Continues the conversation in Russian while keeping identifiers and commands untranslated",
27
+ "Reaches stage 0 and does not skip the grill because the request looks clear"
28
+ ],
29
+ "why": "The description carries Russian trigger aliases; if they do not fire, half the operator's phrasings miss the skill."
30
+ },
31
+ {
32
+ "id": "TRIG-03",
33
+ "category": "should_trigger",
34
+ "skills": ["task-pipeline"],
35
+ "query": "build a support-agent dashboard with saved views and CSV export",
36
+ "expected_behavior": [
37
+ "Invokes the skill without an explicit pipeline phrase, because the request is a substantial build",
38
+ "Detects the user-facing surface and surfaces super-ux at intake",
39
+ "Records the UI verdict in the brief"
40
+ ],
41
+ "why": "Substantial work must trigger without the magic words, or the skill only helps people who already know it exists."
42
+ },
43
+ {
44
+ "id": "NOTRIG-01",
45
+ "category": "should_not_trigger",
46
+ "skills": ["task-pipeline"],
47
+ "query": "what does this regex do: ^(?!.*--)[a-z0-9-]{1,63}$",
48
+ "expected_behavior": [
49
+ "Answers the question directly",
50
+ "Does NOT invoke the task-pipeline skill",
51
+ "Does NOT create a TaskList or propose an intake grill"
52
+ ],
53
+ "why": "A question is not a build. Triggering here is the 'description too broad' failure the enterprise guidance names."
54
+ },
55
+ {
56
+ "id": "NOTRIG-02",
57
+ "category": "should_not_trigger",
58
+ "skills": ["task-pipeline"],
59
+ "query": "fix the typo in the README heading: 'Instalation' -> 'Installation'",
60
+ "expected_behavior": [
61
+ "Makes the edit directly",
62
+ "Does NOT invoke the task-pipeline skill",
63
+ "Does NOT run a ten-stage flow for a one-character change"
64
+ ],
65
+ "why": "A trivial mechanical edit run through ten gates teaches the operator to route around the skill."
66
+ },
67
+ {
68
+ "id": "NOTRIG-03",
69
+ "category": "should_not_trigger",
70
+ "skills": ["task-pipeline"],
71
+ "query": "explain how our auth middleware decides which routes are public",
72
+ "expected_behavior": [
73
+ "Reads the code and explains it",
74
+ "Does NOT invoke the task-pipeline skill"
75
+ ],
76
+ "why": "Explanation is not delivery."
77
+ },
78
+ {
79
+ "id": "AMB-01",
80
+ "category": "ambiguous",
81
+ "skills": ["task-pipeline"],
82
+ "query": "clean up the error handling in the payments module",
83
+ "expected_behavior": [
84
+ "Establishes scope before choosing a route — asks whether this is a bounded fix or a refactor worth the full cycle",
85
+ "Does NOT silently start the ten-stage flow, and does NOT silently start editing",
86
+ "States which route it is taking and why"
87
+ ],
88
+ "why": "The honest failure here is a silent pick in either direction; the skill should make the choice visible."
89
+ },
90
+ {
91
+ "id": "AMB-02",
92
+ "category": "ambiguous",
93
+ "skills": ["task-pipeline"],
94
+ "query": "add an `is_archived` field to the user model",
95
+ "expected_behavior": [
96
+ "Recognises that a schema field touches contracts, migrations and documentation even though the change is small",
97
+ "Either runs the flow or states explicitly which parts it is skipping and why",
98
+ "Does not treat 'small diff' as 'no decision to record'"
99
+ ],
100
+ "why": "Small changes with wide blast radius are where the doc track earns its keep or gets skipped."
101
+ },
102
+ {
103
+ "id": "COEX-01",
104
+ "category": "coexistence",
105
+ "skills": ["task-pipeline", "super-ux"],
106
+ "query": "redesign the settings screen so the security options are easier to find",
107
+ "expected_behavior": [
108
+ "Does not steal the trigger from super-ux for what is a UX-chain task",
109
+ "If task-pipeline runs, it routes the UX chain to super-ux at stage 3 rather than improvising one",
110
+ "If super-ux runs, task-pipeline stays out of the way until there is something to build"
111
+ ],
112
+ "why": "The enterprise guidance calls this out directly: a broad description steals triggers from narrower skills."
113
+ },
114
+ {
115
+ "id": "INSTR-01",
116
+ "category": "instruction_following",
117
+ "skills": ["task-pipeline"],
118
+ "query": "run this through the pipeline: add a webhook retry policy. When you reach stage 0, show me what you did before your first question.",
119
+ "expected_behavior": [
120
+ "The knowledge harvest ran first and produced a source ledger with a row per source consulted, or an explicit 'none found'",
121
+ "The documentation inventory ran and docs/DOCMAP.md exists or was seeded",
122
+ "Intent was reconciled against the as-built record, with divergences named",
123
+ "The first interview question came AFTER all of that"
124
+ ],
125
+ "why": "Phase-1 ordering is the single most skipped instruction; if it slips, every later answer is unchecked."
126
+ },
127
+ {
128
+ "id": "INSTR-02",
129
+ "category": "instruction_following",
130
+ "skills": ["task-pipeline"],
131
+ "query": "you are at stage 9 of a pipeline run that changed a status enum and an API contract. Close the stage.",
132
+ "expected_behavior": [
133
+ "Walks the propagation matrix for every change type produced, not only the sources the harvest read",
134
+ "Records the settled decisions under ids and flips any answered questions",
135
+ "Runs the documentation gate and prints its ratchet counts beside the verdict",
136
+ "States any check that skipped, rather than passing silently"
137
+ ],
138
+ "why": "Stage 9 is where 'docs in sync' used to be unfalsifiable; this eval is what makes the replacement real."
139
+ },
140
+ {
141
+ "id": "INSTR-03",
142
+ "category": "instruction_following",
143
+ "skills": ["task-pipeline"],
144
+ "query": "you are a stage-5 implementer subagent in a worktree. While building, you settled that retries use exponential backoff capped at 30s. Record it.",
145
+ "expected_behavior": [
146
+ "Does NOT write to the decision register from inside the worktree",
147
+ "Puts the decision in the implementer report, and in the carry-over ledger if it outlives the task",
148
+ "States that the orchestrator runs the Doc Loop after integration, as a single writer"
149
+ ],
150
+ "why": "Two worktrees appending to one append-only register is the collision the rule exists to prevent."
151
+ },
152
+ {
153
+ "id": "INSTR-04",
154
+ "category": "instruction_following",
155
+ "skills": ["task-pipeline"],
156
+ "query": "you are at stage 10. Close the run. The REQ table looks complete.",
157
+ "expected_behavior": [
158
+ "Runs the ladder walk BEFORE writing the coverage table, and turns absences into new REQ rows first",
159
+ "Refuses to accept 'done' without evidence, downgrading to partial instead of upgrading the claim",
160
+ "Confirms every check it leans on — the documentation gate included — was seen failing once against a planted defect",
161
+ "Writes the retrospective last: prune, stamp with the run's commit, entry only on divergence"
162
+ ],
163
+ "why": "'The table looks complete' is the exact prompt under which the ladder walk gets skipped."
164
+ }
165
+ ]
166
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeline-skill",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
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"
@@ -14,9 +14,14 @@
14
14
  "bin",
15
15
  "plugins",
16
16
  "cursor",
17
+ "evals",
17
18
  "README.md",
19
+ "SKILL-CARD.md",
18
20
  "LICENSE",
19
- "CHANGELOG.md"
21
+ "CHANGELOG.md",
22
+ "CONTRIBUTING.md",
23
+ "SECURITY.md",
24
+ "CODE_OF_CONDUCT.md"
20
25
  ],
21
26
  "repository": "github:ssheleg/task-pipeline",
22
27
  "homepage": "https://github.com/ssheleg/task-pipeline#readme",
@@ -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 must close with evidence, a loop guard that breaks churn, one provider-agnostic model confirmed up front, and an optional super-ux UX track for user-facing work.",
5
- "version": "1.8.0",
5
+ "version": "1.8.1",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -352,7 +352,7 @@ findings are neither fixed nor parked-with-ruling at the cap.
352
352
  After the last task: build a package over `MERGE_BASE`..`HEAD`
353
353
  (`git merge-base "$BASE_BRANCH" HEAD`, where `$BASE_BRANCH` is the base recorded in
354
354
  the stage-0 brief — never a hardcoded `main`), dispatch the whole-branch review
355
- ([`review.md`](review.md) → *Final review*; on the run's model, escalation offered
355
+ ([`review.md`](review.md) → *Prompt — final whole-branch review*; on the run's model, escalation offered
356
356
  out loud per *Models* above), and point it at the
357
357
  ledger's deferred-minor and parked lines so it can triage what must be fixed before
358
358
  merge.
@@ -50,7 +50,7 @@ repository — the smallest one still decides *somewhere* that a thing is true
50
50
  the only choice is whether that answer is written down or re-derived by each new
51
51
  reader. What scales down is **volume**, never the rules: a register with three
52
52
  entries is a register, and the seeded gate is green on exactly those three
53
- ([`gates.md`](gates.md) → *progressive arming*).
53
+ ([`gates.md`](gates.md) → *Progressive arming*).
54
54
 
55
55
  ---
56
56
 
@@ -23,6 +23,8 @@ elsewhere and is not restated here:
23
23
 
24
24
  - Axis A — the stage gate type
25
25
  - Axis B — the enforcement mechanism
26
+ - Axis C — degrees of freedom
27
+ - Progressive arming
26
28
  - Before you run a check
27
29
  - Anatomy of a project gate
28
30
  - Writing the check itself
@@ -70,6 +72,53 @@ disprove. Left unwritten, it is indistinguishable from an omission.
70
72
 
71
73
  ---
72
74
 
75
+ ## Axis C — degrees of freedom
76
+
77
+ Axis B says how hard a rule bites. This one says how much latitude the *instruction*
78
+ leaves, and it is a separate choice: a low-freedom instruction guarded by nothing is
79
+ a wish, and a high-freedom instruction behind a blocking hook is a bottleneck.
80
+
81
+ Match the level to how **fragile** the step is, not to how important it feels:
82
+
83
+ | Level | Shape | Use when | Example here |
84
+ |---|---|---|---|
85
+ | **high** | prose direction, no prescribed sequence | many routes reach a good answer and context decides | stage 2 — the design conversation |
86
+ | **medium** | a named order with room inside each step | the sequence is fixed, the content is judgement | stage 0 — two phases, adaptive questions |
87
+ | **low** | run exactly this, in this order, no variation | the operation is fragile, irreversible, or must be identical every time | stage 5's TDD order · stage 7's deploy · stage 9's matrix walk |
88
+
89
+ The picture worth keeping is an **open field versus a narrow bridge**. In the field,
90
+ say where to go and let the agent find the route. On the bridge there is one safe way
91
+ across, and the guardrails are the instruction.
92
+
93
+ **Over-constraining costs as much as under-constraining and is harder to see.** A
94
+ high-freedom step written as low freedom produces an agent that follows the letter
95
+ past the point where the letter stopped fitting — and reports success, because it did
96
+ what it was told. Where a step is genuinely open, say so out loud; that sentence is
97
+ what stops the next reader from hardening it.
98
+
99
+ Every stage in [`stages.md`](stages.md) declares its level and its reason, on the
100
+ line under its heading.
101
+
102
+ ## Progressive arming
103
+
104
+ A gate seeded into a young project has almost nothing to check yet, and a gate that
105
+ starts red teaches everyone on day one that it is noise ([`learned.md`](learned.md)
106
+ rule 9). So each section reports one of four states and only one of them fails:
107
+
108
+ | State | Means | Fails? |
109
+ |---|---|---|
110
+ | `ok` | the check ran and passed | no |
111
+ | `dormant: … — no <artefact> yet` | the input does not exist yet | no |
112
+ | `skip: … — <why>` | the input exists, the check could not run here | no |
113
+ | `ERR` | the check ran and found something | **yes** |
114
+
115
+ `dormant` and `skip` are **printed, never silent** — that is the whole reason they do
116
+ not quietly become permanent.
117
+
118
+ They also force one more obligation on the verdict line: it must report **what the
119
+ run actually looked at**. Every section dormant is indistinguishable from a gate
120
+ blind to the shape in front of it, and exit 0 alone cannot tell those two apart.
121
+
73
122
  ## Before you run a check
74
123
 
75
124
  Four preconditions. Skipping any of them turns a run into a claim.
@@ -125,7 +125,7 @@ and the commit. Silent deletion is forbidden: the record is what survives, the
125
125
  instruction is what leaves.
126
126
 
127
127
  **Print the counts beside the gate verdict**, the same way the carry-over ledger
128
- does ([`audit.md`](audit.md) → *ratchet, never TODO*):
128
+ does ([`audit.md`](audit.md) → *What can't be fixed now becomes a ratchet, never a TODO*):
129
129
 
130
130
  ```
131
131
  GATE 10 acceptance: PASS — 14/14 REQ verified
@@ -182,7 +182,7 @@ exactly the sentence a future reader will hit in the code and re-litigate, so a
182
182
  ruling that outlives the run goes through the **Doc Loop**
183
183
  ([`documentation.md`](documentation.md)) — via the report and the ledger, written by
184
184
  the orchestrator after integration, never by a subagent
185
- ([`build.md`](build.md) → 4.1a*).
185
+ ([`build.md`](build.md) → *4.1a Decisions settled inside a task*).
186
186
 
187
187
  Run the final review on the **run's confirmed model** like everything else
188
188
  ([`model-tiering.md`](model-tiering.md)). It is the one review that sees the whole
@@ -53,7 +53,7 @@ never that the work was skipped quietly.
53
53
  - Cross-cutting — the audit
54
54
 
55
55
  ## 0 — Intake grill — MANDATORY
56
- - **Freedom: medium** — the interview adapts to the answers; its two phases and their order do not ([`gates.md`](gates.md) → *Axis B*).
56
+ - **Freedom: medium** — the interview adapts to the answers; its two phases and their order do not ([`gates.md`](gates.md) → *Axis C*).
57
57
  - **Stage 0 is not optional and not skippable.** There is no "small enough task"
58
58
  exemption, no "the request was already clear" exemption, no starting stage 1
59
59
  "while the operator thinks". The only sanctioned bypass is the
@@ -154,7 +154,7 @@ never that the work was skipped quietly.
154
154
  reversible calls can be deferred with a note). Only then start stage 1.
155
155
 
156
156
  ## 1 — Docs study
157
- - **Freedom: medium** — which sources to fetch is judgement; grounding contracts on fetched docs is not ([`gates.md`](gates.md) → *Axis B*).
157
+ - **Freedom: medium** — which sources to fetch is judgement; grounding contracts on fetched docs is not ([`gates.md`](gates.md) → *Axis C*).
158
158
  - **What:** ground every external library / API / SDK the task touches on the
159
159
  *current* docs, before locking any contract.
160
160
  - **Invoke:** the `context7` MCP — `context7:resolve-library-id` → `context7:query-docs`,
@@ -164,7 +164,7 @@ never that the work was skipped quietly.
164
164
  not recall. Unresolvable libraries are flagged in the spec.
165
165
 
166
166
  ## 2 — Brainstorm + decompose
167
- - **Freedom: high** — many designs are valid — this is the open field, and the only fixed thing is the gate ([`gates.md`](gates.md) → *Axis B*).
167
+ - **Freedom: high** — many designs are valid — this is the open field, and the only fixed thing is the gate ([`gates.md`](gates.md) → *Axis C*).
168
168
  - **How it runs: [`brainstorm.md`](brainstorm.md)** — built into this skill. Read
169
169
  the brief first (stage 0 already answered scope/constraints/done-criteria), then
170
170
  explore the codebase, scope-check for decomposition, one question at a time, 2–3
@@ -194,7 +194,7 @@ never that the work was skipped quietly.
194
194
  contracts named with their owner.
195
195
 
196
196
  ## 3 — Spec — with UX track for user-facing tasks
197
- - **Freedom: medium** — what the contract says is judgement; which contracts must be locked is a list ([`gates.md`](gates.md) → *Axis B*).
197
+ - **Freedom: medium** — what the contract says is judgement; which contracts must be locked is a list ([`gates.md`](gates.md) → *Axis C*).
198
198
  - **How it runs: [`spec.md`](spec.md)** — built into this skill: the UX-track order,
199
199
  what the spec must lock (types, schemas, signatures, file layout, the **Global
200
200
  Constraints** block stages 4–5 depend on), the self-review pass and the operator
@@ -250,7 +250,7 @@ never that the work was skipped quietly.
250
250
  starts before this — the chain comes BEFORE interface.
251
251
 
252
252
  ## 4 — Plan
253
- - **Freedom: low** — the task format is prescribed and the REQ set-comparison is mechanical ([`gates.md`](gates.md) → *Axis B*).
253
+ - **Freedom: low** — the task format is prescribed and the REQ set-comparison is mechanical ([`gates.md`](gates.md) → *Axis C*).
254
254
  - **How it runs: [`planning.md`](planning.md)** — built into this skill →
255
255
  `docs/superpowers/plans/YYYY-MM-DD-<topic>.md` (same slug as the brief and the
256
256
  spec). Zero-context tasks, exact
@@ -269,7 +269,7 @@ never that the work was skipped quietly.
269
269
  same change (super-ux *same-change* rule).
270
270
 
271
271
  ## 5 — Dev
272
- - **Freedom: low** — TDD order, worktree isolation and 'a subagent never writes the register' are the narrow bridge ([`gates.md`](gates.md) → *Axis B*).
272
+ - **Freedom: low** — TDD order, worktree isolation and 'a subagent never writes the register' are the narrow bridge ([`gates.md`](gates.md) → *Axis C*).
273
273
  - **How it runs: [`build.md`](build.md)** — built into this skill: isolate the
274
274
  workspace (native worktree tool first, git fallback, baseline tests), keep a
275
275
  ledger under `.task-pipeline/build/<plan>/` so a compacted context can resume,
@@ -291,7 +291,7 @@ never that the work was skipped quietly.
291
291
  "leave it" recorded).
292
292
 
293
293
  ## 6 — Tests
294
- - **Freedom: low** — green means the full suite, and no skip smuggles a red one past ([`gates.md`](gates.md) → *Axis B*).
294
+ - **Freedom: low** — green means the full suite, and no skip smuggles a red one past ([`gates.md`](gates.md) → *Axis C*).
295
295
  - **What:** consolidate test coverage for the change: confirm new functionality
296
296
  has tests (written test-first in stage 5), update/repair existing tests the
297
297
  change touched, and add edge-case + failure-path tests per DoD.
@@ -305,7 +305,7 @@ never that the work was skipped quietly.
305
305
  ([`audit.md`](audit.md)).
306
306
 
307
307
  ## 7 — Lint + deploy
308
- - **Freedom: low** — outward and irreversible — the authorization floor is exact or the stage stops ([`gates.md`](gates.md) → *Axis B*).
308
+ - **Freedom: low** — outward and irreversible — the authorization floor is exact or the stage stops ([`gates.md`](gates.md) → *Axis C*).
309
309
  - Read host conventions (`conventions.md`): run the linter; fix failures. The suite
310
310
  is already green from stage 6 — re-run it if code changed since. For UI projects,
311
311
  the **super-ux linter** (`python3 docs/ux/lint.py` / `/ux-lint`) is part of lint —
@@ -320,14 +320,14 @@ never that the work was skipped quietly.
320
320
  operator go. Respect deploy-from-main rules if the project mandates them.
321
321
 
322
322
  ## 8 — Post-deploy
323
- - **Freedom: medium** — where the logs live varies; 'clean boot or an honest degradation report' does not ([`gates.md`](gates.md) → *Axis B*).
323
+ - **Freedom: medium** — where the logs live varies; 'clean boot or an honest degradation report' does not ([`gates.md`](gates.md) → *Axis C*).
324
324
  - Tail deploy logs / health-check per conventions. Confirm clean boot, no error
325
325
  spike, live subsystems healthy.
326
326
  - **GATE (auto):** clean boot confirmed, or an **honest degradation report** with next
327
327
  steps — never silent success.
328
328
 
329
329
  ## 9 — Docs + wiki
330
- - **Freedom: low** — the matrix walk and the gate are mechanical; what a doc says is not this stage's call ([`gates.md`](gates.md) → *Axis B*).
330
+ - **Freedom: low** — the matrix walk and the gate are mechanical; what a doc says is not this stage's call ([`gates.md`](gates.md) → *Axis C*).
331
331
  - **The propagation sweep runs first** ([`documentation.md`](documentation.md)).
332
332
  The ledger below names the documents you **read**; the matrix in `docs/DOCMAP.md`
333
333
  names the documents you **owe**. They are not the same list, and the gap between
@@ -381,7 +381,7 @@ never that the work was skipped quietly.
381
381
  carry-over count printed beside this verdict**.
382
382
 
383
383
  ## 10 — Acceptance
384
- - **Freedom: medium** — the walk and the evidence rule are fixed; whether it is what was asked for is the operator's ([`gates.md`](gates.md) → *Axis B*).
384
+ - **Freedom: medium** — the walk and the evidence rule are fixed; whether it is what was asked for is the operator's ([`gates.md`](gates.md) → *Axis C*).
385
385
  - **What:** the closing stage — go back to the brief and account for **every**
386
386
  requirement. Doctrine: [`acceptance.md`](acceptance.md). Every earlier gate asks
387
387
  "is this artifact good?"; none asks "does this still contain everything that was
@@ -82,7 +82,9 @@ find . -maxdepth 1 -type f -name '*.md' 2>/dev/null | sort >> "$TMP/files" || tr
82
82
  FILE_COUNT=$(wc -l < "$TMP/files" | tr -d ' ')
83
83
 
84
84
  if [ "$FILE_COUNT" = "0" ]; then
85
- echo "FAIL: documentation gate — no markdown found under $DOCS_DIR"
85
+ echo "FAIL: documentation gate — no markdown found in $DOCS_DIR/ or the repository root."
86
+ echo " Seed the doc map and the registers first (task-pipeline stage 0, phase 1b),"
87
+ echo " or point DOCS_DIR at wherever this project keeps its documentation."
86
88
  exit 1
87
89
  fi
88
90