task-pipeline-skill 1.85.2 → 1.86.3

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 (57) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/CONTRIBUTING.md +2 -2
  3. package/README.md +2 -1
  4. package/SKILL-CARD.md +1 -1
  5. package/bin/task-pipeline.js +70 -9
  6. package/evals/cases/evidence-docs.json +188 -0
  7. package/evals/cases/project-audit.json +188 -0
  8. package/evals/cases/task-pipeline.json +191 -0
  9. package/package.json +5 -4
  10. package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
  11. package/plugins/task-pipeline/skills/evidence-docs/SKILL.md +16 -11
  12. package/plugins/task-pipeline/skills/evidence-docs/references/GENERATED.md +8 -0
  13. package/plugins/task-pipeline/skills/evidence-docs/references/documentation.md +472 -0
  14. package/plugins/task-pipeline/skills/evidence-docs/references/gates.md +645 -0
  15. package/plugins/task-pipeline/skills/evidence-docs/references/hooks.md +279 -0
  16. package/plugins/task-pipeline/skills/evidence-docs/references/learned.md +292 -0
  17. package/plugins/task-pipeline/skills/evidence-docs/references/retrospective.md +551 -0
  18. package/plugins/task-pipeline/skills/evidence-docs/references/setup.md +149 -0
  19. package/plugins/task-pipeline/skills/evidence-docs/templates/decisions.md +50 -0
  20. package/plugins/task-pipeline/skills/evidence-docs/templates/docgate.sh +537 -0
  21. package/plugins/task-pipeline/skills/project-audit/SKILL.md +66 -25
  22. package/plugins/task-pipeline/skills/project-audit/scripts/audit.py +11 -0
  23. package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +71 -54
  24. package/plugins/task-pipeline/skills/task-pipeline/execution-attempt.schema.json +68 -0
  25. package/plugins/task-pipeline/skills/task-pipeline/execution-packet.example.json +42 -0
  26. package/plugins/task-pipeline/skills/task-pipeline/execution-packet.schema.json +217 -0
  27. package/plugins/task-pipeline/skills/task-pipeline/execution-result.example.json +49 -0
  28. package/plugins/task-pipeline/skills/task-pipeline/execution-result.schema.json +261 -0
  29. package/plugins/task-pipeline/skills/task-pipeline/graph.example.json +10 -1
  30. package/plugins/task-pipeline/skills/task-pipeline/graph.schema.json +172 -2
  31. package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +50 -1
  32. package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +7 -0
  33. package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +23 -0
  34. package/plugins/task-pipeline/skills/task-pipeline/references/audit.md +6 -0
  35. package/plugins/task-pipeline/skills/task-pipeline/references/backlog.md +8 -1
  36. package/plugins/task-pipeline/skills/task-pipeline/references/browser.md +8 -0
  37. package/plugins/task-pipeline/skills/task-pipeline/references/build.md +32 -0
  38. package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +14 -3
  39. package/plugins/task-pipeline/skills/task-pipeline/references/decomposition.md +83 -2
  40. package/plugins/task-pipeline/skills/task-pipeline/references/doctrine-map.md +53 -0
  41. package/plugins/task-pipeline/skills/task-pipeline/references/documentation.md +3 -0
  42. package/plugins/task-pipeline/skills/task-pipeline/references/grill.md +27 -8
  43. package/plugins/task-pipeline/skills/task-pipeline/references/hooks.md +10 -5
  44. package/plugins/task-pipeline/skills/task-pipeline/references/model-tiering.md +19 -0
  45. package/plugins/task-pipeline/skills/task-pipeline/references/planning.md +203 -26
  46. package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +1 -0
  47. package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +26 -8
  48. package/plugins/task-pipeline/skills/task-pipeline/references/work-graph.md +7 -1
  49. package/plugins/task-pipeline/skills/task-pipeline/scripts/context_packets.py +686 -0
  50. package/plugins/task-pipeline/skills/task-pipeline/scripts/execution_authority.py +271 -0
  51. package/plugins/task-pipeline/skills/task-pipeline/scripts/graph.py +415 -18
  52. package/plugins/task-pipeline/skills/task-pipeline/scripts/packet.py +400 -0
  53. package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +2 -0
  54. package/plugins/task-pipeline/skills/task-pipeline/templates/browser-claims.json +54 -0
  55. package/plugins/task-pipeline/skills/task-pipeline/templates/finding-evidence.json +42 -0
  56. package/plugins/task-pipeline/skills/task-pipeline/templates/hooks.example.json +2 -2
  57. package/plugins/task-pipeline/skills/task-pipeline/templates/run.md +2 -2
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: project-audit
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."
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 JSON sidecar so the next audit can say what moved, and a self-contained HTML report on request. 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
4
  license: MIT
