task-pipeline-skill 1.79.1 → 1.80.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +4 -3
  3. package/SKILL-CARD.md +1 -1
  4. package/cursor/rules/task-pipeline.mdc +3 -1
  5. package/evals/RESULTS.md +212 -9
  6. package/evals/evidence-docs.evals.json +109 -0
  7. package/evals/project-audit.evals.json +108 -0
  8. package/evals/run.py +47 -19
  9. package/package.json +1 -1
  10. package/plugins/task-pipeline/.claude-plugin/plugin.json +3 -2
  11. package/plugins/task-pipeline/commands/task-pipeline.md +2 -1
  12. package/plugins/task-pipeline/hooks/gate-observer.sh +19 -2
  13. package/plugins/task-pipeline/skills/evidence-docs/SKILL.md +1 -0
  14. package/plugins/task-pipeline/skills/project-audit/SKILL.md +7 -2
  15. package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +49 -56
  16. package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +1 -1
  17. package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +1 -1
  18. package/plugins/task-pipeline/skills/task-pipeline/references/adoption.md +15 -4
  19. package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +4 -2
  20. package/plugins/task-pipeline/skills/task-pipeline/references/brainstorm.md +6 -1
  21. package/plugins/task-pipeline/skills/task-pipeline/references/build.md +11 -1
  22. package/plugins/task-pipeline/skills/task-pipeline/references/certification.md +7 -0
  23. package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +33 -2
  24. package/plugins/task-pipeline/skills/task-pipeline/references/documentation.md +2 -2
  25. package/plugins/task-pipeline/skills/task-pipeline/references/exposure.md +7 -3
  26. package/plugins/task-pipeline/skills/task-pipeline/references/gates.md +17 -185
  27. package/plugins/task-pipeline/skills/task-pipeline/references/model-tiering.md +13 -0
  28. package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +1 -0
  29. package/plugins/task-pipeline/skills/task-pipeline/references/probing.md +202 -0
  30. package/plugins/task-pipeline/skills/task-pipeline/references/progress.md +8 -4
  31. package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +60 -1
  32. package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +32 -54
  33. package/plugins/task-pipeline/skills/task-pipeline/references/work-graph.md +1 -1
  34. package/plugins/task-pipeline/skills/task-pipeline/scripts/graph.py +28 -5
  35. package/plugins/task-pipeline/skills/task-pipeline/templates/backlog.md +6 -2
  36. package/plugins/task-pipeline/skills/task-pipeline/templates/run.md +2 -2
package/evals/run.py CHANGED
@@ -17,12 +17,17 @@ What it does:
17
17
 
18
18
  Zero dependencies, same as the validator.
19
19
  """
20
+ import glob
20
21
  import json
21
22
  import os
22
23
  import re
23
24
  import sys
24
25
 
25
26
  ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
27
+ # EVERY suite, discovered — the directory held one suite per skill from
28
+ # 2026-08-31 (evidence-docs and project-audit joined task-pipeline), and a
29
+ # runner pinned to one filename would validate a third of what ships.
30
+ SUITES = sorted(glob.glob(os.path.join(ROOT, "evals", "*.evals.json")))
26
31
  SUITE = os.path.join(ROOT, "evals", "task-pipeline.evals.json")
27
32
  RESULTS = os.path.join(ROOT, "evals", "RESULTS.md")
28
33
 
@@ -34,14 +39,12 @@ REQUIRED = ("should_trigger", "should_not_trigger", "ambiguous",
34
39
  MIN_EVALS = 3 # Anthropic: "At least three evaluations created"
35
40
 
36
41
 
37
- def main(argv):
42
+ def validate_suite(path):
43
+ """Every gap in one suite, in a stable order. The rules are the same for
44
+ every skill's suite — a second rule set would drift."""
38
45
  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"))
46
+ suite = json.load(open(path, encoding="utf-8"))
43
47
  evals = suite.get("evals") or []
44
-
45
48
  seen = set()
46
49
  for e in evals:
47
50
  where = e.get("id", "<no id>")
@@ -68,6 +71,18 @@ def main(argv):
68
71
  for cat in REQUIRED:
69
72
  if cat not in covered:
70
73
  errors.append(f"no eval covers {cat!r}")
74
+ return suite, evals, errors
75
+
76
+
77
+ def main(argv):
78
+ if not os.path.isfile(SUITE):
79
+ print(f"FAIL: no suite at {os.path.relpath(SUITE, ROOT)}")
80
+ return 2
81
+ parsed, errors = [], []
82
+ for _sp in SUITES:
83
+ _suite, _evals, _errs = validate_suite(_sp)
84
+ parsed.append((os.path.basename(_sp), _suite, _evals))
85
+ errors += [f"{os.path.basename(_sp)}: {e}" for e in _errs]
71
86
 
72
87
  if errors:
73
88
  print("FAIL: evaluation suite invalid")
