task-pipeline-skill 1.91.2 → 1.93.2
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 +168 -0
- package/CONTRIBUTING.md +12 -6
- package/HOW-IT-WORKS.md +9 -4
- package/README.md +32 -4
- package/SKILL-CARD.md +1 -1
- package/cursor/rules/task-pipeline.mdc +11 -2
- package/evals/RESULTS.md +1 -1
- package/evals/task-pipeline.evals.json +16 -1
- package/package.json +3 -3
- package/plugins/task-pipeline/.claude-plugin/plugin.json +2 -2
- package/plugins/task-pipeline/commands/task-pipeline.md +23 -8
- package/plugins/task-pipeline/hooks/hooks.json +11 -0
- package/plugins/task-pipeline/hooks/memory-nudge.sh +49 -0
- package/plugins/task-pipeline/skills/evidence-docs/references/hooks.md +3 -1
- package/plugins/task-pipeline/skills/project-audit/SKILL.md +2 -1
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +10 -20
- package/plugins/task-pipeline/skills/task-pipeline/execution-packet.example.json +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/execution-packet.schema.json +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/graph.schema.json +8 -2
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.example.json +2 -1
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +7 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +4 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/brainstorm.md +6 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/build.md +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/continuity.md +20 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/decomposition.md +4 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/deploy-targets.md +31 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/doctrine-map.md +1 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/grill.md +14 -5
- package/plugins/task-pipeline/skills/task-pipeline/references/hooks.md +3 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +1 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/planning.md +8 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +1 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +15 -7
- package/plugins/task-pipeline/skills/task-pipeline/references/waves.md +233 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/work-graph.md +3 -1
- package/plugins/task-pipeline/skills/task-pipeline/scripts/context_packets.py +8 -2
- package/plugins/task-pipeline/skills/task-pipeline/scripts/graph.py +89 -5
- package/plugins/task-pipeline/skills/task-pipeline/scripts/packet.py +4 -2
- package/plugins/task-pipeline/skills/task-pipeline/scripts/plan_audit.py +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/scripts/stage_checkpoint.py +68 -1
- package/plugins/task-pipeline/skills/task-pipeline/templates/run.md +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-pipeline
|
|
3
|
-
description: "Use when work changes the repository — feature, fix, bug, refactor, migration, integration, rewrite, adoption or hardening; фича, фикс, баг, рефактор, миграция, интеграция, доработать, починить, внедрить, перевести — or
|
|
3
|
+
description: "Use when work changes the repository — feature, fix, bug, refactor, migration, integration, rewrite, adoption or hardening; фича, фикс, баг, рефактор, миграция, интеграция, доработать, починить, внедрить, перевести — or a finding that lands in it: audit/аудит, bug hunt/проверь ошибки, production check/проверь прод, PR review/ревью PR — or on 'run this through the pipeline' / 'прогони по конвейеру', 'the full cycle' / 'полный цикл', /task-pipeline. Runs a substantial task through gated stages: intake grill, docs, brainstorm, spec, plan, build, tests, deploy, post-deploy, docs/wiki, acceptance. 'waves' / 'волнами' closes the whole board; 'checkup' / 'чекап' lists unconfirmed releases; 'setup' audits docs. Not for: answering a question, explaining code, a typo, a one-line edit, a mechanical rename, reconnaissance that lands nothing — say 'no pipeline' / 'без пайплайна' to opt out."
|
|
4
4
|
license: MIT
|
|
5
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."
|
|
6
6
|
---
|
|
@@ -17,8 +17,8 @@ GAP CHECK before it is an interview: the brief is built from the request, the
|
|
|
17
17
|
files and the harvest first, and a question is asked only for a **material
|
|
18
18
|
unknown** the sources cannot answer. A complete brief yields ZERO intake
|
|
19
19
|
questions; what the request or the project already decided is recorded, never
|
|
20
|
-
re-negotiated. The interview, where gaps remain, is
|
|
21
|
-
sweeps stages 1→10 for anything that would stop the run later — then locks the
|
|
20
|
+
re-negotiated. The interview, where gaps remain, is ONE batch ordered by dependency
|
|
21
|
+
and sweeps stages 1→10 for anything that would stop the run later — then locks the
|
|
22
22
|
answers into a brief. Autonomy is bought there or not at all; every MATERIAL
|
|
23
23
|
question skipped at stage 0 comes back as an interruption at stage 6.
|
|
24
24
|
|
|
@@ -66,16 +66,7 @@ gate stops until it is installed.
|
|
|
66
66
|
Which reference owns which stage — all forty-odd of them, by stage number:
|
|
67
67
|
[`references/doctrine-map.md`](./references/doctrine-map.md).
|
|
68
68
|
|
|
69
|
-
**
|
|
70
|
-
onto stages 2/4/5/6 in `pipeline.json` → `skills[]`. That is a **substitution, never a
|
|
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.
|
|
69
|
+
**Precedence:** on a CUSTOM profile the **kernel wins** — scope, evidence, deps and resume are owed by every unit of work; `references/stages.md` is the **default profile's** normative gate set; the kernel is normative for all. Another skill set on stages 2/4/5/6: `references/companion-skills.md`.
|
|
79
70
|
|
|
80
71
|
**super-ux — the preferred provider for ANY user-facing task.** The moment a task
|
|
81
72
|
implies an interface (web / mobile / CLI / TUI), the WHY→UI→scenario chain runs
|
|
@@ -176,15 +167,16 @@ Three things the grill does beyond clarifying the request, each in full in
|
|
|
176
167
|
stages and gates run** (FIX-TP-03.02): the numbers "1→10" name the DEFAULT
|
|
177
168
|
profile, and a custom profile with three stages runs three — no hidden stage
|
|
178
169
|
0, 7 or 10 is injected because the default profile has one. What a custom
|
|
179
|
-
profile does NOT escape is the KERNEL (03.01):
|
|
180
|
-
|
|
181
|
-
drops the evidence gate. And an unknown MANDATORY capability blocks the
|
|
170
|
+
profile does NOT escape is the KERNEL (03.01): dropping stages never drops
|
|
171
|
+
the evidence gate. And an unknown MANDATORY capability blocks the
|
|
182
172
|
compile — a profile whose `must_understand` names a capability this runtime
|
|
183
173
|
does not have is refused, never run with the capability silently absent.
|
|
184
174
|
**Is the brief a platform rather than a change?** Then stage 2 also cuts it into
|
|
185
175
|
modules (`references/decomposition.md`) and stages 3→10 run **per module** in
|
|
186
176
|
build order, one brick at a time — stages 0–2 run once, and the module map's
|
|
187
177
|
status column is the resume point (`references/stages.md` → *The program loop*).
|
|
178
|
+
**The whole board?** `/task-pipeline waves` (`references/waves.md`): stages
|
|
179
|
+
0–4 once, 5–8 per wave, 9–10 to close.
|
|
188
180
|
4. Do **not** advance until the stage **gate** passes (`references/stages.md`).
|
|
189
181
|
Honor the gate **type**: for `auto`, verify the gate's `check` yourself and
|
|
190
182
|
stop/return on fail; for `judgment`, record the named judge's ruling as
|
|
@@ -272,7 +264,5 @@ substitute for, and a ResultEnvelope whose stale candidate (older revision, or
|
|
|
272
264
|
a superseded fence) re-plans instead of landing as current
|
|
273
265
|
(`scripts/packet.py validate-result`). The compiler's first stage maps an
|
|
274
266
|
audit report onto parent tasks (`scripts/context_packets.py compile|verify`):
|
|
275
|
-
ids derived from finding ids
|
|
276
|
-
|
|
277
|
-
status, and any row it cannot map blocks the whole compile rather than being
|
|
278
|
-
dropped silently.
|
|
267
|
+
ids derived from finding ids, never positional; evidence, limits and priority
|
|
268
|
+
kept apart from status; and any row it cannot map blocks the compile.
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"properties": {
|
|
19
19
|
"schema_version": {
|
|
20
20
|
"type": "string",
|
|
21
|
-
"pattern": "^execution-packet/[0-9]+$",
|
|
22
|
-
"description": "Contract version, `execution-packet/<major
|
|
21
|
+
"pattern": "^(task-pipeline/)?execution-packet/[0-9]+$",
|
|
22
|
+
"description": "Contract version, `task-pipeline/execution-packet/<major>` (namespaced since 1.93.0 so Fabric's former packet id cannot be mistaken for it; the bare `execution-packet/<major>` is still read until live packets are migrated, backlog B-135). A consumer that does not know the major REJECTS the packet — an unknown mandatory version is not a warning."
|
|
23
23
|
},
|
|
24
24
|
"id": {
|
|
25
25
|
"type": "string",
|
|
@@ -205,6 +205,11 @@
|
|
|
205
205
|
],
|
|
206
206
|
"description": "The class of the user-facing surface this node builds, copied from the brief's `surface_class` (stage 0). It selects the gate profile, and `graph.py certify` reads it: on `flagship` or `product` the fourth, `visual` tier report is REQUIRED, because none of unit, seam or product opens the contact sheet; on any other class a `visual` report is accepted when given. Absent on a node that builds no user-facing surface. `references/certification.md` → *The fourth reading*."
|
|
207
207
|
},
|
|
208
|
+
"wave": {
|
|
209
|
+
"type": "integer",
|
|
210
|
+
"minimum": 1,
|
|
211
|
+
"description": "Wave mode only (`references/waves.md`): the pass of stages 5–8 that closes this node, from 1, where wave 1 is the walking skeleton. `graph.py validate` refuses an edge from a later wave's node into an earlier wave's node, because an earlier wave waiting on a later one cannot close in its own pass; `graph.py next --wave N` prints that wave's frontier only; `graph.py wave` moves a node and records the re-cut as a revision. Absent outside wave mode."
|
|
212
|
+
},
|
|
208
213
|
"certification": {
|
|
209
214
|
"type": "object",
|
|
210
215
|
"description": "What the tiered certification recorded for this node. Written by `graph.py certify` on every round, pass or fail: a failing round that wrote nothing would erase the only evidence that a node is churning, which is the number the loop-guard ceiling reads.",
|
|
@@ -444,9 +449,10 @@
|
|
|
444
449
|
"park",
|
|
445
450
|
"close",
|
|
446
451
|
"invalidate",
|
|
447
|
-
"waive"
|
|
452
|
+
"waive",
|
|
453
|
+
"wave"
|
|
448
454
|
],
|
|
449
|
-
"description": "Which mutation made this entry. `close` joined the two on 2026-08-17 with T-5 — and it was caught by a probe rather than by the fixture asserting *the graph after a close still validates*, because `violations()` never reaches an enum. The same disagreement B-084 records, one field over. `invalidate` joined with PF-02.02: a REQ/interface/brief change supersedes a node and resets its downstream proofs."
|
|
455
|
+
"description": "Which mutation made this entry. `close` joined the two on 2026-08-17 with T-5 — and it was caught by a probe rather than by the fixture asserting *the graph after a close still validates*, because `violations()` never reaches an enum. The same disagreement B-084 records, one field over. `invalidate` joined with PF-02.02: a REQ/interface/brief change supersedes a node and resets its downstream proofs. `wave` joined with wave mode: the re-cut after every wave moves nodes between waves, and a move nobody recorded is the quiet re-plan `references/planning.md` refuses."
|
|
450
456
|
},
|
|
451
457
|
"node": {
|
|
452
458
|
"type": "string",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"gate": {
|
|
20
20
|
"type": "manual",
|
|
21
|
-
"check": "MANDATORY stage — never skipped (only sanctioned bypass: the entry-from-super-ux short-circuit). PHASE 1, before the first question: harvest the knowledge sources (references/knowledge-sources.md) — code, THE CODE GRAPH when one is built (references/knowledge-graph.md: graphify query/affected/god-nodes answer reach, which grep cannot; detect graphify-out/graph.json — recommended, never required), CLAUDE.md/AGENTS.md, CONTEXT.md + docs/adr, docs/ + docs/ux, past pipeline briefs and carry-over ledgers, THE RETRO'S STANDING INSTRUCTIONS (docs/evidence/retro.md — read IN FULL, not queried: they are capped at ten and they BIND this run; stamp each one the moment it fires, since that date is the only evidence behind stage 10's cold-retirement rule — references/retrospective.md), the knowledge wiki when installed (obsidian-wiki — recommended, never required; detect ~/.obsidian-wiki/config), and any other repo or hosted doc system the project names as its docs — queried by this task's own terms, with the SOURCE LEDGER written into the brief (a row per source consulted, or an explicit 'none found'; THE GRAPH'S ROW CARRIES ITS MEASURED LAG — commits and days behind HEAD, the signal it was measured with (built_at_commit exact / mtime approximate / unresolvable), and the marker '⚠ not trusted for reach until refreshed' — that exact string, so one marker is greppable across every ledger — on anything but current. A bare build date does NOT satisfy this: it is the graph's own reply about itself, true and self-reported and silent about whether the graph describes the tree this run is about to change — references/knowledge-graph.md -> Measure the lag, and references/gates.md -> False success for the class). PHASE 2, the grill, built into the skill (references/grill.md) — no companion to install. Per its contract:
|
|
21
|
+
"check": "MANDATORY stage — never skipped (only sanctioned bypass: the entry-from-super-ux short-circuit). PHASE 1, before the first question: harvest the knowledge sources (references/knowledge-sources.md) — code, THE CODE GRAPH when one is built (references/knowledge-graph.md: graphify query/affected/god-nodes answer reach, which grep cannot; detect graphify-out/graph.json — recommended, never required), CLAUDE.md/AGENTS.md, CONTEXT.md + docs/adr, docs/ + docs/ux, past pipeline briefs and carry-over ledgers, THE RETRO'S STANDING INSTRUCTIONS (docs/evidence/retro.md — read IN FULL, not queried: they are capped at ten and they BIND this run; stamp each one the moment it fires, since that date is the only evidence behind stage 10's cold-retirement rule — references/retrospective.md), the knowledge wiki when installed (obsidian-wiki — recommended, never required; detect ~/.obsidian-wiki/config), and any other repo or hosted doc system the project names as its docs — queried by this task's own terms, with the SOURCE LEDGER written into the brief (a row per source consulted, or an explicit 'none found'; THE GRAPH'S ROW CARRIES ITS MEASURED LAG — commits and days behind HEAD, the signal it was measured with (built_at_commit exact / mtime approximate / unresolvable), and the marker '⚠ not trusted for reach until refreshed' — that exact string, so one marker is greppable across every ledger — on anything but current. A bare build date does NOT satisfy this: it is the graph's own reply about itself, true and self-reported and silent about whether the graph describes the tree this run is about to change — references/knowledge-graph.md -> Measure the lag, and references/gates.md -> False success for the class). PHASE 2, the grill, built into the skill (references/grill.md) — no companion to install. Per its contract: close what the code/docs answer first, then ONE batch of the material unknowns ordered by dependency, a recommended answer with each (one at a time only where answers depend on each other or the operator asks), contradictions reconciled; EVERY answer that touches a harvested source is validated against that source — the operator outranks any document, but only out loud, and the losing side is logged for the stage-9 doc update; domain awareness applied (terms challenged against CONTEXT.md, ADRs recorded for hard-to-reverse calls). The autonomy sweep is covered — every stage 1-10 has its blockers pre-resolved (docs sources, branch/tracker policy, test + lint commands, deploy target and authorization, log/health locations, docs+wiki targets, and for UI tasks the design surface: Figma on or text-only, is the Figma MCP connected, and if it is not — ship text-only or stop and connect it, since the UX chain degrades on its own and never blocks; plus, with Figma on, the DESIGN DESTINATION — which team/org by name and which file per surface, App / Web / ASO (the recorded one, a URL the operator gives, or creation in that named team with the creation explicitly authorized), written into the project's canonical record before the first frame, and never created while a recorded file resolves — an unreachable recorded file means stop and ask, never make a replacement) or is explicitly marked 'stop and ask here'. UI verdict recorded (arms super-ux), and for a user-facing task its SURFACE CLASS — surface_class: flagship | product | internal | ad — which selects the visual gate profile for stages 3, 6 and 10 (references/stages.md -> The surface class); model decision recorded. All of it locked into a committed task brief the operator confirms before stage 1. The REQ table is written — one row per independently verifiable deliverable, each naming how it is verified — and frozen: adding later is free, removing or narrowing needs the operator's explicit agreement. The carry-over ledger is seeded. PHASE 1b, THE DOCUMENTATION INVENTORY (references/documentation.md): four questions answered into docs/DOCMAP.md before the interview — where settled things live (the DECISION HOME, and there is exactly one per project: an existing docs/adr/ IS the register and is recorded as such, never duplicated), what each fact's single home is, what a change of type X obliges (THE PROPAGATION MATRIX, non-empty, every row naming the check that enforces it or the word 'review' with a one-line reason), and what proves it (the gate command). A project with no answers gets them seeded — registers, matrix and scripts/check-docs.sh from the skill's templates — and the seeding is recorded as the register's first entry; the seeded gate must exit 0 on its own seeds, because a project that starts red teaches everyone on day one that the gate is noise. The regime is recorded. PHASE 1c, RECONCILE: git says how it should be, the run record says how it turned out — read both for the area about to be touched and resolve every divergence (the document is stale, the record is wrong, or they genuinely disagree and that is a decision), because starting on an unresolved divergence means building against a system that does not exist. The retro's in-force sections are read IN FULL and its archive is QUERIED by the task's nouns."
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
{
|
|
@@ -183,6 +183,7 @@
|
|
|
183
183
|
"release": {
|
|
184
184
|
"enabled": true,
|
|
185
185
|
"trigger": "tag",
|
|
186
|
+
"approval": "checks",
|
|
186
187
|
"steps": [
|
|
187
188
|
"create a GitHub release from the matching CHANGELOG section",
|
|
188
189
|
"npm publish (task-pipeline-skill) — a second job in the same workflow, armed per repository by the PUBLISH_NPMJS variable (NPM_TOKEN granular automation token, or trusted publishing via OIDC); unarmed it falls back to a human 2FA step"
|
|
@@ -204,6 +204,13 @@
|
|
|
204
204
|
"_goal_note": {
|
|
205
205
|
"type": "string",
|
|
206
206
|
"description": "Free prose beside `goal`."
|
|
207
|
+
},
|
|
208
|
+
"approval": {
|
|
209
|
+
"enum": [
|
|
210
|
+
"checks",
|
|
211
|
+
"reviewers"
|
|
212
|
+
],
|
|
213
|
+
"description": "Who admits a release: `checks` — a guard (tag on main, CI green on that commit) and no reviewers, so the run tags, watches and reports; `reviewers` — an environment with required reviewers, so the run reports the direct link to the run that is actually `waiting`. Absent: read the organisation's declaration or the environment's protection rules; never assume `checks` (references/deploy-targets.md)."
|
|
207
214
|
}
|
|
208
215
|
}
|
|
209
216
|
},
|
|
@@ -33,6 +33,8 @@ docs/
|
|
|
33
33
|
YYYY-MM-DD-<topic>-brief.md # stage 0 — locked intake brief (grill output)
|
|
34
34
|
YYYY-MM-DD-<topic>-carryover.md # stage 0 seeds it; EVERY stage appends; stage 10 reads it
|
|
35
35
|
YYYY-MM-DD-<topic>-modules.md # stage 2 — module map + build order (platforms only)
|
|
36
|
+
YYYY-MM-DD-<topic>-inventory.json # wave mode, stage 0 — every open item by id, verified
|
|
37
|
+
YYYY-MM-DD-<topic>-canvas.md # wave mode, stages 2–3 — the target state over the current logic
|
|
36
38
|
YYYY-MM-DD-<topic>-design.md # stage 3 — the spec / module dossier (locks shared contracts)
|
|
37
39
|
YYYY-MM-DD-<topic>-acceptance.md # stage 10 — REQ coverage table + evidence
|
|
38
40
|
plans/
|
|
@@ -170,6 +172,8 @@ them is a finding, not a tie-break ([`knowledge-sources.md`](knowledge-sources.m
|
|
|
170
172
|
| 10 Board resolution | `<artifacts>/backlog.md` — every unresolved ledger row — homed `backlog` or still `open` — arrives with a real id, and the ledger row is updated to name it; priority re-derived ([`backlog.md`](backlog.md)) | the next run's harvest, and every loop iteration |
|
|
171
173
|
| 10 Retro rotation | `<artifacts>/retro/YYYY-QN.md` — entries older than five stamps, plus every retirement, each with its commit | queried by a later run's harvest |
|
|
172
174
|
| 2 Decompose | `specs/<topic>-modules.md` — module map, build order, contracts, per-module status (platforms only) | stages 3–10, every module's run |
|
|
175
|
+
| 0 Wave mode | `specs/<topic>-inventory.json` — every open item: id, source, status, area, node, wave, release ([`waves.md`](waves.md)) | stages 2–10, every wave's re-measure |
|
|
176
|
+
| 2–3 Wave mode | `specs/<topic>-canvas.md` — as-is → to-be per module and contract, the seams, REQ → module → wave, what is deleted | every wave, and each re-cut |
|
|
173
177
|
| 3 Spec | `specs/<topic>-design.md` — module dossier for a decomposed platform (+ links `docs/ux/*` for UI) | stage 4 |
|
|
174
178
|
| 4 Plan | `plans/<topic>.md` | stage 5 |
|
|
175
179
|
| 3 UX track | `docs/ux/{foundation,flows,screens,scenarios}.md` | stages 4–9 + `/ux-lint` |
|
|
@@ -56,9 +56,12 @@ not a question to re-open from scratch.
|
|
|
56
56
|
the platform's shape — the pieces, how they relate, what order they land in —
|
|
57
57
|
not the details of one corner; those belong to each module's own stage-3
|
|
58
58
|
dossier. Don't refine something that needs splitting first.
|
|
59
|
-
3. **Questions one
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
3. **Questions in one batch, after the sources.** What the brief, the code and the
|
|
60
|
+
recorded decisions cannot answer goes in one message, ordered by dependency, each
|
|
61
|
+
with a recommendation; one at a time only where an answer reshapes the next
|
|
62
|
+
question or the operator asks ([`grill.md`](grill.md)). Multiple choice where it
|
|
63
|
+
fits, open where it doesn't. Purpose, constraints, success criteria — anything the
|
|
64
|
+
brief left at design level.
|
|
62
65
|
4. **Propose 2–3 approaches with trade-offs**, lead with your recommendation and
|
|
63
66
|
the reason for it. **YAGNI ruthlessly** — strip anything the task doesn't need
|
|
64
67
|
from every option before presenting.
|
|
@@ -610,9 +610,9 @@ merge.
|
|
|
610
610
|
|
|
611
611
|
If it returns findings, dispatch **ONE** fix subagent with the complete list — not
|
|
612
612
|
one fixer per finding; per-finding fixers each rebuild context and re-run suites.
|
|
613
|
-
Then exactly **one** scoped re-review of the fix
|
|
613
|
+
Then exactly **one** scoped re-review of the fix round. Adjudicate residuals as in
|
|
614
614
|
the breaker: park with rulings, or stop on load-bearing ones. There is no second
|
|
615
|
-
fix
|
|
615
|
+
fix round.
|
|
616
616
|
|
|
617
617
|
## 6. Integrate, then finish
|
|
618
618
|
|
|
@@ -47,13 +47,21 @@ This spans the whole run, not one stage:
|
|
|
47
47
|
|
|
48
48
|
- the plan's tasks at stage 5;
|
|
49
49
|
- the boundary between stages whose gate is `auto`;
|
|
50
|
-
- the per-module program loop when the brief was a platform
|
|
50
|
+
- the per-module program loop when the brief was a platform, and the waves when
|
|
51
|
+
the request was the whole board ([`waves.md`](waves.md));
|
|
51
52
|
- the acceptance → retro tail, which is where runs most often stall one step from
|
|
52
53
|
finished.
|
|
53
54
|
|
|
54
55
|
It stops for exactly four things: a `manual` gate, a block it cannot resolve, a
|
|
55
56
|
genuine ambiguity the brief does not answer, and completion.
|
|
56
57
|
|
|
58
|
+
**A block or an ambiguity stops its node, not the run.** The node is parked with the
|
|
59
|
+
question as its reason, marked `needs-operator` and answerable without context
|
|
60
|
+
([`prioritisation.md`](prioritisation.md) → *5. Where the human goes*), and the run
|
|
61
|
+
continues on every node it does not block. The run itself stops only when the whole
|
|
62
|
+
frontier is blocked — `graph.py next` exits `4` — and the questions are then asked
|
|
63
|
+
together. **When the board is empty, say so once**, and do not invent work to fill it.
|
|
64
|
+
|
|
57
65
|
**This extends [`build.md`](build.md); it does not replace it.** That file's
|
|
58
66
|
*Continuous execution* rule governs the inside of a stage-5 execution — do not
|
|
59
67
|
check in between the tasks of a plan you were told to execute. It is unconditional
|
|
@@ -122,7 +130,9 @@ So at the bottom of an iteration, beside the re-derived `prio`:
|
|
|
122
130
|
2. state whether the next item still serves it;
|
|
123
131
|
3. if it does not, **re-order or re-scope the queue and say what moved and why.** A row
|
|
124
132
|
that stops serving the goal leaves for the board with its reason
|
|
125
|
-
([`backlog.md`](backlog.md)), it does not get worked because it was next.
|
|
133
|
+
([`backlog.md`](backlog.md)), it does not get worked because it was next. On a work
|
|
134
|
+
graph the move is a committed `revisions` entry — `park`, `add`, or `wave` between
|
|
135
|
+
waves — never an untracked edit.
|
|
126
136
|
|
|
127
137
|
A queue re-derived only by `age` and `sev` is a queue that is honest about priority and
|
|
128
138
|
silent about purpose. Both numbers can be right while the run is finishing something the
|
|
@@ -308,6 +318,12 @@ right costs nothing extra and pays twice.
|
|
|
308
318
|
|
|
309
319
|
## Part 3 — workflow memory at the stage boundary
|
|
310
320
|
|
|
321
|
+
Which of the five handoff mechanisms carries what — the Git record, Observatory's lease
|
|
322
|
+
and checkpoint, a host's launch context, the inbound queue — and the order a successor
|
|
323
|
+
reads them in, has one home:
|
|
324
|
+
[sshlg-skills `docs/working-rules/handoff-layers.md`](https://github.com/ssheleg/sshlg-skills/blob/main/docs/working-rules/handoff-layers.md).
|
|
325
|
+
This part is the checkpoint and lease half of it.
|
|
326
|
+
|
|
311
327
|
The ledger survives a compaction. It does not survive a quota that ran out on another
|
|
312
328
|
account, or a run picked up by a different agent on another machine. When the host has
|
|
313
329
|
Project Observatory's memory tools, **every gate that returns also writes a workflow
|
|
@@ -318,6 +334,8 @@ checkpoint**, and the next executor continues from the last finished stage.
|
|
|
318
334
|
- **The constraints.** Give the brief's restrictive rules once, as `--constraint`. They are carried to every later boundary, and a successor reads them first.
|
|
319
335
|
- **Keys.** Pass keys by name, as `--credential PROJECT/ENV/NAME`, never as a value.
|
|
320
336
|
- **Without the tools.** `stage_checkpoint.py record --unavailable "<why>"` appends one `event: memory — unavailable` line, and the run continues exactly as before. Missing memory is a state the ledger names, not a failure.
|
|
337
|
+
- **A planned change of executor** — a quota running out, a route moving the work to another model or account. `stage_checkpoint.py handoff --to-provider <p> [--to-model <m>] --reason limit|plan_route|operator` prints `observatory_handoff_create`'s arguments; `record --answer -` keeps the offer as one ledger line, and the lease stays with this run until the successor accepts. The successor runs `stage_checkpoint.py accept --handoff-id <id>` → `observatory_handoff_accept` → `record --answer -` **before its first write**, and obeys the constraints the answer carries first. `LeaseLost` is then left for the race nobody planned.
|
|
338
|
+
- **The reminder.** `hooks/memory-nudge.sh` (PostToolUse) reads the ledger after each tool call and, once per `stage:` line with no `event: memory` line after it, puts one sentence in front of the model naming the two commands above. It decides nothing and blocks nothing; adoption measured before it was one write in 293 sessions.
|
|
321
339
|
- **A refusal.** `LeaseLost` means another executor holds the workflow now. The script drops the token. Read the workflow (`observatory_checkpoint_latest` with `stage_checkpoint.py state`'s id) before doing anything else. A stale writer stops after one refusal.
|
|
322
340
|
- **The lease token.** It lives in `.task-pipeline/memory.json` (mode 0600, git-ignored) and never in the ledger, a reply or a commit.
|
|
323
341
|
- **What this is not.** Not a second ledger and not the narrative. The checkpoint is the work's state for the next executor. The wiki and the ledger keep everything else.
|
|
@@ -137,6 +137,10 @@ Rules for the loop:
|
|
|
137
137
|
lands, or build several and deploy once. Record it; don't decide it per module.
|
|
138
138
|
- **Update the map's status column as each module closes**, in the same commit as
|
|
139
139
|
that module's acceptance. The map is the resume point after a lost context.
|
|
140
|
+
- **The whole board is waves, not bricks** ([`waves.md`](waves.md)). When the request
|
|
141
|
+
is every open item rather than one platform, stages 0–2 still run once, the map
|
|
142
|
+
becomes the canvas, and the loop runs **one wave at a time**. A wave may hold several
|
|
143
|
+
bricks or nodes, provided they close together in one pass.
|
|
140
144
|
- **Loop discipline:** a module re-entering the same stage a third time trips the
|
|
141
145
|
loop guard ([`loop-guard.md`](loop-guard.md)) — stop, name the oscillation, and
|
|
142
146
|
fix the layer that owns it instead of iterating.
|
|
@@ -163,6 +163,37 @@ gh run view <run-id> --log-failed # only the failed step's log
|
|
|
163
163
|
or failed deploy is the most common way a run reports success while nothing
|
|
164
164
|
shipped — and it is exactly what the stage-8 gate is for.
|
|
165
165
|
|
|
166
|
+
### When the release waits for an approval
|
|
167
|
+
|
|
168
|
+
**Read the project's approval mode before tagging, and do not guess it.** It is one of
|
|
169
|
+
two, and each owes the operator something different.
|
|
170
|
+
|
|
171
|
+
- **`checks`** — a guard admits the release, with no person on the path. For example,
|
|
172
|
+
`release-guard` checks that the tag is on main and that CI on that commit is green,
|
|
173
|
+
and the `release` environment has no reviewers. PassionCode products declare this in
|
|
174
|
+
`passioncode-ai/.github` `release-signing/products.json` (`"approval": "checks"`).
|
|
175
|
+
Push the tag, watch the run selected **by the tag you pushed**, and report what was
|
|
176
|
+
published, or the guard's refusal and its cause. A refusal is fixed at its cause,
|
|
177
|
+
never worked around. Send no approval request: there is nobody to send it to.
|
|
178
|
+
- **`reviewers`** — the run stops at an environment with required reviewers. Find that
|
|
179
|
+
run by the tag, and confirm its status is `waiting` before saying anything:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
gh run list -w release.yml --json url,status,headBranch -L 5
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Then hand the operator the **direct link** to that run, where they press *Review
|
|
186
|
+
deployments*, together with the tag and the jobs that are waiting. A request without
|
|
187
|
+
the link is incomplete, and so is a link to a run that is not waiting.
|
|
188
|
+
|
|
189
|
+
The mode comes from, in order:
|
|
190
|
+
1. `pipeline.json` → `release.approval`;
|
|
191
|
+
2. an organisation declaration such as the file above;
|
|
192
|
+
3. the environment's own protection rules
|
|
193
|
+
(`gh api repos/<owner>/<repo>/environments/release`).
|
|
194
|
+
|
|
195
|
+
A run that cannot establish the mode says so. It does not assume `checks`.
|
|
196
|
+
|
|
166
197
|
## Other platforms, quick verbs
|
|
167
198
|
|
|
168
199
|
| Platform | Deploy | Verify |
|
|
@@ -27,6 +27,7 @@ UX track on a user-facing task.
|
|
|
27
27
|
| 0 Intake grill | `references/grill.md` |
|
|
28
28
|
| 2 Brainstorm | `references/brainstorm.md` |
|
|
29
29
|
| 2 Decompose (platforms only) | `references/decomposition.md` |
|
|
30
|
+
| 0–10 · **wave mode** — the whole board: 0–4 once, 5–8 per wave, 9–10 to close | `references/waves.md` |
|
|
30
31
|
| 3 Spec | `references/spec.md` |
|
|
31
32
|
| 4 Plan | `references/planning.md` |
|
|
32
33
|
| the queue the loop walks | `references/work-graph.md` |
|
|
@@ -63,16 +63,25 @@ not depend on it.
|
|
|
63
63
|
|
|
64
64
|
Where material unknowns remain, interview the operator about THOSE until you
|
|
65
65
|
reach a **shared understanding**. Walk down each unresolved branch of the
|
|
66
|
-
decision tree, resolving dependencies between decisions
|
|
67
|
-
|
|
68
|
-
1. **
|
|
66
|
+
decision tree, resolving dependencies between decisions in order.
|
|
67
|
+
|
|
68
|
+
1. **Close from the sources first, then ask ONE batch.** Every material unknown
|
|
69
|
+
the harvest, the code and the recorded decisions leave open goes into one
|
|
70
|
+
message, ordered by dependency, each with a recommended answer and what each
|
|
71
|
+
answer changes. **One question at a time only when the answers depend on each
|
|
72
|
+
other** — the next question cannot be written until this one is answered, and
|
|
73
|
+
then you go depth-first — **or when the operator asks for it.** Decided by the
|
|
74
|
+
operator on 2026-10-11: a question asked alone costs a human round, and a batch
|
|
75
|
+
costs one. [`prioritisation.md`](prioritisation.md) → *5. Where the human goes*
|
|
76
|
+
says the same about the rest of the run.
|
|
69
77
|
2. **Recommend an answer with every question** (+ a one-line rationale). "What do
|
|
70
78
|
you think?" is lazy — you have the codebase in front of you, they don't.
|
|
71
79
|
3. **If the codebase can answer it, go read the codebase.** Spending the
|
|
72
80
|
operator's turn on something `grep`/`Read`/context7 would have told you is the
|
|
73
81
|
most common way to waste a grill.
|
|
74
|
-
4. **
|
|
75
|
-
|
|
82
|
+
4. **Prerequisites first.** Order the batch so prerequisite decisions come before
|
|
83
|
+
the ones they shape; where an answer can invalidate a later question, ask the
|
|
84
|
+
prerequisite alone and go depth-first.
|
|
76
85
|
5. **Reconcile contradictions immediately**, and chase dodges: "we'll decide
|
|
77
86
|
later" → "what's the latest you can decide and still ship?"
|
|
78
87
|
6. **Cover the autonomy sweep** (below). An unasked MATERIAL question is not
|
|
@@ -218,7 +218,9 @@ Since v1.50.0 the plugin carries hooks of its own. `hooks/release-gate.sh`
|
|
|
218
218
|
(`PreToolUse` on `Bash`) refuses an **outward, irreversible act** — `git tag`, a
|
|
219
219
|
tag push, `gh release create`, `npm publish` — while the run says the suite has not
|
|
220
220
|
passed. `hooks/gate-observer.sh` (`PostToolUse` and `PostToolUseFailure`) records
|
|
221
|
-
what the declared gate command actually did.
|
|
221
|
+
what the declared gate command actually did. `hooks/memory-nudge.sh` (`PostToolUse` on `Bash|Edit|Write|MultiEdit`) reminds,
|
|
222
|
+
once per returned gate, that no workflow-memory line follows it
|
|
223
|
+
([`continuity.md`](continuity.md), Part 3).
|
|
222
224
|
|
|
223
225
|
**Two lessons from v1.50.0, both shipped as defects and both fixed in v1.51.0.**
|
|
224
226
|
|
|
@@ -42,6 +42,7 @@ makes the grill's answers *checkable* instead of merely confident.
|
|
|
42
42
|
|
|
43
43
|
| # | Source | How to find it | What it's good for |
|
|
44
44
|
|---|---|---|---|
|
|
45
|
+
| 0 | **A host's launch context** | a session started by Fabric or Fabric Dashboards (`session-handoff/1`): the brief arrives appended to the system prompt, the task as the first prompt, and `context.md` is the cited context pack | the request in the words the operator gave the host — taken as the request, not re-asked; the context pack is a harvest source like any other and is cited by its section |
|
|
45
46
|
| 1 | **The code** | the repo you're in | what actually runs — the tiebreaker |
|
|
46
47
|
| 2 | **The code graph** | `graphify-out/graph.json` — see below | *reach*: what calls this, what breaks if it moves, what every change passes through |
|
|
47
48
|
| 3 | **Host agent docs** | `CLAUDE.md`, `AGENTS.md`, `.cursor/rules/` | conventions, commands, deploy path, house rules |
|
|
@@ -112,6 +112,14 @@ which grows but never reorders a stage. Discovery that lands in a committed
|
|
|
112
112
|
artifact is not a dynamic graph; discovery that changes what runs next, silently,
|
|
113
113
|
is.
|
|
114
114
|
|
|
115
|
+
**Wave mode's re-cut is the same kind of discovery** ([`waves.md`](waves.md)). After
|
|
116
|
+
each wave the remaining waves are re-cut from the re-measured inventory, and every move
|
|
117
|
+
lands twice in committed form: a `revisions` entry in the work graph (`graph.py wave`,
|
|
118
|
+
which refuses a move that breaks the wave order) and the canvas edit that says why. The
|
|
119
|
+
stage list does not change and no stage is invented; what changes is which nodes the
|
|
120
|
+
next pass of stages 5–8 takes, and that is written down before the pass begins. So the
|
|
121
|
+
static-graph decision holds.
|
|
122
|
+
|
|
115
123
|
## Task right-sizing
|
|
116
124
|
|
|
117
125
|
A task is the smallest unit that carries its own test cycle and is worth a fresh
|
|
@@ -71,6 +71,7 @@ a row pointing outside the bundle is the defect this file exists to catch.
|
|
|
71
71
|
| What a stage reads, and which host files bind it | `references/artifacts.md` |
|
|
72
72
|
| The design conversation, its hard gate, UI detection, user paths | `references/brainstorm.md` |
|
|
73
73
|
| Cutting a platform into modules, brick criteria, build order | `references/decomposition.md` |
|
|
74
|
+
| **Wave mode** — the whole board: the inventory, the canvas, the one question batch, the wave cut and the close pass | `references/waves.md` |
|
|
74
75
|
| What a spec must lock, the UX-track order, the module dossier | `references/spec.md` |
|
|
75
76
|
| The zero-context plan format, parallel groups, set equality | `references/planning.md` |
|
|
76
77
|
| The work graph: its fields, the verbs and their exit codes, and the three invariants a schema cannot state | `references/work-graph.md`, `scripts/graph.py`, `graph.schema.json` |
|
|
@@ -166,9 +166,10 @@ never that the work was skipped quietly.
|
|
|
166
166
|
([`progress.md`](progress.md)), and a skip nobody can see is indistinguishable from a
|
|
167
167
|
stage that was never entered.
|
|
168
168
|
- **How it runs: [`grill.md`](grill.md)** — the full doctrine, built into this
|
|
169
|
-
skill (nothing to install). In short:
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
skill (nothing to install). In short: close what the sources can, then ONE batch
|
|
170
|
+
of the material unknowns, ordered by dependency, a recommended answer with each —
|
|
171
|
+
one at a time only where answers depend on each other or the operator asks;
|
|
172
|
+
contradictions reconciled on the spot; **every answer that touches
|
|
172
173
|
a harvested source is checked against it** — the operator outranks any document,
|
|
173
174
|
but only out loud, and the losing side is logged for the stage-9 doc update; plus
|
|
174
175
|
**domain awareness**
|
|
@@ -267,9 +268,9 @@ never that the work was skipped quietly.
|
|
|
267
268
|
- **Freedom: high** — many designs are valid — this is the open field, and the only fixed thing is the gate ([`gates.md`](gates.md) → *Axis C*).
|
|
268
269
|
- **How it runs: [`brainstorm.md`](brainstorm.md)** — built into this skill. Read
|
|
269
270
|
the brief first (stage 0 already answered scope/constraints/done-criteria), then
|
|
270
|
-
explore the codebase, scope-check for decomposition,
|
|
271
|
-
approaches with a recommendation, design presented in sections and
|
|
272
|
-
section by section. **Hard gate:** no code, no scaffolding, no implementation
|
|
271
|
+
explore the codebase, scope-check for decomposition, the open questions in one
|
|
272
|
+
batch, 2–3 approaches with a recommendation, design presented in sections and
|
|
273
|
+
approved section by section. **Hard gate:** no code, no scaffolding, no implementation
|
|
273
274
|
skill before the operator approves the design — including on "obviously simple"
|
|
274
275
|
tasks.
|
|
275
276
|
- **UI detection (mandatory check):** decide whether the task touches any
|
|
@@ -588,7 +589,11 @@ never that the work was skipped quietly.
|
|
|
588
589
|
`partial` ships only with the operator's explicit acceptance. A gap is cheapest to
|
|
589
590
|
close before it ships, and the operator is already present at this gate. **The
|
|
590
591
|
carry-over count is printed beside this verdict.** Deploy is outward → explicit
|
|
591
|
-
operator go
|
|
592
|
+
operator go — unless the operator already authorised releases. **Before the tag, read
|
|
593
|
+
the release's approval mode** (`pipeline.json` → `release.approval`; then
|
|
594
|
+
[`deploy-targets.md`](deploy-targets.md) → *When the release waits for an approval*):
|
|
595
|
+
`checks` — push the tag, watch the run selected by the tag, report; `reviewers` — the
|
|
596
|
+
direct link to the run that is actually `waiting`, never a request without it. Respect deploy-from-main rules if the project mandates them. **Before
|
|
592
597
|
tagging, the CI verdict for what was just pushed is READ, not assumed**
|
|
593
598
|
([`conventions.md`](conventions.md) → *The CI verdict*) — a tag on a commit whose
|
|
594
599
|
run nobody read is how a red `main` ships.
|
|
@@ -859,6 +864,9 @@ module N → 3 spec (dossier) → 4 plan → 5 build → 6 tests → 7 lint+depl
|
|
|
859
864
|
- **Program done** when every row is `done` or `deferred` with an agreed home, the
|
|
860
865
|
cross-module contracts are covered by tests that cross the seam, and a final
|
|
861
866
|
acceptance covers the platform's whole REQ table — not module by module.
|
|
867
|
+
- **The whole board, rather than one platform, is wave mode**
|
|
868
|
+
([`waves.md`](waves.md)): stages 0–4 once over every open item, 5–8 per wave with a
|
|
869
|
+
close pass after each, 9–10 to close the release.
|
|
862
870
|
|
|
863
871
|
## Cross-cutting — the Doc Loop
|
|
864
872
|
|