task-pipeline-skill 1.74.0 → 1.76.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.
@@ -200,10 +200,18 @@ plugins/task-pipeline/
200
200
  templates/ # skeletons seeded into a host project
201
201
  hygiene.sh docgate.sh # -> scripts/check-hygiene.sh, check-docs.sh
202
202
  README.md # the index — and it is the list, not a copy of it
203
+ scripts/graph.py # the work graph, walked so the model never reads it
204
+ skills/evidence-docs/SKILL.md # the ten canons, as a navigator
205
+ skills/project-audit/ # a whole project as the subject
206
+ SKILL.md # the six phases, cold start
207
+ references/probes.md # the probe catalogue, by stack and shape
208
+ scripts/audit.py # discovery, registry, HTML + JSON sidecar
209
+ commands/project-audit.md # /project-audit
203
210
  cursor/rules/task-pipeline.mdc # Cursor channel (self-contained rule)
204
211
  bin/task-pipeline.js # npx installer (package task-pipeline-skill)
205
212
  install.sh # POSIX installer
206
213
  test/validate.py # structural validator (npm test)
214
+ test/graph_test.py test/project_audit_test.py # the other two halves of `npm test`
207
215
  .github/workflows/{validate,release}.yml # CI + toggleable release automation
208
216
  .github/ISSUE_TEMPLATE/ .github/PULL_REQUEST_TEMPLATE.md
209
217
  package.json .gitignore
@@ -34,6 +34,14 @@ whose whole job is "audit X" runs nothing else.
34
34
  | [`acceptance.md`](acceptance.md) | stage 10 | did everything **on the list** ship, with evidence? |
35
35
  | [`loop-guard.md`](loop-guard.md) | any **editing** loop churns | is this pass undoing the last one? |
36
36
  | **this file** | any **audit** pass | what is broken or missing that nobody has compared? |
37
+ | the `project-audit` skill | a **whole project** is the subject | what is true of this repository today — from a cold start, with no brief |
38
+
39
+ **`project-audit` is the cold-start caller of this file, not a second copy of
40
+ it.** This ladder needs a REQ row and a module map to walk; most repositories
41
+ have neither, and *"your spine is missing"* is a true first finding and a useless
42
+ audit. That skill discovers what the project is, probes it, reads the production
43
+ evidence a repository cannot hold, and hands phase 4 back here — so the method
44
+ below stays the one place it is written.
37
45
 
38
46
  `loop-guard.md` governs loops that *change* things — the fix loop, a re-entered
39
47
  stage. Its trip means a decision is being re-litigated at the wrong altitude. This
@@ -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