@@ -75,31 +90,42 @@ def main(argv):
75
90
  print(" - " + e)
76
91
  return 1
77
92
 
93
+ suite = next(s for n, s, ev in parsed if n == "task-pipeline.evals.json")
94
+ evals = [e for _, _, ev in parsed for e in ev]
78
95
  by_cat = {}
79
96
  for e in evals:
80
97
  by_cat.setdefault(e["category"], []).append(e)
81
98
 
82
99
  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")
100
+ for name, _s, ev in parsed:
101
+ print(f"{name} {_s.get('skill', '?')}")
102
+ for cat in REQUIRED:
103
+ for e in ev:
104
+ if e["category"] == cat:
105
+ print(f" {e['id']:<10} {cat:<22} {e['query'][:60]}")
106
+ print(f"\n{len(evals)} evals across {len(by_cat)} categories, "
107
+ f"{len(parsed)} suite(s)")
87
108
  return 0
88
109
 
89
110
  print("=" * 72)
90
- print("task-pipeline evaluation protocol")
111
+ print("task-pipeline plugin evaluation protocol (one section per suite)")
91
112
  print("=" * 72)
92
- print("Run each query in a FRESH session with the skill installed, once per")
113
+ print("Run each query in a FRESH session with the pack installed, once per")
93
114
  print("model in", suite.get("models", []), "— effectiveness varies by model.")
94
115
  print("Record every verdict in evals/RESULTS.md with the date and the model.")
95
116
  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}")
117
+ for name, _s, ev in parsed:
118
+ print(f"\n=== {name} — {_s.get('skill', '?')} ===")
119
+ for cat in REQUIRED:
120
+ group = [e for e in ev if e["category"] == cat]
121
+ if not group:
122
+ continue
123
+ print(f"\n--- {cat} ---")
124
+ for e in group:
125
+ print(f"\n[{e['id']}] {e['query']}")
126
+ print(f" why: {e['why']}")
127
+ for b in e["expected_behavior"]:
128
+ print(f" [ ] {b}")
103
129
 
104
130
  print("\n" + "=" * 72)
105
131
  if not os.path.isfile(RESULTS):
@@ -118,6 +144,8 @@ def main(argv):
118
144
  if not infence:
119
145
  outside.append(ln)
120
146
  runs = [l for l in outside if re.match(r"^## 20\d{2}-\d{2}-\d{2}\b", l)]
147
+ print("suites: " + " · ".join(f"{n.replace('.evals.json', '')} {len(ev)}"
148
+ for n, _s, ev in parsed))
121
149
  print(f"suite: {len(evals)} evals · recorded runs: {len(runs)}")
122
150
  if not runs:
123
151
  print("RESULTS.md carries no dated run — the suite is authored and unexecuted.")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeline-skill",
