task-pipeline-skill 1.74.0 → 1.75.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 CHANGED
@@ -1,5 +1,71 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.75.0 — 2026-08-22 — the day's findings become doctrine
4
+
5
+ Nothing new ships behind a flag here; what ships is the doctrine the previous release
6
+ earned, written where the next run will read it instead of in a changelog nobody greps.
7
+
8
+ **`documentation.md` canon 2 gains its dual.** *Numbers are computed, never restated* had
9
+ a half nobody had written down: **an example that instantiates a number IS one.** A release
10
+ note explaining that a count was written in the wrong shape — with the digits in it — places
11
+ a second readable count in a section a gate reads, so a probe that removes the real one
12
+ leaves the narrative matching and the guard silent. Measured three times in one hour, each
13
+ time inside prose *about* this very failure. The umbrella already said it for commands:
14
+ name a dead command, never claim it. It holds for a number, a version and a shape.
15
+
16
+ **`gates.md` gains three sections.**
17
+
18
+ *A probe rots, and every way it rots reports green.* The three assertions prove a probe
19
+ works today; the thing it guards is the thing that moves it. An anchor pinned to a literal
20
+ dies on the release that changes the number it guards. A precondition inherited from the
21
+ tree evaporates **when the system works correctly** — an honest run stamp leaves nothing
22
+ "after the newest stamp", a release absorbs the `## Unreleased` section — and the probe
23
+ lands and proves nothing. The triage is one question: *what does this probe look for, and
24
+ who is allowed to change it?*
25
+
26
+ *A ratchet prices the rule, not the exception.* A coverage check that asserts once per
27
+ exception and falls through on the ordinary case makes the correct remediation lower the
28
+ count — so the gate goes red on the stricter answer and a legitimate lowering becomes
29
+ indistinguishable from the failure the floor exists to catch. One assertion per subject
30
+ examined, whatever its verdict. And measure the floor **after** the last edit: read, keep
31
+ editing, restate is how every floor ends up below its true count, silently, because a floor
32
+ is a minimum.
33
+
34
+ *Run the whole suite locally before you push the tag.* Also **R-010**, because it is a
35
+ run-level obligation rather than a note. One tag took five CI rounds where the last four
36
+ were a single twelve-minute local run apart — and the second half is what makes it a rule:
37
+ a branch push cannot see a tag that does not exist yet, so three checks have no earlier
38
+ chance to fire.
39
+
40
+ ### And R-010 failed on its own release, which is the finding
41
+
42
+ The local suite was green and CI was not. The difference was one precondition asking
43
+ `os.path.isdir(".git")` — false in a **submodule** checkout, where `.git` is a file holding a
44
+ gitdir pointer. The whole release-gap check had been switching itself off in the only checkout
45
+ this family is developed in, since the day it was written, with no line of output. It ran in CI
46
+ alone, which clones standalone, so a class of defect reached four tag pushes before anyone asked
47
+ why the local run was green.
48
+
49
+ This repository had already recorded that class **twice**, in `docgate.sh` and in the retro log,
50
+ both naming `[ -d .git ]` as the wrong question. This instance was missed both times. Knowing a
51
+ class is not sweeping it — which is standing instruction R-003, also already in force.
52
+
53
+ Two fixes, and the second is the general one: ask `exists`, never `isdir`, of anything named
54
+ `.git`; and **a precondition that fails must disclose rather than skip**. A check guarded by a
55
+ bare `and` evaporates without output, and it evaporates most reliably in the environment its
56
+ authors work in. R-010 gains the half it learned by failing: *a green local suite is not
57
+ evidence until you know which checks looked* — tag locally first, run, then read the `unlooked`
58
+ line before believing the exit code.
59
+
60
+ Seven board citations into `gates.md` were re-pointed across two passes, which is the ordinary
61
+ cost of inserting text above them and the reason those citations carry a phrase as well as a
62
+ range.
63
+
64
+ Guards: 412 → **412**. Flat by construction: this release adds doctrine, not checks, and a
65
+ guard count that rose on a documentation change would be a number borrowed from a suite that
66
+ never ran. The shape of that line is the one canon 2's new half is about, so it is written
67
+ here in the form the guard reads and described nowhere else in this section.
68
+
3
69
  ## v1.74.0 — 2026-08-20 — a node is closed by three readings, not one
4
70
 
5
71
  **A verifier reads the diff it was handed, and that is the definition of its context, not 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.74.0 |
15
+ | **Version** | 1.75.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.74.0",
3
+ "version": "1.75.0",
4
4
  "description": "Full-cycle delivery pipeline for coding agents: a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine ships inside the skill — no companion plugin required. This package is the installer CLI.",