5
5
  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."
6
6
  ---
@@ -122,23 +122,36 @@ audit: what a fix costs is the fixer's decision, not the finder's
122
122
  ([`references/prioritisation.md`](../task-pipeline/references/prioritisation.md)). An audit
123
123
  that edits while it reads cannot be re-run to check itself.
124
124
 
125
- ## A finding carries its consequence, or it is a hypothesis
126
-
127
- **A mechanism is derived from the code; the consequence lives in production.** A row
128
- written from the mechanism alone is indistinguishable from a real finding until
129
- somebody measures it and one audit had **eight consecutive rows** rewritten by that
130
- measurement, two of which would have destroyed inventory if remedied as written,
131
- because both read an absence of sales as an absence of demand.
132
-
133
- So before a row may be written as a `finding` rather than as a hypothesis:
134
-
135
- 1. **how often does the mechanism fire?** A query, a log count, a telemetry read — or
136
- an explicit statement that it has never been observed to fire;
137
- 2. **where the answer is *never*, the row is still worth keeping**, priced as
138
- **latent**: the remedy is weighed against zero rather than against the mechanism's
139
- severity;
140
- 3. **where the measurement is impossible, that is a `blind` on the consequence** and
141
- the row says so. A blind consequence is not a finding.
125
+ ## A finding keeps its axes apart, or it is a guess wearing a verdict
126
+
127
+ **Mechanism status, exploit/reproduction, exposure, observed incidence and impact
128
+ uncertainty are FIVE axes, not one.** A row written from the mechanism alone is
129
+ indistinguishable from a real finding until each axis says what it knows and one
130
+ audit had **eight consecutive rows** rewritten by measurement, two of which would
131
+ have destroyed inventory if remedied as written, because both read an absence of
132
+ sales as an absence of demand. But the correction cuts both ways:
133
+
134
+ - **A proven defect may have incidence UNKNOWN.** An auth bypass or a race
135
+ reproduced locally is a code defect BEFORE any incident the reproduction is the
136
+ proof, and no production log is needed to license the row. A confirmed local
137
+ crash with no production logs stays a code defect, external incidence UNKNOWN.
138
+ - **UNKNOWN 0.** A zero sample is not zero risk; absent telemetry lowers what can
139
+ be said about EXPOSURE, never the technical truth — and the row says which.
140
+ - **Unknown attacker control lowers exploitability CONFIDENCE**, never the observed
141
+ behaviour: what was watched happening stays written as watched.
142
+ - **A documented exception does not turn a failed invariant into PASS** — decision
143
+ status and technical validity are the separate axes of the section below.
144
+
145
+ The incidence axis is still asked: **how often does the mechanism fire?** A query, a
146
+ log count, a telemetry read. Where the answer is *never*, keep the row priced as
147
+ **latent** (the remedy weighed against zero); where the measurement is impossible,
148
+ the INCIDENCE axis records `blind` — and the finding stands on its mechanism and
149
+ reproduction axes. Each row records its observation scope and time, keeping code
150
+ mechanism, deployment observation and assumptions apart —
151
+ `templates/finding-evidence.json` in task-pipeline is the minimal schema, and the
152
+ collector writes `mechanism`/`incidence`/`observed_scope`/`observed_at` into the
153
+ sidecar. Ask an operator only when the unknown would change the action — an
154
+ interview is not a prerequisite for a row.
142
155
 
143
156
  Two rules follow from the same place:
144
157
 
@@ -159,9 +172,20 @@ Five of eight rows in one run were that.
159
172
  - **Read the call site, not only the definition.** A finding about a module is not