3
- "version": "1.79.1",
3
+ "version": "1.80.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"
@@ -1,8 +1,9 @@
1
1
  {
2
+ "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
2
3
  "name": "task-pipeline",
3
4
  "displayName": "Task Pipeline",
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.79.1",
5
+ "description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/judgment/manual gates, a frozen requirement spine that closes with evidence, a work board and a verification ledger that outlive a run, an exposure line naming what shipped unconfirmed, a progress rail computed from the project's own config, a loop guard whose review ceiling measures rather than stops, and stage-3 tracks for what a product does, how it sounds and how it looks. Two modes need no task: `checkup` (what is unverified) and `setup` (audit existing docs). Retro insights can publish upstream as issues, opt-in and redacted.",
6
+ "version": "1.80.0",
6
7
  "author": {
7
8
  "name": "ssheleg",
8
9
  "url": "https://x.com/sshlg93"
@@ -100,7 +100,8 @@ Anything deferred enters the carry-over ledger the moment it is said.
100
100
  | 9 | Docs + wiki | **three artifacts, not two** — module docs, the wiki, **and the code graph** |
101
101
  | 10 | Acceptance | the ladder walk first, then the table, then the retrospective |
102
102
 
103
- **Honor every gate by its type**: `auto` — verify the check yourself; `manual` — wait
103
+ **Honor every gate by its type**: `auto` — verify the check yourself; `judgment` —
104
+ record the named judge's ruling as judgement, never as a measurement; `manual` — wait
104
105
  for an explicit go.
105
106
 
106
107
  ## Cross-cutting — the three that fire at any stage
@@ -73,11 +73,28 @@ if not matches:
73
73
  # PostToolUse fires on success; PostToolUseFailure carries the error. Both are
74
74
  # wired to this script, and `error` present means the command did not exit 0.
75
75
  failed = bool(data.get("error")) or data.get("hook_event_name") == "PostToolUseFailure"
76
- out = data.get("tool_output") or {}
77
- if isinstance(out, dict) and out.get("exit_code") is not None:
76
+ # The harness documents the result field as `tool_response`; `tool_output` is the
77
+ # name this script shipped reading, so it stays as a fallback rather than a
78
+ # breaking change. Reading only the wrong name left the exit-code branch dead.
79
+ # The fallback is BY FIELD, not by object: the real Bash `tool_response` is
80
+ # {stdout, stderr, interrupted} with no exit_code, and `resp or legacy` made a
81
+ # legacy exit_code unreachable behind it — found by the R-005 reader, measured,
82
+ # before this shipped. The same reading found `interrupted`: a gate cut short
83
+ # is not a gate that passed, whatever a stale exit_code says, so a failure
84
+ # event or an interruption is never recorded as exit 0.
85
+ out = {}
86
+ interrupted = False
87
+ for cand in (data.get("tool_response"), data.get("tool_output")):
88
+ if isinstance(cand, dict):
89
+ interrupted = interrupted or bool(cand.get("interrupted"))
90
+ if not out and cand.get("exit_code") is not None:
91
+ out = cand
92
+ if out:
78
93
  code = int(out["exit_code"])
79
94
  else:
80
95
  code = 1 if failed else 0
96
+ if (failed or interrupted) and code == 0:
97
+ code = 1
81
98
 
82
99
  stamp = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
83
100
 
@@ -24,6 +24,7 @@ The full statement of each canon, its rationale and its enforcement live in
24
24
  7. **Silence is not a pass** — ask what a mechanism prints when it did not look.
25
25
  8. **An estimate is never announced as a measurement** — a rule states its evidence condition.
26
26
  9. **What was not checked is printed beside what was.**
27
+ - **9a. A measured zero and an unmeasured quantity may not print the same** — canon 9 says carry the absence; 9a says refuse the number when nothing measured it.
27
28
  10. **The document ships in the change that made it true** — and a correction is appended, never written over.
28
29
 
29
30
  They are **epistemic**: what makes a claim documentation. The operational layer — what to
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: project-audit
3
3
  description: "Use when someone asks what is actually true of a whole project right now — what is finished, what is half-built, what is broken, and what nobody has looked at. Walks a cold start: discover what the project is, run a registry of probes chosen from that, read production evidence (published artefact against source, CI history, telemetry present or absent), then leave a self-contained HTML report and a JSON sidecar so the next audit can say what moved. Read-only: it proposes board rows and commits nothing. Triggers - 'project audit', 'audit the project', 'codebase audit', 'state of the project', 'what is unfinished', 'project health check', 'аудит проекта', 'проаудируй проект', 'состояние проекта', 'что не доделано', 'аудит кодовой базы'. Not for: auditing one deliverable inside a run (that is the pipeline's own ladder), reviewing a diff, or checking a skill's construction — say 'без диагностики' to opt out."
4
+ compatibility: "The collector (scripts/audit.py) needs python3 and reads committed state, so it needs git. Probes needing gh, npm, network or a browser declare it and report blind when it is absent — degraded, never silent."
4
5
  ---
5
6
 
6
7
  # Project audit — what is true of this project right now
@@ -33,6 +34,7 @@ next audit reads.
33
34
  | this skill | the **procedure** — cold start, probes, production, the report | a whole project is the subject |
34
35
  | `/skill-audit` (make-skill) | a skill's construction against the standard | the thing audited is a skill or plugin |
35
36
  | `/ux-audit` (super-ux) | code against documented scenarios | the question is user-facing behaviour |
37
+ | `/seo-aeo-audit` (seo-aeo-audit) | a public surface's search and answer-engine visibility | the question is whether a machine will find it |
36
38
 
37
39
  **The method is not restated here.** Phase 4 below hands off to `audit.md` and
38
40
  comes back; a second copy of the ladder would be a second rule, and the two
@@ -96,8 +98,11 @@ the same object.
96
98
  ### 6. Propose — rows, not edits
97
99
 
98
100
  **This skill commits nothing.** Findings leave as board rows in the project's
99
- own vocabulary, priced with the project's own formula —
100
- `P = blast × (1 + age_runs) / effort` — and the operator accepts them. An audit
101
+ own vocabulary, priced with **the board header's declared formula** the shipped
102
+ default is `Sev × Blast + age_bonus` (`references/backlog.md`, the pipeline's
103
+ board doctrine) — and the operator accepts them. Effort never ranks inside an
104
+ audit: what a fix costs is the fixer's decision, not the finder's
105
+ (`references/prioritisation.md`). An audit
101
106
  that edits while it reads cannot be re-run to check itself.
102
107
 
103
108
  ## Three verdicts, and why the third one exists
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: task-pipeline
3
- description: "Use when work changes the repository — feature, fix, refactor, migration, integration, rewrite, adoption or hardening; фича, фикс, рефактор, миграция, интеграция, доработать, починить, внедрить, перевести — or when the output is a finding that lands in it: audit/аудит, bug hunt/проверь ошибки, production check/проверь прод, PR review/ревью PR — or on 'run this through the pipeline' / 'прогони по конвейеру', 'full cycle, the full cycle' / 'полный цикл', /task-pipeline. Runs a substantial task through an intake grill, docs study, brainstorm, spec, plan, build, tests, deploy, post-deploy, docs/wiki sync and acceptance with explicit gates. 'checkup' / 'чекап' reports unconfirmed releases; 'setup' audits existing docs. Not for: answering a question, explaining code, a typo or a one-line edit — say 'без пайплайна' / 'quick' to opt out."
3
+ description: "Use when work changes the repository — feature, fix, refactor, migration, integration, rewrite, adoption or hardening; фича, фикс, рефактор, миграция, интеграция, доработать, починить, внедрить, перевести — or when the output is a finding that lands in it: audit/аудит, bug hunt/проверь ошибки, production check/проверь прод, PR review/ревью PR — or on 'run this through the pipeline' / 'прогони по конвейеру', 'full cycle, the full cycle' / 'полный цикл', /task-pipeline. Runs a substantial task through an intake grill, docs study, brainstorm, spec, plan, build, tests, deploy, post-deploy, docs/wiki sync and acceptance with explicit gates. 'checkup' / 'чекап' reports unconfirmed releases; 'setup' audits existing docs. Not for: answering a question, explaining code, a typo or a one-line edit, a mechanical rename, reconnaissance that lands nothing — say 'без пайплайна' / 'quick' to opt out."
4
4
  license: MIT
5
+ compatibility: "Doctrine runs on any agent. The bundled scripts need python3; the run needs git. Missing either degrades, never blocks — the graph verbs and seeded gates go unused, and the run says so."
5
6
  ---
6
7
 
7
8
  # task-pipeline
@@ -27,8 +28,11 @@ that encodes this plugin's own default flow (stage 0 intake + the 1→10 stages
27
28
  tabled below) and an optional, toggleable `release` block. Any project replaces it
28
29
  wholesale — any number of stages, run by its own skills/agents, with its own gate
29
30
  types (see *Bring your own skills*). Each gate has a **type**: `auto` (the
30
- orchestrator verifies the `check` itself, pass/fail) or `manual` (wait for an
31
- explicit operator go); which stages are manual is the operator's call. In the
31
+ orchestrator verifies the `check` itself, pass/fail), `judgment` (no complete
32
+ deterministic check exists a named judge rules, and the ruling is recorded as
33
+ judgement, never as a measurement; `references/gates.md` → *The judgment gate*)
34
+ or `manual` (wait for an explicit operator go); which stages are manual is the
35
+ operator's call. In the
32
36
  example's `skills[]`, `task-pipeline:<name>` denotes this skill's own built-in