5
5
  "bin": {
6
6
  "task-pipeline": "bin/task-pipeline.js"
@@ -2,7 +2,7 @@
2
2
  "name": "task-pipeline",
3
3
  "displayName": "Task Pipeline",
4
4
  "description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/manual gates, a frozen requirement spine that closes with evidence, a work board and a verification ledger that outlive a run, an exposure line naming what shipped unconfirmed, a progress rail computed from the project's own config, a loop guard whose review ceiling measures rather than stops, and stage-3 tracks for what a product does, how it sounds and how it looks. Two modes need no task: `checkup` (what is unverified) and `setup` (audit existing docs). Retro insights can publish upstream as issues, opt-in and redacted.",
5
- "version": "1.74.0",
5
+ "version": "1.75.0",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -49,9 +49,23 @@ the same run and a description of the behaviour is not the behaviour. → the re
49
49
  SHA-resolution guard; the finding shape in [`setup.md`](setup.md); [`tdd.md`](tdd.md) →
50
50
  *When the thing under test is an agent*.
51
51
 
52
- **2. Numbers are computed, never restated.** A count in prose is a number that was true
53
- once. Derive it at check time and compare the stated one against the computed one as the
54
- same object. → [`learned.md`](learned.md) rule 8.
52
+ **2. Numbers are computed, never restated and an example that instantiates a number
53
+ IS one.** A count in prose is a number that was true once. Derive it at check time and
54
+ compare the stated one against the computed one as the same object. → [`learned.md`](learned.md)
55
+ rule 8.
56
+
57
+ The half that costs more, because it is written by the person who understands the rule:
58
+ **a document quoting a form as an example is indistinguishable from the form.** A release
59
+ note explaining *"the count was written wrongly as `Guards: 412 → 412`"* has just placed a
60
+ second readable count in a section whose count a gate reads — so when the probe removes the
61
+ real one, the narrative still matches and the guard reports green over a section that states
62
+ nothing. Measured three times in one hour on 2026-08-22, each time inside prose *about* this
63
+ very failure: the release note, the board row filed against it, and the repair to the probe.
64
+
65
+ The rule the umbrella already states for commands — **name a dead command, never claim it**
66
+ — holds for a number, a version and a shape. Describe the wrong form; do not write it.
67
+ *"the bold sat around the whole phrase instead of around the second number"* is checkable by
68
+ a reader and invisible to a pattern; the same sentence with the digits in it is a live claim.
55
69
 
56
70
  **3. Every fact has exactly one home.** Other documents link to it; they never restate
57
71
  it. Two homes do not disagree on the day they are written — they disagree on the day one
@@ -31,6 +31,9 @@ elsewhere and is not restated here:
31
31
  - Anatomy of a project gate
32
32
  - Writing the check itself
33
33
  - Probing — plant, run, restore
34
+ - A probe rots, and every way it rots reports green
35
+ - A ratchet prices the rule, not the exception
36
+ - Run the whole suite locally before you push the tag
34
37
  - The neighbour probe — plant the evidence outside the subject
35
38
  - A ratchet's matcher is itself a check, and it needs a near-miss
36
39
  - A green probe is evidence only if the mutation is known to have landed
@@ -385,6 +388,95 @@ Otherwise the next reader has to redo it to know whether it was ever done.
385
388
 
386
389
  ---
387
390
 
391
+ ## A probe rots, and every way it rots reports green
392
+
393
+ The three assertions above prove a probe works **today**. They say nothing about the
394
+ day after, and a probe is uniquely exposed: the thing it guards is the thing that moves
395
+ it. Four rotted in one release on 2026-08-22, and none of them failed loudly — two
396
+ reported `caught`, two reported nothing at all.
397
+
398
+ **1. The anchor is a literal the guarded thing moves.** A probe pinned to *"the bundle
399
+ is N reference files"* stops landing the day a reference file is added — on the release
400
+ that changes the very number it guards. Same for a version, a count word, a phrase a
401
+ release rewrites. **Derive the anchor**: read whatever the text currently says and make
402
+ *that* wrong. A probe that computes `wrong = stated - 1` never needs maintaining.
403
+
404
+ **2. The precondition is inherited from the tree rather than created.** This is the
405
+ subtle one, because it is triggered by the system working correctly. A probe that
406
+ narrows a declared gap to expose *releases after the newest run stamp* has nothing to
407
+ expose the moment a release writes an honest stamp — the newest release is now the
408
+ newest stamp. A probe requiring an `## Unreleased` section has none the moment a release
409
+ absorbs it. **Both landed. Both proved nothing.** A probe must construct the state it
410
+ needs: remove the stamp, write the section, then plant the defect.
411
+
412
+ **3. The document quotes the form the probe removes.** Covered as
413
+ [`documentation.md`](documentation.md) canon 2's second half, and it belongs here too
414
+ because the probe is where it surfaces: prose describing the wrong shape *with real
415
+ values in it* is a second instance of the shape. The probe deletes the real one, the
416
+ narrative still matches, the guard is silent.
417
+
418
+ **How to see it before CI does.** Ask one question per probe: *what does this probe
419
+ LOOK FOR, and who is allowed to change it?* Where the answer is "the thing it guards",
420
+ it is rotting already. A repository-wide sweep is one grep — a two-digit literal inside
421
+ a needle, an `assert` or a `replace` — and the triage is: the number a probe **writes**
422
+ is correct, the number it **looks for** is the defect.
423
+
424
+ ## A ratchet prices the rule, not the exception
425
+
426
+ A floor that counts assertions is a floor that can be lowered by improving the code, if
427
+ the assertions are attached to the wrong things.
428
+
429
+ Measured: a coverage check called `check()` once per *exception* — a silent value, a kept
430
+ value, a promise — and simply `continue`d on the ordinary case. Collapsing four kept
431
+ values, **the remediation the requirement names first**, therefore dropped the count by
432
+ four against its floor and turned the suite red on the stricter answer. The only way
433
+ through was lowering a ratchet whose own reason says a falling count is how a deleted
434
+ requirement hides — so a legitimate lowering and the failure the floor exists to catch
435
+ became indistinguishable.
436
+
437
+ **One assertion per subject examined, whatever its verdict.** The ordinary case asserts
438
+ too. Then the floor is a function of how large the corpus is, not of how many exceptions
439
+ it happens to contain, and doing the right thing can never lower it.
440
+
441
+ **And measure the floor after the last edit, not before it.** Read the count, keep
442
+ editing, restate the count you read — every floor set that way sits below the true one,
443
+ and a floor is a minimum, so nothing ever says so. Where the gate cannot enforce
444
+ equality — it must not, or the ratchet stops allowing growth — it can still **print the
445
+ gap**: `floor 4026, ran 4027: 1 check is not pinned` turns a silent difference into a
446
+ visible one for the cost of one line.
447
+
448
+ ## Run the whole suite locally before you push the tag
449
+
450
+ Not a preference: an arithmetic. A release workflow that runs the full suite takes
451
+ twenty-five to forty minutes per round, and it reports one failure at a time. The same
452
+ suite on the machine that wrote the change takes twelve and reports all of them at once.
453
+
454
+ On 2026-08-22 one tag took **five CI rounds** — a stray key in a `run:` block, a missing
455
+ run stamp, a stamp cap, and then four rotted probes — where a single local `test:all`
456
+ before the first push would have found the last four together. Every refusal was correct.
457
+ The cost was entirely in asking the wrong machine.
458
+
459
+ **A green local suite is not evidence until you know which checks LOOKED.** This
460
+ instruction failed on its own release: the local run was green, CI was not, and the
461
+ difference was a precondition asking `os.path.isdir(".git")` — false in a submodule
462
+ checkout, where `.git` is a *file* holding a gitdir pointer. One check switched itself
463
+ off in the only checkout the family is developed in, silently, and had been doing so
464
+ since it was written. The repository had recorded that class **twice** already, in two
465
+ other files, and this instance was missed both times: knowing a class is not sweeping
466
+ it. Two consequences, and the second is the general one:
467
+
468
+ - ask `exists`, never `isdir`, of anything named `.git`;
469
+ - **a precondition that fails must disclose, not skip.** Where a check cannot run, it
470
+ appends to the unlooked list and the run prints it. A check guarded by a bare `and`
471
+ evaporates without a line of output, which is the one thing this file's own canon
472
+ forbids — and it evaporates most reliably in the environment its authors use.
473
+
474
+ The rule has a second half, and it is the one that makes it stick: **a tag is the only
475
+ thing that runs some checks.** A branch push cannot see a tag that does not exist yet, so
476
+ the tag-ancestry check, the version-sync check and the run-stamp check have no earlier
477
+ opportunity to fire. Locally, run them the way the release does — against the tree you are
478
+ about to tag, with the suite the release claims.
479
+
388
480
  ## The neighbour probe — plant the evidence outside the subject
389
481
 
390
482
  A probe proves a guard rejects **the phrasing its author had in mind**. That is less than