160
173
  written until the places that use it have been read.
161
174
  - **Every row states which of three it is:** *(a)* undecided, *(b)* decided and
162
- documented right here, *(c)* decided elsewhere and not propagated. Only **(a)** and
163
- **(c)** are work. **(b)** is the audit being wrong, and recording that is worth more
164
- than deleting the row.
175
+ documented right here, *(c)* decided elsewhere and not propagated. **(a)** and **(c)**
176
+ are work — and so is a **(b)** that is still WRONG, because **decision status and
177
+ technical validity are DIFFERENT AXES.** A documented decision can be mistaken, stale,
178
+ or break an external contract; "it's by design" is not a proof of correctness. So a
179
+ **(b)** splits:
180
+ - **accepted trade-off** — a conscious limitation with a real, named cost the project
181
+ chose to pay (single-browser support under a matching contract): mark it *accepted
182
+ limitation* with its cost, not a defect.
183
+ - **documented violation** — a decision that STILL breaks a security invariant, an
184
+ external contract, or its own stated goal (an ADR that permits logging a refresh
185
+ token): this REMAINS a `finding`, carrying the `decision_id`, the reason to revisit,
186
+ and the counter-evidence. Recording a **(b)** the audit got wrong (a false positive)
187
+ is worth more than deleting the row; but excluding every documented decision from
188
+ findings is a systemic source of false NEGATIVES, which is the more expensive miss.
165
189
  - **Where the verdict is (c), the remedy is a mechanical check, not an edit.** A
166
190
  written rule nobody verifies reaches exactly as far as the place it was written; the
167
191
  durable fix in all five cases was a guard that asks the project's own instruction of
@@ -210,7 +234,12 @@ Two more traps, both of which shipped in the first draft and are now fixtures:
210
234
  ## The artefacts — the sidecar always, the page on request
211
235
 
212
236
  `docs/audit/<date>-audit.json` is written on every run. **The HTML page is written
213
- only with `--report`.**
237
+ only with `--report`.** Three output modes, and only one needs a browser:
238
+ **stdout** (`--stdout` — the summary in the terminal, nothing written but the
239
+ sidecar), **json** (the sidecar alone, the default — a machine reads it, no
240
+ page and no browser), **html** (`--report` — the page too). A json-only or
241
+ stdout run **never opens a browser and never requires one**; the browser is a
242
+ concern of `--report` alone.
214
243
 
215
244
  The split is not symmetry. The sidecar is what makes this a ratchet rather than a
216
245
  snapshot, and the next run reads it — skipping it would silently turn every future run
@@ -230,6 +259,13 @@ stdout: an audit must not become the second place a credential leaks. Redaction
230
259
  is total rather than a prefix — half a credential plus its context is often
231
260
  enough to finish.
232
261
 
262
+ **"Read-only" is about the TARGET, not the disk.** The audit reads the
263
+ project's source, data and production evidence and mutates NONE of it, and it
264
+ commits nothing. It DOES write its own artefacts into its allowed output
265
+ directory (`docs/audit/` by default, `--out-dir` to relocate) — the sidecar
266
+ always, the page on `--report`. Writing the sidecar there is not a violation of
267
+ read-only; writing into the target's source, or `git add`-ing anything, is.
268
+
233
269
  **The sidecar is what makes this a ratchet rather than a snapshot.** Each
234
270
  finding carries an id derived from its probe and its place, so it survives a
235
271
  rewording; the next run prints what closed, what is new, and what has now
@@ -252,16 +288,21 @@ could not look.
252
288
 
253
289
  ## Exit criterion
254
290
 
255
- An audit is finished when:
291
+ An audit is finished when — the criterion is CONDITIONAL on the deliverables
292
+ requested, not a fixed page-and-browser:
256
293
 
257
294
  1. every probe has a verdict, and every `blind` one names why;
258
- 2. the page and the sidecar are written and the page has been opened;
295
+ 2. the sidecar is written (always). **On `--report`, and only then**, the HTML
296
+ page also exists, its internal links are safe and resolve, and its
297
+ inspect/render status is recorded (opened, or `--no-open` noted) — WITHOUT
298
+ `--report` no page is created and the run is still complete;
259
299
  3. **every number in the report was produced by a command this run executed** —