33
37
  doctrine (`references/<name>.md`) and `host:<name>` denotes the host project's own
34
38
  command for that job (`references/conventions.md`); everything else is a real skill
@@ -59,7 +63,7 @@ gate stops until it is installed.
59
63
  | 3 Spec | `references/spec.md` |
60
64
  | 4 Plan | `references/planning.md` |
61
65
  | the queue the loop walks | `references/work-graph.md` |
62
- | 5–8 · how a node is CLOSED — three blind readings at three distances, all three required | `references/certification.md` |
66
+ | 5–8 · how a **work-graph node** is CLOSED — three blind readings at three distances, all three required (ceiling 3); a **prose-plan task** closes through `review.md` instead — one reviewer, five-round cap | `references/certification.md` |
63
67
  | 5 Build (worktree, subagents, fix loop) | `references/build.md` + `references/review.md` |
64
68
  | 5–6 TDD + suite gate | `references/tdd.md` |
65
69
  | 5, 6, 8 The browser — the look, the spec suite, and the difference | `references/browser.md` |
@@ -108,12 +112,11 @@ bind this run, the log queried because nothing caps it — are in
108
112
  `references/knowledge-sources.md` and `references/retrospective.md`.
109
113
 
110
114
  **Three artifacts close a run, not two — and they are a convergence, not a sequence.**
111
- Stage 9 syncs the docs, the wiki **and the code graph**. None consumes another; all three
112
- consume the same change, and the **graph↔docs divergence check is the gate over their
113
- convergence** — the only thing that compares two of the three against each other, which
114
- is why it is not optional where a graph exists. A stale graph is a false premise
115
- **carrying the authority of a machine**: a wrong doc gets argued with, a wrong graph gets
116
- believed (`references/knowledge-graph.md`, `references/audit.md`).
115
+ Stage 9 syncs the docs, the wiki **and the code graph**; none consumes another, and the
116
+ **graph↔docs divergence check is the gate over their convergence** — the only thing
117
+ comparing two of the three against each other, so it is not optional where a graph
118
+ exists. A stale graph is a false premise **carrying the authority of a machine**
119
+ (`references/knowledge-graph.md`, `references/audit.md`).
117
120
 
