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.
- package/CHANGELOG.md +148 -0
- package/README.md +1 -0
- package/SKILL-CARD.md +1 -1
- package/package.json +5 -4
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/commands/project-audit.md +23 -0
- package/plugins/task-pipeline/skills/project-audit/SKILL.md +202 -0
- package/plugins/task-pipeline/skills/project-audit/references/probes.md +199 -0
- package/plugins/task-pipeline/skills/project-audit/scripts/audit.py +1267 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +8 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/audit.md +8 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/documentation.md +17 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/gates.md +92 -0
|
@@ -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
|
|
53
|
-
|
|
54
|
-
same object. → [`learned.md`](learned.md)
|
|
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
|