260
300
  a restated count is an assertion (`evidence-docs`);
261
301
  4. at least one figure was **re-derived by a differently-shaped command** and
262
302
  both were printed. Re-running the same command is a spell-check of the first
263
303
  run;
264
- 5. the proposed rows are printed for the operator, with nothing written.
304
+ 5. the proposed rows are printed for the operator, with nothing written to the
305
+ target.
265
306
 
266
307
  ## Rationalizations
267
308
 
@@ -897,12 +897,23 @@ def open_in_browser(path, opener=None):
897
897
 
898
898
  def _finding(probe_id, where, title, severity, blast, effort, remedy,
899
899
  detail="", evidence=""):
900
+ # The axes stay apart (FIX-PA-02.01): every shipped probe reads the tree,
901
+ # so its MECHANISM is confirmed with evidence — while this collector
902
+ # measures no production, so INCIDENCE is "unknown", and UNKNOWN != 0: it
903
+ # never lowers the mechanism's truth, only what may be claimed about
904
+ # exposure. Scope and time of the observation ride in the sidecar so the
905
+ # next audit knows what was looked at, and when.
900
906
  return {
901
907
  "id": finding_id(probe_id, where, title), "probe": probe_id,
902
908
  "title": title, "severity": severity, "where": where,
903
909
  "detail": detail, "evidence": evidence, "remedy": remedy,
904
910
  "blast": blast, "effort": effort, "runs_open": 0,
905
911
  "first_seen": datetime.date.today().isoformat(),
912
+ "mechanism": "confirmed",
913
+ "incidence": "unknown",
914
+ "observed_scope": "local checkout",
915
+ "observed_at": datetime.datetime.now(datetime.timezone.utc)
916
+ .strftime("%Y-%m-%dT%H:%M:%SZ"),
906
917
  }
907
918
 
908
919
 
@@ -12,12 +12,15 @@ own built-in doctrine — no companion plugin required. Keeps the main thread
12
12
  disciplined: no stage advances until its gate passes; the whole run uses one model,
13
13
  confirmed before it starts.
14
14
 
15
- **Grill first, then run autonomously.** A one-line task ("make me feature X") is
16
- never enough to finish without a human in the loop. Stage 0 is **mandatory**: a
17
- relentless, one-question-at-a-time interview that resolves every decision branch
18
- *and* sweeps stages 1→10 for anything that would stop the run later — then locks
19
- the answers into a brief. Autonomy is bought there or not at all; every question
20
- skipped at stage 0 comes back as an interruption at stage 6.
15
+ **Grill first, then run autonomously.** Stage 0 is **mandatory**, but it is a
16
+ GAP CHECK before it is an interview: the brief is built from the request, the
17
+ files and the harvest first, and a question is asked only for a **material
18
+ unknown** the sources cannot answer. A complete brief yields ZERO intake
19
+ questions; what the request or the project already decided is recorded, never
20
+ re-negotiated. The interview, where gaps remain, is one-question-at-a-time and
21
+ sweeps stages 1→10 for anything that would stop the run later — then locks the
22
+ answers into a brief. Autonomy is bought there or not at all; every MATERIAL
23
+ question skipped at stage 0 comes back as an interruption at stage 6.
21
24
 
22
25
  **Config contract: [`pipeline.schema.json`](pipeline.schema.json).** A pipeline is
23
26
  a machine-readable config — an ordered list of stages, each with `skills[]` (the
@@ -25,9 +28,21 @@ skills/agents that run it) and a `gate {type, check}`. The schema is the univers
25
28
  contract; it imposes **no** specific stages, skills, or gate assignments.
26
29
  [`pipeline.example.json`](pipeline.example.json) is a **copy-and-rewrite example**
27
30
  that encodes this plugin's own default flow (stage 0 intake + the 1→10 stages