118
121
  **Documentation is a deliverable, and it has a gate** (`references/documentation.md`).
119
122
  Stage 0 answers the four questions that make docs a *system* into `docs/DOCMAP.md`;
@@ -133,26 +136,14 @@ triggers and what an entry must carry are in `references/retrospective.md`; why
133
136
  the order cannot be swapped is `references/learned.md` rule 21.
134
137
 
135
138
  Stage 0 reads those standing instructions in full, which is why the prune is a gate
136
- criterion and not a good intention: a rule nobody reads to the end is worse than no
137
- rule, because everyone believes it is covered.
139
+ criterion: a rule nobody reads to the end is worse than no rule, because everyone
140
+ believes it is covered.
138
141
 
139
- Three things the grill does beyond clarifying the request:
140
- - **Domain awareness.** It reads the project's own `CONTEXT.md` / `docs/adr/` and
141
- holds the operator to them challenging terms that conflict with the glossary,
142
- sharpening overloaded words, stress-testing with concrete scenarios, and
143
- flagging where the code contradicts what was just said. Resolved terms are
144
- written to `CONTEXT.md` as they land; genuinely hard-to-reverse decisions get an
145
- ADR.
146
- - **The autonomy sweep.** It pre-resolves what would otherwise stop stages 1→10
147
- mid-flight (test/lint/deploy commands, branch policy, log locations, docs
148
- targets, the model decision, deploy authorization). Autonomy is bought here or
149
- not at all — an unasked question is a scheduled interruption.
150
- - **The design destination**, when the project designs in Figma: *which* file, in
151
- which team — a stage-0 decision, never a stage-3 side effect. Left to drawing
152
- time the question is answered by whoever is holding the brush, and the answer is
153
- usually *create a new file* — which is how a project ends up with three files
154
- called some variation of "Design", each with real work in it and no way to tell
155
- which one the team opens.
142
+ Three things the grill does beyond clarifying the request, each in full in
143
+ [`references/grill.md`](references/grill.md):
144
+ - **Domain awareness** — it reads the project's `CONTEXT.md` / `docs/adr/` and holds the operator to them, writing resolved terms back as they land.
145
+ - **The autonomy sweep** — it pre-resolves what would otherwise stop stages 1→10 mid-flight. Autonomy is bought here or not at all; an unasked question is a scheduled interruption.
146
+ - **The design destination** with Figma on *which* file, in which team, decided at stage 0. Left to drawing time it is answered by whoever holds the brush, and the answer is usually *create a new file*.
156
147
 
157
148
  ## How to run
158
149
 
@@ -165,7 +156,9 @@ Three things the grill does beyond clarifying the request:
165
156
  the most capable model available, let the operator confirm or override, record
166
157
  it. Ask once, here. **The same block carries the run mode**
167
158
  (`references/continuity.md`): read `pipeline.json` → `run.loop`; where it is
168
- recorded, arm it and print the job id and the cancel command the config is
159
+ recorded, arm it **at the point `run.loop.arm` names** here at preflight, or
160
+ at stage 2's close for `after-decomposition`, once the queue exists — and when
161
+ it arms, print the job id and the cancel command; the config is
169
162
  the authorization, so re-asking rebuilds the habit it exists to retire. Where
170
163
  it is **absent, the mode is off**; recommend it in one line and move on.
171
164
  Silence arms nothing, and the mode never collapses a `manual` gate.
@@ -193,9 +186,10 @@ Three things the grill does beyond clarifying the request:
193
186
  status column is the resume point (`references/stages.md` → *The program loop*).
194
187
  4. Do **not** advance until the stage **gate** passes (`references/stages.md`).
195
188
  Honor the gate **type**: for `auto`, verify the gate's `check` yourself and
196
- stop/return on fail; for `manual`, present the result and **wait for the
197
- operator's explicit "continue"/go** an auto gate never substitutes for a
198
- required manual approval.
189
+ stop/return on fail; for `judgment`, record the named judge's ruling as
190
+ judgement, never as a measurement; for `manual`, present the result and
191
+ **wait for the operator's explicit "continue"/go** — neither of the other
192
+ two ever substitutes for a required manual approval.
199
193
  5. **The cross-cutting rules fire at any stage**, not only here — the Doc Loop, the
200
194
  loop guard, the audit's exit, the frozen REQ list, the carry-over ledger, and
201
195
  what counts as evidence, and **every gate prints `holds: N`** — what this run left
@@ -217,9 +211,9 @@ capable available — see `references/model-tiering.md`).
217
211
  | 3 | Spec | committed + reviewed; UI: chain validated, linter green, scenarios and `SCR-` traced; COPY and VISUAL are a parallel layer after UX, and where both ran their convergence check is recorded | manual |