28
- tabled below) and an optional, toggleable `release` block. Any project replaces it
29
- wholesale — any number of stages, run by its own skills/agents, with its own gate
30
- types (see *Bring your own skills*). Each gate has a **type**: `auto` (the
31
+ tabled below) and an optional, toggleable `release` block.
32
+
33
+ **Two layers, and only one is replaceable.** The **KERNEL** is what every
34
+ pipeline must carry no matter how few stages it has — for every unit of work:
35
+ its **scope** (what it may change), its **evidence** (a claim carries its
36
+ receipt), its **deps** (what it reads and what must precede it), and a
37
+ **resume** point (it survives context loss). The kernel is invariant. The
38
+ **PROFILE** is the STAGE LIST — how many stages, their names, their skills,
39
+ their gates — and a project **replaces the profile wholesale** (any number of
40
+ stages, its own skills/agents, its own gate types; see *Bring your own
41
+ skills*). **The stage numbers belong to the SELECTED profile, never to the
42
+ kernel:** a minimal three-stage profile has no "stage 7", and a rule keyed on a
43
+ global stage number is a rule about the default profile, not about every
44
+ pipeline. What a custom profile may drop is stages; what it may not drop is a
45
+ kernel field. Each gate has a **type**: `auto` (the
31
46
  orchestrator verifies the `check` itself, pass/fail), `judgment` (no complete
32
47
  deterministic check exists — a named judge rules, and the ruling is recorded as
33
48
  judgement, never as a measurement; `references/gates.md` → *The judgment gate*)
@@ -48,53 +63,30 @@ wiki and the code graph are recommendations. The **one** exception is deliberate
48
63
  named: on a user-facing task the stage-3 UX track requires super-ux, and the spec
49
64
  gate stops until it is installed.
50
65
 
51
- | Stage | Built-in doctrine |
52
- |---|---|
53
- | 0, 9 · The documentation system | `references/documentation.md` |
54
- | any stage · The canons, and where each is enforced | [`evidence-docs`](../evidence-docs/SKILL.md) — the sibling skill in this plugin |
55
- | 6–10 · Gates | `references/gates.md` |
56
- | 7–8 · Deploy targets | `references/deploy-targets.md` |
57
- | any stage · Hooks | `references/hooks.md` |
58
- | 0 Knowledge harvest (pre-grill) | `references/knowledge-sources.md` |
59
- | 0, 9 The code graph (graphify — recommended, never required) | `references/knowledge-graph.md` |
60
- | 0 Intake grill | `references/grill.md` |
61
- | 2 Brainstorm | `references/brainstorm.md` |
62
- | 2 Decompose (platforms only) | `references/decomposition.md` |
63
- | 3 Spec | `references/spec.md` |
64
- | 4 Plan | `references/planning.md` |
65
- | the queue the loop walks | `references/work-graph.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` |
67
- | 5 Build (worktree, subagents, fix loop) | `references/build.md` + `references/review.md` |
68
- | 5–6 TDD + suite gate | `references/tdd.md` |
69
- | 5, 6, 8 The browser — the look, the spec suite, and the difference | `references/browser.md` |
70
- | 10 Acceptance (REQ close-out) | `references/acceptance.md` |
71
- | 10 Retrospective (the run's last act) | `references/retrospective.md` |
72
- | 10 + any audit (what's *missing*) | `references/audit.md` |
73
- | **first run in a project** (new or existing) | `references/adoption.md` |
74
- | **first run · the entry audit** (offered once) | `references/setup.md` |
75
- | **what travels with the bundle vs stays in a project** | `references/portability.md` |
76
- | any repeating loop | `references/loop-guard.md` |
77
- | run-wide · what the run **leaves running and leaves behind** — every gate, and stage 10 | `references/residue.md` |
78
- | run-wide · what the run **prints about itself** — the rail, the iteration line | `references/progress.md` |
79
- | run-wide · how a run keeps going (the loop mode + the context budget) | `references/continuity.md` |
80
- | run-wide · the work-list **between** runs, and the order it comes off | `references/backlog.md` + `references/prioritisation.md` |
81
- | run-wide · whether a **human** ever confirmed what shipped, and when | `references/verification.md` |
82
- | run-wide · how much unconfirmed work has piled up, and what to look at first | `references/exposure.md` |
83
- | any stage · Where each artifact belongs | `references/artifacts.md` |
84
- | preflight · Companion skills and their fallbacks | `references/companion-skills.md` |
85
- | 6–10 · How the host project's CLAUDE.md is read | `references/conventions.md` |
86
- | preflight · Model map, ids and the override | `references/model-tiering.md` |
66
+ Which reference owns which stage — all forty-odd of them, by stage number:
67
+ [`references/doctrine-map.md`](./references/doctrine-map.md).
87
68
 
88
69
  **Optional bridge.** An equivalent skill set the operator already runs can be mapped
89
70
  onto stages 2/4/5/6 in `pipeline.json` → `skills[]`. That is a **substitution, never a
90
- requirement**: the built-in doctrine is normative, the gates in `references/stages.md`
91
- still govern, and nothing detects, recommends or waits for an external provider.
71
+ requirement**. And the precedence is explicit, because two layers could seem to
72
+ disagree: on a CUSTOM profile the **kernel wins** scope, evidence, deps and
73
+ resume are owed by every unit of work — while `references/stages.md` is the
74
+ **default profile's** normative gate set, governing the stages that profile
75
+ actually selects, not imposing its stage numbers on a profile that dropped
76
+ them. The built-in doctrine is normative for the default profile; the kernel is
77
+ normative for all. Nothing detects, recommends or waits for an external
78
+ provider.
92
79
 
93
- **super-ux — recommended for ANY user-facing task**, and the one thing that can stop a
94
- gate. The moment a task implies an interface (web / mobile / CLI / TUI), the
95
- WHY→UI→scenario chain runs through `/ux` and its linter, which belongs in the host's
96
- CI so UX drift cannot merge. **Not installed on a UI task? The stage-3 spec gate
97
- stops**offer the install and wait (`references/companion-skills.md`).
80
+ **super-ux — the preferred provider for ANY user-facing task.** The moment a task
81
+ implies an interface (web / mobile / CLI / TUI), the WHY→UI→scenario chain runs
82
+ through `/ux` and its linter, which belongs in the host's CI so UX drift cannot
83
+ merge. **But the stage-3 gate checks the ARTIFACT, not the package**: valid
84
+ scenarios covering the change produced by super-ux, by an alternative provider
85
+ honouring the same contract, or written inline against
86
+ `references/companion-skills.md`'s fallback — pass the gate. What stops the gate
87
+ is the ABSENCE of any scenario artifact: then create one (super-ux is the
88
+ preferred way, the inline fallback is the floor), and a missing tool is reported
89
+ as the NAMED check that was not done, never as a failed task.
98
90
 
99
91
  **The grill is built in and mandatory** (`references/grill.md`). No "clear enough task"
100
92
  exemption and no stage 1 without a committed, operator-confirmed brief. It produces the
@@ -153,7 +145,8 @@ Three things the grill does beyond clarifying the request, each in full in
153
145
  is built in, so this only checks the *optional* companions (super-ux for UI
154
146
  tasks, context7, wiki-update, graphify) and emits ONE block covering them
155
147
  **and the model decision** (`references/model-tiering.md`): recommend
156
- the most capable model available, let the operator confirm or override, record
148
+ the most capable model available (advice), let the operator confirm or
149
+ override (the choice — inherited verbatim by plan, stages and subagents), record
157
150
  it. Ask once, here. **The same block carries the run mode**
158
151
  (`references/continuity.md`): read `pipeline.json` → `run.loop`; where it is
159
152
  recorded, arm it **at the point `run.loop.arm` names** — here at preflight, or
@@ -180,6 +173,15 @@ Three things the grill does beyond clarifying the request, each in full in
180
173
  3. Walk stages 1→10 on the model confirmed at preflight. **Don't re-ask about the
181
174
  model at every boundary** — only when the operator recorded a per-stage override
182
175
  map and the next stage's entry differs (`references/model-tiering.md`).
176
+ **The SELECTED profile is compiled once, at preflight, and only ITS declared
177
+ stages and gates run** (FIX-TP-03.02): the numbers "1→10" name the DEFAULT
178
+ profile, and a custom profile with three stages runs three — no hidden stage
179
+ 0, 7 or 10 is injected because the default profile has one. What a custom
180
+ profile does NOT escape is the KERNEL (03.01): scope, evidence, deps and
181
+ resume are owed by every stage of every profile, so dropping stages never
182
+ drops the evidence gate. And an unknown MANDATORY capability blocks the
183
+ compile — a profile whose `must_understand` names a capability this runtime
184
+ does not have is refused, never run with the capability silently absent.
183
185
  **Is the brief a platform rather than a change?** Then stage 2 also cuts it into
184
186
  modules (`references/decomposition.md`) and stages 3→10 run **per module** in
185
187
  build order, one brick at a time — stages 0–2 run once, and the module map's
@@ -259,4 +261,19 @@ Most references are routed from the **Built-in doctrine** table above, keyed by
259
261
  the stage that sends you there. The rest are routed by prose: `stages.md` (named
260
262
  at every stage of *How to run*), `learned.md` (cited where a rule binds) and
261
263
  `probing.md` (from `gates.md`, whose checks it proves). The config contracts sit
262
- beside this file: `pipeline.schema.json` and `pipeline.example.json`.
264
+ beside this file: `pipeline.schema.json` and `pipeline.example.json`. The
265
+ family's task/context contract sits there too: `execution-packet.schema.json`
266
+ with `execution-packet.example.json` — an immutable, content-addressed packet
267
+ per dispatchable unit of work, validated dependency-free by
268
+ `scripts/packet.py` before anything acts on it (an unknown mandatory version,
269
+ a ref without its digest, or an unbound decision is rejected at the door) —
270
+ and its answer half, `execution-result.schema.json` with
271
+ `execution-result.example.json`: an AttemptGrant that a boolean can never
272
+ substitute for, and a ResultEnvelope whose stale candidate (older revision, or
273
+ a superseded fence) re-plans instead of landing as current
274
+ (`scripts/packet.py validate-result`). The compiler's first stage maps an
275
+ audit report onto parent tasks (`scripts/context_packets.py compile|verify`):
276
+ ids derived from finding ids — never positional, so a shuffled report compiles
277
+ byte-identically — evidence/limits/priority in their own fields separate from
278
+ status, and any row it cannot map blocks the whole compile rather than being
279
+ dropped silently.
@@ -0,0 +1,68 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://raw.githubusercontent.com/ssheleg/task-pipeline/main/plugins/task-pipeline/skills/task-pipeline/execution-attempt.schema.json",
4
+ "title": "task-pipeline execution attempt (grant)",
5
+ "description": "One attempt at running one node — the identity that a claim on a graph node carries, so `next` can be raced by two processes and only one wins. This is the record `graph.py acquire/start/renew/release/recover` reads and writes (the next implementation leaf); this schema is the contract those verbs must round-trip.\n\nThe defect this exists to close (PF-01): the node's `owner` is a ROLE name, not an identity. Two independent `next` runs both saw N-001 `pending`, both dispatched it, and a `running` node with no fenced grant could be left orphaned forever — `next` then exits 4 until a human edits the file. A grant is owned by a SESSION/ATTEMPT, fenced by a monotonic token and a node revision, and expires, so a lost holder is reclaimable and a stale holder's write is rejected by its own fence.\n\nState is `ready` → `claimed`: `ready` is a grant minted but not yet installed on the node; `claimed` is the live hold. There is no third value here — `done`/`blocked`/`parked` are the NODE's states in graph.schema.json, not the attempt's. The record is ISSUED by `scripts/execution_authority.py` (PF-01.02) — a durable single-writer SQLite coordinator whose `BEGIN IMMEDIATE` makes ready→claimed atomic, so two racing `graph.py claim` runs yield one winner; the `fence` here is that coordinator's monotonic lease generation, and `expiry` bounds the run in place of a held OS lock. Local filesystem only; a Fabric adapter replaces the coordinator for distributed execution.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schema_version",
10
+ "node",
11
+ "owner",
12
+ "attempt",
13
+ "revision",
14
+ "fence",
15
+ "expiry",
16
+ "state"
17
+ ],
18
+ "properties": {
19
+ "schema_version": {
20
+ "type": "string",
21
+ "pattern": "^execution-attempt/[0-9]+$",
22
+ "description": "Contract version. A consumer that does not know the major REJECTS the grant."
23
+ },
24
+ "node": {
25
+ "type": "string",
26
+ "pattern": "^N-[0-9]{3,}$",
27
+ "description": "The graph node this attempt claims."
28
+ },
29
+ "owner": {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "description": "The SESSION/ATTEMPT identity that holds the claim — never a role name. Two `next` runs of the same role are two owners; that is the whole point. `graph.schema.json`'s node `owner` stays the ROLE; this is who is actually running it right now."
33
+ },
34
+ "attempt": {
35
+ "type": "integer",
36
+ "minimum": 1,
37
+ "description": "Which attempt on this node this is. A recovered node's next claim increments it, so a retry is distinguishable from the run it replaced."
38
+ },
39
+ "revision": {
40
+ "type": "integer",
41
+ "minimum": 0,
42
+ "description": "The node revision this claim was taken against. `start`/`renew`/`release` must present the revision they read; a write against a stale revision is refused — the compare in compare-and-swap."
43
+ },
44
+ "fence": {
45
+ "type": "integer",
46
+ "minimum": 1,
47
+ "description": "A monotonic fence token, strictly increasing across the node's lifetime. A held-then-lost owner that wakes up and writes carries an OLD fence, and the store rejects it — the guarantee that a zombie cannot clobber the run that reclaimed its node."
48
+ },
49
+ "expiry": {
50
+ "type": "string",
51
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
52
+ "description": "ISO-8601 UTC. Past it, `recover` may reclaim the node for a new attempt. UNKNOWN is not a value — a grant with no expiry is an orphan waiting to happen, so the field is required."
53
+ },
54
+ "state": {
55
+ "enum": [
56
+ "ready",
57
+ "claimed",
58
+ "completed"
59
+ ],
60
+ "description": "`ready` — minted, not yet installed on the node; `claimed` — the live hold. The node's own lifecycle (pending/running/done/blocked/parked) lives in graph.schema.json, not here."
61
+ },
62
+ "installed_at": {
63
+ "type": "string",
64
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
65
+ "description": "When the claim went `claimed`. Optional — a `ready` grant has none yet."
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "schema_version": "execution-packet/1",
3
+ "id": "FIX-EX-01.01",
4
+ "parent_id": "FIX-EX-01",
5
+ "module": "example-module",
6
+ "intent": "Split received from completed in the webhook reference so a crash between them stops losing the event.",
7
+ "inputs": [
8
+ {
9
+ "address": "docs/evidence/audits/example/leaves/FIX-EX-01.01.md",
10
+ "sha256": "9b64e93e16025c61cce840b5facbeed619927a20c07f6f919ac92816d6ddc3b6",
11
+ "role": "primary packet brief"
12
+ }
13
+ ],
14
+ "decision_refs": [
15
+ {
16
+ "id": "DEC-0007",
17
+ "address": "docs/decisions.md#dec-0007",
18
+ "sha256": "276e15892305979ae04a402971c6632a53c249412d99fbea1cf49b4795dbf622"
19
+ }
20
+ ],
21
+ "source_scope": {
22
+ "edit_targets": [
23
+ {
24
+ "address": "plugins/example/skills/example/SKILL.md",
25
+ "mode": "Edit",
26
+ "baseline_sha256": "a0dcc36937f50a8da38261c1c39afe6caeb0f31674cdf3baaac48c4c81defe32"
27
+ },
28
+ {
29
+ "address": "test/audit_regressions/fix-ex-01.01.py",
30
+ "mode": "Create_or_extend"
31
+ }
32
+ ],
33
+ "claim": "FIX-EX-01.01"
34
+ },
35
+ "budgets": {
36
+ "context_bytes": 24576,
37
+ "token_note": "estimate: utf8 bytes / 3.9 chars-per-token (the family's measured divisor)"
38
+ },
39
+ "acceptance": [
40
+ "A crash after the receipt admits a repeat worker; a duplicate of a completed event never grants again."
41
+ ]
42
+ }