218
212
  | 4 | Plan | parallel-ready, DoD per task; **every edge names what it carries** — the fake-edge test run and its `Edges:` count computed | auto |
219
213
  | 5 | Dev | tasks DONE, TDD green per task, branch integrated per the brief; a fanned-out group gets **one convergence check over all its diffs together** before the first worktree lands | auto |
220
- | 6 | Tests | full suite green, new and changed code covered, every new check probed both ways and asserted on its exit code; **a web surface is checked in a browser, not in the diff** | auto |
214
+ | 6 | Tests | full suite green, new and changed code covered, every new check probed both ways and asserted on its exit code; **a web surface is checked in a browser, not in the diff** — where a browser channel is connected; absent, the weaker claim is recorded | auto |
221
215
  | 7 | Lint + deploy | lint clean and suite green before deploy; deploy needs a go, or the brief's specific standing authorization | manual |
222
- | 8 | Post-deploy | clean boot or an honest degradation report; **a deployed web target is opened, not curled** — a `200` proves the server answered and nothing else | auto |
216
+ | 8 | Post-deploy | clean boot or an honest degradation report; **a deployed web target is opened, not curled** — a `200` proves the server answered and nothing else; where no browser channel is connected, the weaker claim is recorded | auto |
223
217
  | 9 | Docs + wiki | every stale row of the stage-0 source ledger updated; the propagation matrix walked for every change type this run produced; the documentation gate green with its ratchets printed; docs, wiki and the code graph synced and checked against each other | auto |
224
218
  | 10 | **Acceptance** | the ladder walk ran and its absences became REQ rows; every REQ accounted for with evidence from a check seen failing once; no unresolved ledger row; **every repository clean, pushed and pointed at**; the hand-back written and the environment given back; the retrospective written **last**, and in order | manual |
225
219
 
@@ -228,42 +222,41 @@ capable available — see `references/model-tiering.md`).
228
222
  ladder walk is, which eight environment classes stage 10 enumerates, what makes an
229
223
  edge fake, why a `200` is not a working page: all there, none here.
230
224
 
231
- **Several repositories?** A submodule is finished when its parent says so — the
232
- work can be committed, pushed and green while a clone of the parent still gets the
233
- commit before it, and neither repository looks wrong alone. The two commands that
234
- prove it, and the two-command fix whose second half gets forgotten, are in
225
+ **Several repositories?** A submodule is finished when its parent says so — a clone
226
+ can still get the commit before it while neither repository looks wrong alone. The
227
+ commands that prove it are in
235
228
  [`references/acceptance.md`](references/acceptance.md) → *A project of several
236
229
  repositories*.
237
230
 
238
231
  ## Model — ask once, at preflight
239
232
 
240
- Default recommendation: **the most capable reasoning model the environment
241
- offers** (currently the latest Opus generation read that as a tier, not a
242
- string). **Never hardcode a model id**: generations ship, tiers get renamed, and
243
- the operator may be on another provider entirely resolve the top tier available
244
- at runtime. Stage configs use provider-agnostic tokens (`default` / `inherit`).
233
+ Recommend **the most capable reasoning model available** — a tier resolved at
234
+ runtime, **never a hardcoded id**; stage configs use `default` / `inherit`. The
235
+ block to emit is `references/model-tiering.md` *Mechanic*, and it is a
236
+ reminder: no such tier means say which one is in use and continue. Record the
237
+ answer in the brief, don't re-ask per stage; stage-5 subagents are pinned to it
238
+ automatically.
245
239
 
246
- > 🧠 **Model for this run:** recommended **`<top tier available>`**. You're on
247
- > `<current>`. `/model <id>` to switch, or "keep current", or name per-stage
248
- > overrides. *(Reminder only — if that tier isn't available, say which one you're
249
- > using and continue.)*
240
+ ## Degradation
250
241
 
251
- Record the answer in the brief; don't re-ask per stage. Stage-5 subagents are
252
- pinned to the confirmed model automatically. Detail: `references/model-tiering.md`.
242
+ - **No python3** → the work-graph verbs and the seeded gate scripts cannot run: the queue degrades to a prose plan, the gates to checklists — said out loud, never silently.
243
+ - **No git** no worktree isolation and no commit-addressed evidence: the run records the weaker claim instead of pretending to the stronger one.
244
+ - **No browser channel** → a web surface is verified by reading the diff, and the close-out records that as the weaker claim it is.
253
245
 
254
246
  ## Bring your own skills
255
247
 
256
248
  The stages above are the **example** flow. A host project owns its pipeline: copy
257
249
  `pipeline.example.json` → `pipeline.json`, define its **own** stages (any count),
258
250
  point each `skills[]` at what its environment resolves, set each `gate.type`
259
- (`auto`/`manual`) to fit its process, and toggle its own `release` block. The
251
+ (`auto`/`judgment`/`manual`) to fit its process, and toggle its own `release`
252
+ block. The
260
253
  framework ships no fixed stage count and no opinion on which gates are manual —
261
254
  `pipeline.schema.json` is the only contract.
262
255
 
263
256
  ## References
264
257
 
265
- Every reference is routed from the **Built-in doctrine** table above, keyed by
266
- the stage that sends you there one home for that mapping rather than two. The
267
- two config contracts sit beside this file: `pipeline.schema.json` (the universal
268
- stages + release contract) and `pipeline.example.json` (this plugin's default
269
- flow as config).
258
+ Most references are routed from the **Built-in doctrine** table above, keyed by
259
+ the stage that sends you there. The rest are routed by prose: `stages.md` (named
260
+ at every stage of *How to run*), `learned.md` (cited where a rule binds) and
261
+ `probing.md` (from `gates.md`, whose checks it proves). The config contracts sit
262
+ beside this file: `pipeline.schema.json` and `pipeline.example.json`.
@@ -65,7 +65,7 @@
65
65
  ],
66
66
  "gate": {
67
67
  "type": "manual",
68
- "check": "UX track ran FIRST for user-facing tasks (/ux -> ux-foundation CJM -> ux-flows screens -> ux-scenarios -> /ux-lint green); spec committed and user-reviewed; every user-facing requirement traces to a scenario ID. Every spec section carries covers: REQ-... and every REQ appears in at least one section. With Figma on: the destination the brief named was used — the canonical record (docs/ux/foundation.md -> Design tooling) holds exactly one file, no file was created while a recorded one resolved, and every screens.md frame link carries that same :fileKey (a string match, not a judgement — a differing key means the run drew in a second file nobody will open)."
68
+ "check": "UX track ran FIRST for user-facing tasks (/ux -> ux-foundation CJM -> ux-flows screens -> ux-scenarios -> /ux-lint green); spec committed and user-reviewed; every user-facing requirement traces to a scenario ID. Every spec section carries covers: REQ-... and every REQ appears in at least one section. With Figma on: the destination the brief named was used — the canonical record (docs/ux/foundation.md -> Design tooling) holds exactly one file, no file was created while a recorded one resolved, and every screens.md frame link carries that same :fileKey (a string match, not a judgement — a differing key means the run drew in a second file nobody will open). COPY and VISUAL are a parallel layer after UX: every user-facing string went through the COPY track or the refusal is recorded, the visual layer went through the VISUAL track or the refusal is recorded, and where both tracks ran their convergence check is recorded - findings with the ruling, or 'Tracks converge: clean'."
69
69
  }
70
70
  },
71
71
  {
@@ -354,7 +354,7 @@ All of:
354
354
  the table was written, and the two pass counts recorded.
355
355
  3. **Every check this gate leans on has been seen failing** at least once against a
356
356
  planted defect (`audit.md` → *Exit criterion*; the procedure, with the commands,
357
- is [`gates.md`](gates.md) → *Probing*). An unproven check's green is not
357
+ is [`probing.md`](probing.md) → *Probing — plant, run, restore*). An unproven check's green is not
358
358
  evidence. That includes **the documentation gate** the project's doc map names
359
359
  ([`documentation.md`](documentation.md)) — stage 9 ran it, this stage is where it
360
360
  is *proven*, and its **ratchet counts are printed beside this verdict**. A
@@ -80,12 +80,23 @@ being *unrecorded* is the defect, not the choice.
80
80
  Usually the map and the gate; often the register already exists in some shape.
81
81
 
82
82
  ```bash
83
- cp <skill>/templates/docmap.md docs/DOCMAP.md # only if absent
84
- cp <skill>/templates/docgate.sh scripts/check-docs.sh # only if absent
85
- cp <skill>/templates/exposure.sh scripts/exposure.sh # only if absent
86
- chmod +x scripts/check-docs.sh scripts/exposure.sh
83
+ cp <skill>/templates/docmap.md docs/DOCMAP.md # only if absent
84
+ cp <skill>/templates/docgate.sh scripts/check-docs.sh # only if absent
85
+ cp <skill>/templates/exposure.sh scripts/exposure.sh # only if absent
86
+ cp <skill>/templates/hygiene.sh scripts/check-hygiene.sh # only if absent
87
+ cp <skill>/templates/stage-coverage.sh scripts/stage-coverage.sh # only if absent
88
+ cp <skill>/templates/convergence.sh scripts/check-convergence.sh # only if absent, and only where the project pins components
89
+ chmod +x scripts/check-docs.sh scripts/exposure.sh scripts/check-hygiene.sh \
90
+ scripts/stage-coverage.sh scripts/check-convergence.sh
87
91
  ```
88
92
 
93
+ The last three are the scripts the later gates run — stage 5 runs
94
+ `check-hygiene.sh` after every task, stage 10 runs `stage-coverage.sh` before the
95
+ coverage table and `check-convergence.sh` where components are pinned
96
+ ([`../templates/README.md`](../templates/README.md) is the full seeding map). A
97
+ fresh host that skips them reaches gates whose commands do not resolve, which
98
+ reads as a broken gate rather than a skipped seeding.
99
+
89
100
  **Seeding never overwrites.** An existing brief, register or map is the project's
90
101
  memory; the template is a skeleton.
91
102
 
@@ -89,8 +89,10 @@ validator). `test/artifact_root_test.py` runs both against one case table and fa
89
89
  they disagree — which is why one rule is allowed two implementations here.
90
90
 
91
91
  **Every** run keeps a **git-ignored** run ledger at `.task-pipeline/run.md`, seeded at
92
- stage 0 from [`../templates/run.md`](../templates/run.md). Three line shapes: a
93
- `stage:` verdict when a gate returns, an `iter:` line when an iteration closes, and a
92
+ stage 0 from [`../templates/run.md`](../templates/run.md), whose *Lines* section
93
+ declares every line shape the list is the count, and a count restated here said
94
+ *three* over a template of eight. Among them: a `stage:` verdict when a gate
95
+ returns, an `iter:` line when an iteration closes, and a
94
96
  `touch:` line per file per repeating pass. Two readers depend on it —
95
97
  [`loop-guard.md`](loop-guard.md) detects churn from the `touch:` lines after a lost
96
98
  context, and [`progress.md`](progress.md) derives the stage rail and the iteration
@@ -142,7 +142,12 @@ The operator approves the design, **the UI verdict is recorded**, and — where
142
142
  is either covered now or explicitly dropped by the operator, with the drop written
143
143
  into the carry-over ledger. For a platform, the module map
144
144
  ([`decomposition.md`](decomposition.md)) is committed and approved as part of this
145
- same gate. Then, and only then, stage 3 writes it up.
145
+ same gate. Two more criteria close it, and the gate of record —
146
+ [`stages.md`](stages.md) → *2 — Brainstorm + decompose* — states both in full:
147
+ **the queue is an artifact rather than a recollection** (where it is a work graph,
148
+ `graph.py validate` exits 0 and `graph.py coverage` names any requirement no node
149
+ serves), and **the loop's arming state is printed** — armed with its queue and
150
+ pacing, or not armed with the reason. Then, and only then, stage 3 writes it up.
146
151
 
147
152
  ## Rationalizations
148
153
 
@@ -374,6 +374,13 @@ satisfied**, and code quality. The implementer's self-review never substitutes f
374
374
  it. Rubric, inputs, prompt templates and how to build the diff package:
375
375
  [`review.md`](review.md).
376
376
 
377
+ **The boundary with certification:** this review closes a **prose-plan task** —
378
+ one reviewer, the five-round cap of §4.5. A **work-graph node** is closed by the
379
+ three blind tiers and `graph.py certify` instead
380
+ ([`certification.md`](certification.md), ceiling 3); the artifact the queue is —
381
+ plan or graph — decides which protocol closes the work, never whichever is
382
+ cheaper at the moment of closing.
383
+
377
384
  The REQ verdict is the one the other two can't produce: a task can meet every line
378
385
  of its brief and still miss the requirement it was written to deliver. A ❌ there
379
386
  enters the fix loop like any Important finding.
@@ -561,7 +568,10 @@ stages 7–9 run against an unintegrated branch.
561
568
 
562
569
  ## GATE (auto)
563
570
 
564
- All plan tasks DONE with all three review verdicts (spec compliance, REQ satisfied,
571
+ **The hygiene gate green in diff mode after every task** (*The hygiene gate*,
572
+ above) — six checks over what that task changed, no floor, a finding fixed
573
+ in-task or carried over with a reason;
574
+ all plan tasks DONE with all three review verdicts (spec compliance, REQ satisfied,
565
575
  code quality); **every group that actually fanned out has run its convergence check
566
576
  (§4.2a) before its first worktree was integrated, and logged a line either way** —
567
577
  findings with their ruling, or `convergence check clean`; the full test suite green;
@@ -4,6 +4,13 @@ A node is not closed by one agent's opinion. It is closed by **three independent
4
4
  readings at escalating visibility**, and the run may not advance until all three
5
5
  pass.
6
6
 
7
+ **The boundary: this closes a node of the work graph.** Where the queue is a
8
+ prose plan rather than a graph, a task closes through the per-task review instead
9
+ ([`build.md`](build.md) §4.4 and [`review.md`](review.md) — one reviewer, a
10
+ five-round fix loop with an explicit breaker). Two closure protocols with no
11
+ boundary sentence were how a run picked whichever was cheaper; the artifact the
12
+ queue is — graph or plan — is what decides, not the mood of the closer.
13
+
7
14
  ## Contents
8
15
 
9
16
  - Why one verifier is not enough, stated as the failure it produces