task-pipeline-skill 1.93.3 → 1.95.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +145 -0
- package/CONTRIBUTING.md +32 -0
- package/HOW-IT-WORKS.md +4 -3
- package/README.md +59 -15
- package/SKILL-CARD.md +2 -2
- package/bin/task-pipeline.js +64 -33
- package/cursor/rules/task-pipeline.mdc +10 -5
- package/evals/RESULTS.md +1 -1
- package/evals/task-pipeline.evals.json +16 -0
- package/package.json +3 -3
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/agents/verifier.md +5 -2
- package/plugins/task-pipeline/commands/task-pipeline.md +25 -10
- package/plugins/task-pipeline/hooks/memory-nudge.sh +45 -3
- package/plugins/task-pipeline/hooks/release-gate.sh +1 -1
- package/plugins/task-pipeline/skills/evidence-docs/references/gates.md +6 -3
- package/plugins/task-pipeline/skills/evidence-docs/references/hooks.md +2 -1
- package/plugins/task-pipeline/skills/evidence-docs/references/retrospective.md +26 -1
- package/plugins/task-pipeline/skills/task-pipeline/SKILL.md +24 -20
- package/plugins/task-pipeline/skills/task-pipeline/graph.schema.json +89 -4
- package/plugins/task-pipeline/skills/task-pipeline/pipeline.schema.json +7 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/artifacts.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/backlog.md +25 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/brainstorm.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/browser.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/certification.md +46 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/companion-skills.md +3 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/continuity.md +97 -26
- package/plugins/task-pipeline/skills/task-pipeline/references/deploy-targets.md +30 -4
- package/plugins/task-pipeline/skills/task-pipeline/references/doctrine-map.md +20 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/gates.md +6 -3
- package/plugins/task-pipeline/skills/task-pipeline/references/grill.md +2 -2
- package/plugins/task-pipeline/skills/task-pipeline/references/hooks.md +2 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/iteration.md +387 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/knowledge-sources.md +1 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/loop-guard.md +4 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/portability.md +13 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/retrospective.md +26 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +7 -5
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-00-intake.md +158 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-01-docs-study.md +10 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-02-brainstorm.md +52 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-03-spec.md +66 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-04-plan.md +11 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-05-dev.md +55 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-06-tests.md +11 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-07-lint-deploy.md +15 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-08-post-deploy.md +29 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-09-docs-wiki.md +45 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stage-10-acceptance.md +91 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/stages.md +60 -475
- package/plugins/task-pipeline/skills/task-pipeline/references/verification.md +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/waves.md +76 -36
- package/plugins/task-pipeline/skills/task-pipeline/references/work-graph.md +54 -5
- package/plugins/task-pipeline/skills/task-pipeline/scripts/backlog_sources.py +54 -13
- package/plugins/task-pipeline/skills/task-pipeline/scripts/context_packets.py +3 -3
- package/plugins/task-pipeline/skills/task-pipeline/scripts/graph.py +205 -22
- package/plugins/task-pipeline/skills/task-pipeline/scripts/lessons.py +1137 -0
- package/plugins/task-pipeline/skills/task-pipeline/scripts/stage_checkpoint.py +264 -44
- package/plugins/task-pipeline/skills/task-pipeline/scripts/waves.py +546 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/README.md +6 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/backlog-sources.schema.json +96 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/canvas.md +97 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/dossier.md +82 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/inventory.schema.json +94 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/lesson.schema.json +221 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/questions.md +45 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/retro.md +4 -0
- package/plugins/task-pipeline/skills/task-pipeline/templates/run.md +2 -2
|
@@ -21,6 +21,7 @@ queue is — graph or plan — is what decides, not the mood of the closer.
|
|
|
21
21
|
- The report, and where each field lands
|
|
22
22
|
- The commands
|
|
23
23
|
- The fix cycle, and its ceiling
|
|
24
|
+
- Rounds owed by risk class
|
|
24
25
|
- What this costs, said out loud
|
|
25
26
|
- Rationalizations
|
|
26
27
|
|
|
@@ -83,7 +84,7 @@ tier saw.
|
|
|
83
84
|
| `visual` | the contact sheet, the director record, the project linter's output, the rubric | a frame that contradicts the record's intent; a gate item failing under a PASS; a hole in the state × axes matrix; a judge verdict from an uncalibrated judge |
|
|
84
85
|
|
|
85
86
|
**When it runs.** A node that builds a user-facing surface copies the brief's
|
|
86
|
-
`surface_class` ([`
|
|
87
|
+
`surface_class` ([`stage-00-intake.md`](stage-00-intake.md) → *0 — Intake grill — MANDATORY*, the surface-class bullet). On
|
|
87
88
|
**`flagship` and `product`** the `visual` report is **required** — `graph.py certify`
|
|
88
89
|
refuses the round without it and names the tier. On `internal` and `ad` it is accepted
|
|
89
90
|
when given and counted like any other tier, and not demanded: an internal tool's floor
|
|
@@ -217,10 +218,53 @@ has failed **every** round. A run spinning on one level needs the operator to se
|
|
|
217
218
|
*which* level:
|
|
218
219
|
|
|
219
220
|
- the same tier every round → the level is being misread, or the node is the wrong
|
|
220
|
-
shape. Not one fix away. Re-plan the node, do not attempt round
|
|
221
|
+
shape. Not one fix away. Re-plan the node, do not attempt another failing round. (An R3
|
|
222
|
+
node's owed rounds are not this count — *Rounds owed by risk class*, below.)
|
|
221
223
|
- different tiers each round → churn across levels. Usually one requirement that
|
|
222
224
|
was never decided, surfacing at whichever distance looks at it.
|
|
223
225
|
|
|
226
|
+
## Rounds owed by risk class
|
|
227
|
+
|
|
228
|
+
In a release iteration a node carries `risk` (R1–R3, [`work-graph.md`](work-graph.md);
|
|
229
|
+
[`iteration.md`](iteration.md) → *Verification starts when a node lands*), and the class
|
|
230
|
+
decides how many **passing** rounds the node owes before `close` accepts it: **R1 one, R2
|
|
231
|
+
two, R3 three, of which one is adversarial.** A round is the three blind tiers (four on a
|
|
232
|
+
flagship or product surface) plus one fix cycle. `graph.py certify` prints `round N: k of M
|
|
233
|
+
owed passing rounds — not closable yet` until the count is met (`k of M owed passing rounds —
|
|
234
|
+
closable` once it is), and `graph.py close` refuses
|
|
235
|
+
the verdict until then. **Only passing rounds count** — a round passes when every tier
|
|
236
|
+
passes, read from `certification.history` — and, for R3, one of the passing rounds must be
|
|
237
|
+
one recorded with `--kind adversarial`
|
|
238
|
+
(`certification.kinds`, one entry per round). A node with a `risk` and no certification at
|
|
239
|
+
all is refused by `close` too: its class owes at least one round.
|
|
240
|
+
|
|
241
|
+
**What a round after a clean round reads.** The node's **whole diff at the new HEAD** — not
|
|
242
|
+
the fix diff alone, and not the previous round's reports. A clean round proves the tree it
|
|
243
|
+
read; the next owed round asks the same three distances again of the whole change as it
|
|
244
|
+
stands, so a defect the first reading accepted has a second chance to be seen from a fresh
|
|
245
|
+
context.
|
|
246
|
+
|
|
247
|
+
**Owed rounds and the ceiling are different counts.** `--ceiling` measures churn: how many
|
|
248
|
+
rounds a node has *failed*, and which tier keeps failing. An R3 node that owes three rounds
|
|
249
|
+
and passes them is not "at round four" of anything; its owed rounds are the plan, and the
|
|
250
|
+
ceiling's warning is about failing rounds beyond what the class owes. Read the ceiling's
|
|
251
|
+
output only when rounds fail.
|
|
252
|
+
|
|
253
|
+
**The adversarial round** (one of R3's three, on another model where one is available):
|
|
254
|
+
1. **Plant defects in the change** — off-by-one in a limit, an inverted check, a dropped
|
|
255
|
+
error path — and require the node's own checks to fail on each. A plant that passes is a
|
|
256
|
+
finding against the check, not against the plant.
|
|
257
|
+
2. **Model the external system's state across runs** — a policy edited between two runs, a
|
|
258
|
+
key or resource renamed, two writers at once, a provider that echoes a request back or
|
|
259
|
+
answers twice. The defects of a money or credential path live in the second run, not
|
|
260
|
+
the first.
|
|
261
|
+
3. **Try the abuse cases** a caller outside the trust boundary would: inputs at and past
|
|
262
|
+
every bound, replays, a revoked identity, an out-of-order sequence.
|
|
263
|
+
|
|
264
|
+
It is a different question, not a stricter reading: on 2026-10-12 one iteration's third
|
|
265
|
+
round on a spend-limits node found three breaks of a money invariant that two blind rounds
|
|
266
|
+
had passed. Record it with `certify --kind adversarial`.
|
|
267
|
+
|
|
224
268
|
## What this costs, said out loud
|
|
225
269
|
|
|
226
270
|
Three agents per node instead of one — four on a flagship or product surface. That is
|
|
@@ -287,7 +287,8 @@ Rules:
|
|
|
287
287
|
nothing: **one self-observed run by the author, zero blind runs on zero models**, with
|
|
288
288
|
a preflight that reported companion availability in detail and its own confidence not
|
|
289
289
|
at all. A skill silent about its own evidence is read as tested.
|
|
290
|
-
- **Never gate any stage on an install
|
|
290
|
+
- **Never gate any stage on an install.** On UI tasks the stage-3 gate requires the
|
|
291
|
+
valid scenario artifact under the provider rule above, not a package.
|
|
291
292
|
- Optional tools missing → state the fallback, don't block.
|
|
292
293
|
- Re-detect after the operator installs; don't assume.
|
|
293
294
|
- The model answer goes into the brief. Don't ask again per stage
|
|
@@ -342,5 +343,5 @@ Both notices live in the repo `LICENSE` → *Third-party*.
|
|
|
342
343
|
## Hand-off the other direction
|
|
343
344
|
|
|
344
345
|
super-ux's `/ux` menu can hand off *to* this pipeline (its "execute autonomously"
|
|
345
|
-
action). When entered that way the UX chain already exists — see `
|
|
346
|
+
action). When entered that way the UX chain already exists — see `stage-00-intake.md`
|
|
346
347
|
*Entry-from-super-ux short-circuit*: verify, don't rebuild.
|
|
@@ -27,19 +27,63 @@ almost no window left, loses the middle of it, and re-derives what it already di
|
|
|
27
27
|
|
|
28
28
|
**The loop mode collapses discretionary check-ins. It collapses nothing else.**
|
|
29
29
|
|
|
30
|
-
- A `manual` gate
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
- A `manual` gate requires the operator's explicit go. A specific standing authorization
|
|
31
|
+
naming that gate's act is such a go; cite its source and scope in the gate record.
|
|
32
|
+
Without it, the gate waits. A generic instruction to continue is not authorization.
|
|
33
|
+
- An outward or irreversible act — deploy, publish, a tag or a release, sending to a
|
|
34
|
+
person, spending money, creating or editing a shared design file — still needs its own
|
|
35
|
+
**specific** authorization. A recorded loop mode is a **generic** flag, and a generic
|
|
36
|
+
flag is not a specific authorization; that floor is set in [`grill.md`](grill.md) and
|
|
37
|
+
this file does not lower it.
|
|
38
|
+
- **Pushing this repository's work and opening its pull request** is armed by a specific
|
|
39
|
+
standing authorization that names it — a recorded instruction to push the requested work
|
|
40
|
+
to the repository's own remote ([`build.md`](build.md) → *6. Integrate, then finish*).
|
|
41
|
+
Without one it waits for the go like the acts above. Another repository's PR is outward
|
|
42
|
+
every time ([`conventions.md`](conventions.md)).
|
|
43
|
+
|
|
44
|
+
**What arms the loop — exactly three sources, and the ledger says which.**
|
|
45
|
+
1. `run.loop` in `pipeline.json` (Part 1);
|
|
46
|
+
2. the operator's answer at preflight;
|
|
47
|
+
3. **a standing instruction the host already carries** — an organisation's principle that
|
|
48
|
+
a free agent takes the next task, a global instruction file, a recorded decision.
|
|
49
|
+
|
|
50
|
+
The run cites its source once, in the ledger: `loop: armed by <source:line>`.
|
|
51
|
+
**Silence still arms nothing**: absent all three, the mode is off, exactly as silence authorizes no
|
|
52
|
+
deploy. A project with no such instruction behaves as it always did.
|
|
53
|
+
|
|
54
|
+
**What a watcher may do unasked.** A wait is not a stop: while a review, CI, a peer's
|
|
55
|
+
answer or a release run is pending, the run starts a watcher and takes the next independent
|
|
56
|
+
item (*Waits outlive turns*, below). When the wait clears, the watcher may take — **only
|
|
57
|
+
where a standing instruction names that class of act** — these steps: merge under the
|
|
58
|
+
repository's own integration policy, release a lease, rebase a stacked branch onto what
|
|
59
|
+
landed, notify. Deploy, publish, tag and sending to people stay gated unless a *specific*
|
|
60
|
+
standing authorization names them. A recorded "releases are the agent's" decision is one:
|
|
61
|
+
it names the act class — the tag, and the publish its release run performs — and, when it
|
|
62
|
+
names no repositories, it covers every repository its owner governs. It does not stretch to
|
|
63
|
+
a deploy or a message it does not name.
|
|
64
|
+
|
|
65
|
+
**Work that depends on a pending change is not blocked by it**: start it on a branch
|
|
66
|
+
stacked on the pending one, open its PR against that branch, and rebase or merge when the
|
|
67
|
+
pending change lands. **A watcher polls at the pace its wait changes** — a PR or a peer's
|
|
68
|
+
answer every one to two minutes, a release run while it runs, a scheduled time at that time
|
|
69
|
+
— and that pace is separate from the loop's `/loop` interval below, which paces items, not
|
|
70
|
+
waits.
|
|
38
71
|
|
|
39
72
|
The mode's whole content is the removal of *"should I continue?"* between items
|
|
40
73
|
the operator already asked for. Anything beyond that is a different decision,
|
|
41
74
|
taken separately.
|
|
42
75
|
|
|
76
|
+
### Waits outlive turns
|
|
77
|
+
|
|
78
|
+
A watcher started inside a session — a background loop, a monitor, a session cron —
|
|
79
|
+
dies with the session. **A wait that can outlive the session goes on a durable trigger**: a
|
|
80
|
+
launchd or systemd job, an `at` one-shot, a CI schedule, or a board row with a due time that
|
|
81
|
+
a session-start hook surfaces, where the host has one. Its one line — what it waits on and which trigger acts on it —
|
|
82
|
+
goes into the handoff or the board ([`backlog.md`](backlog.md)), not only into the chat,
|
|
83
|
+
because the chat is the one place the next session will not read. On Claude Code the
|
|
84
|
+
session-bound primitives are a `run_in_background` loop, a Monitor and `/loop`; on other
|
|
85
|
+
harnesses, a background process or the host's own scheduler.
|
|
86
|
+
|
|
43
87
|
## Part 1 — the loop
|
|
44
88
|
|
|
45
89
|
**On, the run advances one item per iteration and does not ask between items.**
|
|
@@ -52,15 +96,21 @@ This spans the whole run, not one stage:
|
|
|
52
96
|
- the acceptance → retro tail, which is where runs most often stall one step from
|
|
53
97
|
finished.
|
|
54
98
|
|
|
55
|
-
It stops for exactly four things:
|
|
99
|
+
It stops for exactly four things: an unmet `manual` gate, a block it cannot resolve, a
|
|
56
100
|
genuine ambiguity the brief does not answer, and completion.
|
|
57
101
|
|
|
58
|
-
**A block or an ambiguity stops its node, not the run.**
|
|
59
|
-
|
|
60
|
-
([`
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
102
|
+
**A block or an ambiguity stops its node, not the run.** An ambiguity whose answer is
|
|
103
|
+
internal and reversible is not a stop at all: the run takes the recommended answer, records
|
|
104
|
+
it as **assumed** on the node, and continues ([`iteration.md`](iteration.md) → *Question
|
|
105
|
+
rounds*). Otherwise park the node with its actual reason and owner: only human-owned
|
|
106
|
+
questions are marked `needs-operator` and made answerable without context
|
|
107
|
+
([`prioritisation.md`](prioritisation.md) → *5. Where the human goes*); external waits
|
|
108
|
+
get watchers, and project-owned questions go to the owning Project under
|
|
109
|
+
[`iteration.md`](iteration.md)'s board rule. The run continues on every node it does
|
|
110
|
+
not block. When the whole frontier is blocked — `graph.py next` exits `4` — classify the
|
|
111
|
+
recorded reasons: external waits go on watchers, human decisions go into the question
|
|
112
|
+
batch. Exit 4 does not prove a human gate or completion. A watcher keeps the recorded
|
|
113
|
+
next action alive while no independent node is runnable. **When the board is empty, say so once**, and do not invent work to fill it.
|
|
64
114
|
|
|
65
115
|
**This extends [`build.md`](build.md); it does not replace it.** That file's
|
|
66
116
|
*Continuous execution* rule governs the inside of a stage-5 execution — do not
|
|
@@ -84,8 +134,13 @@ and still leave the run picking its next move by recollection — which is the f
|
|
|
84
134
|
nodes and nothing else. It is preferred over the two below for one measured reason — a
|
|
85
135
|
400-node graph and a 4-node graph produce the same 27-byte frontier, so the cost of knowing
|
|
86
136
|
what is next does not grow with the programme. `run.loop.queue: work-graph` records it, and
|
|
87
|
-
`next`'s exit codes are what the loop branches on: `3` is *every node is
|
|
88
|
-
|
|
137
|
+
`next`'s exit codes are what the loop branches on: `3` is *every node is terminal*
|
|
138
|
+
(including deliberately parked nodes), `4` retains another unresolved barrier, and
|
|
139
|
+
`6` means recorded watched waits hold every remaining dependency leaf. On 6, keep
|
|
140
|
+
the recorded watchers armed and take independent work; it is neither completion
|
|
141
|
+
nor a new human gate. `graph.py wait` records the locator and `resume --wait-id`
|
|
142
|
+
resolves that exact wait; neither executes a watcher or grants authority. See
|
|
143
|
+
[`work-graph.md`](work-graph.md) → *Watched external waits*.
|
|
89
144
|
|
|
90
145
|
**Otherwise the queue is the module map** ([`decomposition.md`](decomposition.md)) when the brief
|
|
91
146
|
was a platform, and the plan's task list otherwise. Both already exist and both are
|
|
@@ -97,6 +152,10 @@ stage 2** and the run says so in one line. It is not asked for at that point, fo
|
|
|
97
152
|
same reason the mode is recorded rather than requested: re-asking would rebuild the habit
|
|
98
153
|
the config exists to retire.
|
|
99
154
|
|
|
155
|
+
**A standing instruction the host carries counts as recorded** (*The limit, before the
|
|
156
|
+
capability*, source 3): it arms at the close of stage 2 like `run.loop`, unless the
|
|
157
|
+
instruction itself says otherwise, and the ledger cites it.
|
|
158
|
+
|
|
100
159
|
**Where nothing is recorded, nothing arms.** Silence arms nothing here too — this section
|
|
101
160
|
moves *where* a recorded mode is armed, from preflight to the close of stage 2. It does
|
|
102
161
|
not make arming unconditional, and a reader who takes it that way would arm a loop in a
|
|
@@ -104,7 +163,8 @@ project with no `pipeline.json` at all. That reading was in this section's first
|
|
|
104
163
|
an independent reader found it before it shipped.
|
|
105
164
|
|
|
106
165
|
**What arming does NOT change, and this is load-bearing:** the four stops are the four
|
|
107
|
-
stops. A `manual` gate
|
|
166
|
+
stops. A `manual` gate waits unless a specific standing authorization already names
|
|
167
|
+
its act, cited with its source and scope. An outward or irreversible act still needs its own
|
|
108
168
|
specific authorization — *a generic flag is not a specific authorization*, and arming a
|
|
109
169
|
queue is the most generic flag there is. Arming decides only that the run does not stop
|
|
110
170
|
to ask *"shall I take the next one?"*.
|
|
@@ -293,10 +353,12 @@ true.
|
|
|
293
353
|
|
|
294
354
|
## What happens at the signal
|
|
295
355
|
|
|
296
|
-
The four acts above, in order, and one prohibition: **
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
356
|
+
The four acts above, in order, and one prohibition: **no new item starts.** This is the one
|
|
357
|
+
carve-out from "take the next task in the same turn": **at the compaction signal, finish the
|
|
358
|
+
current unit and write the next task into the handoff** — the ledger's next line, the board
|
|
359
|
+
row — **instead of starting it.** Until compaction, the only writes are to what already
|
|
360
|
+
exists: the ledger, the plan, the decisions already settled, the REQ statuses. The next
|
|
361
|
+
turn, after compaction, takes the written task from there.
|
|
300
362
|
|
|
301
363
|
If the project has recorded that it must not cross a compaction mid-stage, stop at
|
|
302
364
|
the stage boundary instead and hand off. That is a project answer, not a default:
|
|
@@ -318,6 +380,11 @@ right costs nothing extra and pays twice.
|
|
|
318
380
|
|
|
319
381
|
## Part 3 — workflow memory at the stage boundary
|
|
320
382
|
|
|
383
|
+
Project Observatory is a separately installed, public engine:
|
|
384
|
+
[passioncode-ai/project-observatory-dashboard](https://github.com/passioncode-ai/project-observatory-dashboard)
|
|
385
|
+
— its README's *Install* and *MCP* sections say how to run it and connect it. Without it,
|
|
386
|
+
everything below degrades to one ledger line and the run continues.
|
|
387
|
+
|
|
321
388
|
Which of the five handoff mechanisms carries what — the Git record, Observatory's lease
|
|
322
389
|
and checkpoint, a host's launch context, the inbound queue — and the order a successor
|
|
323
390
|
reads them in, has one home:
|
|
@@ -330,12 +397,14 @@ Project Observatory's memory tools, **every gate that returns also writes a work
|
|
|
330
397
|
checkpoint**, and the next executor continues from the last finished stage.
|
|
331
398
|
|
|
332
399
|
- **When.** After the `stage:` line is appended, every time a gate returns, whatever the verdict. A failed gate's checkpoint says `blocked` and keeps the stage open. Acceptance closes the workflow.
|
|
333
|
-
- **How.** `scripts/stage_checkpoint.py emit` prints the tool's arguments, built from the ledger
|
|
400
|
+
- **How.** `scripts/stage_checkpoint.py emit` prints the tool's arguments, built from the ledger and selected project profile: the topic, observed verdicts, next declared stage, operator's constraints and key names. Pass them to `observatory_checkpoint_write`, or to `memory.checkpoint.write` under memory/0.1. Then hand the answer to `stage_checkpoint.py record --answer -`.
|
|
401
|
+
- **Profile authority.** `pipeline.json` at the project root owns stage order; only genuinely absent config selects the bundled default. Unreadable/malformed config, ambiguous numeric ledger ids, unsupported mandatory capabilities or a ledger stage outside the selected profile refuse before producing tool arguments. Optional ids use array ordinals, optional names use stable state labels; explicit ids retain declared array order. This reader does not execute gates or replace full preflight/schema validation. A final skipped stage stays open for confirmation, never inventing a successor or closing by inference.
|
|
402
|
+
- **Root and recovery.** The usual ledger stays `.task-pipeline/run.md`; `paths.artifacts` relocates project documents, not this run state. For a relocated ledger use `emit --ledger <path> --project-root <project>` (an enclosing Git root can also establish the project). The first emit saves the selected profile's source/digest and run identity beside the ledger; record retains them. Same-run profile changes, a missing formerly selected config, or a different run reusing that state refuse. Restore the selected source and retry, or reconcile the old workflow and start a distinct ledger/state for the new run; never delete a lease to make the check green. A pre-existing custom workflow with no profile binding also needs reconciliation. Ledger file symlinks and state-file links refuse without migration or overwrite; accepted directory aliases resolve consistently for emit, record, state and handoff. Profile, ledger and existing state inputs must be regular files, so a FIFO is refused before reading. No live checkpoint or read-attestation is proved by a locally emitted payload.
|
|
334
403
|
- **The constraints.** Give the brief's restrictive rules once, as `--constraint`. They are carried to every later boundary, and a successor reads them first.
|
|
335
404
|
- **Keys.** Pass keys by name, as `--credential PROJECT/ENV/NAME`, never as a value.
|
|
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.
|
|
405
|
+
- **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. When the tools are absent for the whole run — no Observatory on this machine — say it **once**: `record --unavailable "<why>" --for-run` appends one `unavailable for this run` line and leaves a marker in `.task-pipeline/memory.json`; no later gate is nudged or needs a line. Any later `record --answer` (the tools came back) clears the marker.
|
|
337
406
|
- **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. A retried offer keeps its idempotency key until a memory event (a checkpoint, a refusal, a recorded offer — never `unavailable`) is appended, so a `gate:` or `stage:` line between retries does not turn it into a new offer that replaces the unaccepted one.
|
|
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.
|
|
407
|
+
- **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 — unless the run-level marker says memory is unavailable for this run, in which case it stays silent. The first reminder of a run also says where Observatory comes from, once. It decides nothing and blocks nothing; adoption measured before it was one write in 293 sessions.
|
|
339
408
|
- **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.
|
|
340
409
|
- **The lease token.** It lives in `.task-pipeline/memory.json` (mode 0600, git-ignored) and never in the ledger, a reply or a commit.
|
|
341
410
|
- **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.
|
|
@@ -344,7 +413,9 @@ checkpoint**, and the next executor continues from the last finished stage.
|
|
|
344
413
|
|
|
345
414
|
| Excuse | Reality |
|
|
346
415
|
|---|---|
|
|
347
|
-
| "The operator obviously wants it to keep going, I'll just loop" | Default off. Silence arms nothing — the same floor deploy authorization uses.
|
|
416
|
+
| "The operator obviously wants it to keep going, I'll just loop" | Default off. Silence arms nothing — the same floor deploy authorization uses. Arm from `run.loop`, the preflight answer, or a standing instruction the host carries, and cite which in the ledger. |
|
|
417
|
+
| "The watcher can push the release through when CI goes green" | A watcher takes only the act classes a standing instruction names — merge, release a lease, rebase, notify. A tag or a deploy needs its own specific authorization. |
|
|
418
|
+
| "My background loop will catch it tomorrow" | It dies with the session. A wait that can outlive it goes on a durable trigger, and its line goes into the handoff. |
|
|
348
419
|
| "The mode is on, so I can push the deploy through" | The mode collapses check-ins, never gates or outward acts. A generic flag is not a specific authorization. |
|
|
349
420
|
| "I'll tell it to keep going and it will" | On Claude Code, prose does not survive the turn boundary. Either a job is scheduled or the run stops; say which. |
|
|
350
421
|
| "A one-minute interval is closest to no pause" | The interval must be longer than a typical item, or every fire lands on work already in progress and buys nothing. |
|
|
@@ -165,6 +165,16 @@ shipped — and it is exactly what the stage-8 gate is for.
|
|
|
165
165
|
|
|
166
166
|
### When the release waits for an approval
|
|
167
167
|
|
|
168
|
+
**Establish the authority for the act separately from the approval mode.** Optional
|
|
169
|
+
`release.authorized_by` records a single-line source locator, such as a committed
|
|
170
|
+
`source:line`, for the standing grant covering the tag and publication. A locator
|
|
171
|
+
is not authorization: read its source and verify the issuer's authority, the grant's
|
|
172
|
+
currentness and its exact act and scope. A missing, unreadable or ambiguous source
|
|
173
|
+
cannot establish a grant. If the field is absent, inspect existing recorded authority
|
|
174
|
+
before asking; neither field presence nor `approval: checks` supplies permission.
|
|
175
|
+
Human-only actions remain human, and a release grant does not authorize a separate
|
|
176
|
+
deployment or message it does not name.
|
|
177
|
+
|
|
168
178
|
**Read the project's approval mode before tagging, and do not guess it.** It is one of
|
|
169
179
|
two, and each owes the operator something different.
|
|
170
180
|
|
|
@@ -172,8 +182,11 @@ two, and each owes the operator something different.
|
|
|
172
182
|
`release-guard` checks that the tag is on main and that CI on that commit is green,
|
|
173
183
|
and the `release` environment has no reviewers. PassionCode products declare this in
|
|
174
184
|
`passioncode-ai/.github` `release-signing/products.json` (`"approval": "checks"`).
|
|
175
|
-
Push the tag
|
|
176
|
-
|
|
185
|
+
Push the authorized tag and put the run selected **by that tag** on a watcher.
|
|
186
|
+
Follow [`continuity.md`](continuity.md) → *Waits outlive turns*: take independent work
|
|
187
|
+
meanwhile, and use a durable trigger if the wait may outlive the session. On success,
|
|
188
|
+
continue stage 8 on the published artefact and report; on failure, report the cause.
|
|
189
|
+
A refusal is fixed at its cause,
|
|
177
190
|
never worked around. Send no approval request: there is nobody to send it to.
|
|
178
191
|
- **`reviewers`** — the run stops at an environment with required reviewers. Find that
|
|
179
192
|
run by the tag, and confirm its status is `waiting` before saying anything:
|
|
@@ -184,7 +197,11 @@ two, and each owes the operator something different.
|
|
|
184
197
|
|
|
185
198
|
Then hand the operator the **direct link** to that run, where they press *Review
|
|
186
199
|
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.
|
|
200
|
+
the link is incomplete, and so is a link to a run that is not waiting. Put that run
|
|
201
|
+
on a watcher that continues stage 8 after approval and successful publication. Where
|
|
202
|
+
standing host instructions name an approval-notification channel, send the same link
|
|
203
|
+
there with a stable event id per repository/tag/run. An unavailable channel is reported;
|
|
204
|
+
it is not a reason to invent another recipient or omit the direct link.
|
|
188
205
|
|
|
189
206
|
The mode comes from, in order:
|
|
190
207
|
1. `pipeline.json` → `release.approval`;
|
|
@@ -204,7 +221,7 @@ A run that cannot establish the mode says so. It does not assume `checks`.
|
|
|
204
221
|
|
|
205
222
|
## The verification trio
|
|
206
223
|
|
|
207
|
-
|
|
224
|
+
For a served application, stage 8's gate needs the same three, and all three:
|
|
208
225
|
|
|
209
226
|
1. **Process/deployment state** — is the new version the running version
|
|
210
227
|
2. **Runtime logs** — clean boot, no error spike
|
|
@@ -213,3 +230,12 @@ Whatever the platform, stage 8's gate needs the same three, and all three:
|
|
|
213
230
|
One or two of the three is where "deployed successfully" gets said about a
|
|
214
231
|
service that is crash-looping. If any of the three cannot be obtained, that is
|
|
215
232
|
the honest degradation report the gate asks for — not a reason to call it green.
|
|
233
|
+
|
|
234
|
+
**Installed artefacts use their consumer boundary.** For a package, plugin, skill or CLI,
|
|
235
|
+
verify the registry's published version; refresh existing installations within the
|
|
236
|
+
authorized rollout through the owner's update path, then read back their actual versions
|
|
237
|
+
and installed payloads. Read the update/runtime diagnostics and run the supported consumer
|
|
238
|
+
smoke check for each claimed channel. A registry version alone does not prove an installed
|
|
239
|
+
update, and readable files do not prove native discovery or model/task quality. If a channel
|
|
240
|
+
cannot be checked, name it and leave its acceptance open. Do not invent a server health
|
|
241
|
+
URL or clean-boot log for a target that has neither.
|
|
@@ -6,8 +6,9 @@ built-in doctrine lives, so an agent loads the one file the stage needs instead
|
|
|
6
6
|
carrying the whole index in every turn.
|
|
7
7
|
|
|
8
8
|
The rule the table serves stays in `SKILL.md`: every stage's doctrine ships inside this
|
|
9
|
-
skill
|
|
10
|
-
|
|
9
|
+
skill and no stage blocks on an install. The stage-3 UX gate on a user-facing task
|
|
10
|
+
requires a valid scenario artifact; [the provider rule](companion-skills.md) governs
|
|
11
|
+
the preferred provider, equivalent providers and inline fallback.
|
|
11
12
|
|
|
12
13
|
## Contents
|
|
13
14
|
|
|
@@ -15,8 +16,24 @@ UX track on a user-facing task.
|
|
|
15
16
|
|
|
16
17
|
## Which reference owns which stage
|
|
17
18
|
|
|
19
|
+
For the default profile, `references/stages.md` owns the full gates and exact
|
|
20
|
+
on-entry/resume route to each `references/stage-*.md` detail. Read the selected
|
|
21
|
+
stage detail before its work; this table routes additional subject doctrine.
|
|
22
|
+
Custom profiles use their own declared stages and doctrine, with the kernel intact.
|
|
23
|
+
|
|
18
24
|
| Stage | Built-in doctrine |
|
|
19
25
|
|---|---|
|
|
26
|
+
| 0 · Stage procedure | `references/stage-00-intake.md` |
|
|
27
|
+
| 1 · Stage procedure | `references/stage-01-docs-study.md` |
|
|
28
|
+
| 2 · Stage procedure | `references/stage-02-brainstorm.md` |
|
|
29
|
+
| 3 · Stage procedure | `references/stage-03-spec.md` |
|
|
30
|
+
| 4 · Stage procedure | `references/stage-04-plan.md` |
|
|
31
|
+
| 5 · Stage procedure | `references/stage-05-dev.md` |
|
|
32
|
+
| 6 · Stage procedure | `references/stage-06-tests.md` |
|
|
33
|
+
| 7 · Stage procedure | `references/stage-07-lint-deploy.md` |
|
|
34
|
+
| 8 · Stage procedure | `references/stage-08-post-deploy.md` |
|
|
35
|
+
| 9 · Stage procedure | `references/stage-09-docs-wiki.md` |
|
|
36
|
+
| 10 · Stage procedure | `references/stage-10-acceptance.md` |
|
|
20
37
|
| 0, 9 · The documentation system | `references/documentation.md` |
|
|
21
38
|
| any stage · The canons, and where each is enforced | [`evidence-docs`](../../evidence-docs/SKILL.md) — the sibling skill in this plugin |
|
|
22
39
|
| 6–10 · Gates | `references/gates.md` |
|
|
@@ -28,6 +45,7 @@ UX track on a user-facing task.
|
|
|
28
45
|
| 2 Brainstorm | `references/brainstorm.md` |
|
|
29
46
|
| 2 Decompose (platforms only) | `references/decomposition.md` |
|
|
30
47
|
| 0–10 · **wave mode** — the whole board: 0–4 once, 5–8 per wave, 9–10 to close | `references/waves.md` |
|
|
48
|
+
| 0–10 · **release iteration** — the loop around the waves: dossiers, integration, question rounds, checks as nodes land, release, post-release check, next pool, the shared lesson store | `references/iteration.md` |
|
|
31
49
|
| 3 Spec | `references/spec.md` |
|
|
32
50
|
| 4 Plan | `references/planning.md` |
|
|
33
51
|
| the queue the loop walks | `references/work-graph.md` |
|
|
@@ -50,12 +50,14 @@ From [`../pipeline.schema.json`](../pipeline.schema.json), one per stage:
|
|
|
50
50
|
|---|---|---|
|
|
51
51
|
| `auto` | the orchestrator verifies the `check` itself, pass/fail, and stops on fail | advancing on an unverified check |
|
|
52
52
|
| `judgment` | somebody **rules** on it, because no complete deterministic check exists; the gate names its `judge` | recording the ruling in the slot reserved for what a machine established |
|
|
53
|
-
| `manual` |
|
|
53
|
+
| `manual` | the operator's **explicit** go, or specific standing authorization naming the act | treating an auto verification as the approval |
|
|
54
54
|
|
|
55
55
|
**An auto gate never substitutes for a required manual approval.** A green table is
|
|
56
56
|
not the operator confirming it is what they asked for, and no amount of checking
|
|
57
57
|
makes it one. Which stages are manual is the **operator's** decision, recorded in
|
|
58
58
|
their `pipeline.json`; the framework fixes no stage count and no gate assignment.
|
|
59
|
+
A standing authorization is cited with its source and scope, not inferred from a generic
|
|
60
|
+
loop flag ([`continuity.md`](continuity.md) → *The limit, before the capability*).
|
|
59
61
|
|
|
60
62
|
**That sentence is about the pipeline's SHAPE, and nothing else.** It says a project
|
|
61
63
|
chooses how many stages it runs and which of them wait for a person. It does not say the
|
|
@@ -495,8 +497,9 @@ run:
|
|
|
495
497
|
what it does not cover, stated, beats two measurements and no decision.
|
|
496
498
|
|
|
497
499
|
**This never licenses skipping a gate.** The gates are the floor, and the floor is
|
|
498
|
-
not proportionate to anything — a `manual` gate waits
|
|
499
|
-
|
|
500
|
+
not proportionate to anything — a `manual` gate waits without an explicit go or a
|
|
501
|
+
specific standing authorization naming its act, cited with source and scope;
|
|
502
|
+
`unknown` fails stage 10, and a green nobody watched fail is not evidence at any blast radius. What is
|
|
500
503
|
proportionate is the work *above* the floor: how many axes, how many passes, how
|
|
501
504
|
much of the corpus. Cutting the floor to go faster is not speed; it is the failure
|
|
502
505
|
this whole file exists to prevent, arriving on schedule.
|
|
@@ -168,7 +168,7 @@ explicit "stop and ask me here":
|
|
|
168
168
|
| Stage | What to settle up front |
|
|
169
169
|
|---|---|
|
|
170
170
|
| run-wide | the model decision ([`model-tiering.md`](model-tiering.md)); what to decide autonomously vs escalate |
|
|
171
|
-
| run-wide Pacing | the **run mode** ([`continuity.md`](continuity.md)): does the run advance item-by-item with no check-in between items, and on what interval?
|
|
171
|
+
| run-wide Pacing | the **run mode** ([`continuity.md`](continuity.md)): does the run advance item-by-item with no check-in between items, and on what interval? Three sources arm it: `pipeline.json` → `run.loop` (read first — a recorded mode is the answer and is not re-asked), this answer, or a standing instruction the host already carries; the ledger cites which as `loop: armed by <source:line>`. **Absent all three, it is off**: recommend it, take the answer, record it. It never collapses a `manual` gate or an outward act, so this row buys pacing, not authorization |
|
|
172
172
|
| 0 Harvest | doc sources beyond this repo — other repos, hosted doc systems, the knowledge wiki, **the code graph** ([`knowledge-graph.md`](knowledge-graph.md): built / installed-not-built / absent) — and whether stage 9 may write to them (another repo is outward: propose + PR, never a direct push) |
|
|
173
173
|
| 0 Duplicates | for every artifact the build reads — a Dockerfile, a schema, a lockfile, a spec — **which copy does the consumer actually name**. Quoted from the workflow or the Makefile, not inferred from the tree: the copy that ships is often not the copy people open (`learned.md` rule 20) | the consumer line, quoted |
|
|
174
174
|
| 0 Fixtures | what **persists between runs** on this machine — a database, a volume, a cache, generated files — and the command that recreates it from nothing. A suite green against accumulated state carries a premise that is false on every runner (`learned.md` rule 18) | the recreate command, stated |
|
|
@@ -179,7 +179,7 @@ explicit "stop and ask me here":
|
|
|
179
179
|
| 0 Docs regime | where settled things live (the decision home — **one** per project, and an existing `docs/adr/` **is** it), who may write it, whether a lease mechanism is present or the run is `ungated`, the gate command and its ratchet floors, and whether this run may raise a floor ([`documentation.md`](documentation.md)) |
|
|
180
180
|
| 1 Docs | external libs/APIs/SDKs in play; any private ones context7 can't resolve → where their docs live |
|
|
181
181
|
| 2 Decompose | is this a platform (several capabilities/surfaces) or one module? if platform: deploy cadence — per module or once at the end |
|
|
182
|
-
| 2–3 Spec | UI verdict (arms super-ux) **and the surface class** — `flagship`, `product`, `internal` or `ad`, which selects the visual gate profile ([`
|
|
182
|
+
| 2–3 Spec | UI verdict (arms super-ux) **and the surface class** — `flagship`, `product`, `internal` or `ad`, which selects the visual gate profile ([`stage-00-intake.md`](stage-00-intake.md) → *0 — Intake grill — MANDATORY*, the surface-class bullet); any scenario-tracing waiver |
|
|
183
183
|
| 3 Design surface | UI tasks only: **Figma on or text-only** (super-ux's project-level choice, default on — check `docs/ux/foundation.md` → *Design tooling* before asking); is the Figma MCP connected; **and if it isn't — ship text-only, or stop here and connect it?** super-ux degrades to text-only on its own and never blocks, which means an unasked question here silently ships a UI feature with no mockups |
|
|
184
184
|
| 3 Design file | Figma on only: **exactly which files — one per surface (App, Web, ASO) — in which team/org** — the recorded ones, or a URL the operator gives, or *create one in a named team* with that creation explicitly authorized. A destination decided at drawing time is how a project ends up with three "design" files and no way to tell which is real. See *The design destination* below |
|
|
185
185
|
| 4–5 Dev | base branch; worktree/branch policy; is `main` off-limits; commit convention; task tracker |
|
|
@@ -219,7 +219,8 @@ Since v1.50.0 the plugin carries hooks of its own. `hooks/release-gate.sh`
|
|
|
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
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
|
|
222
|
+
once per returned gate, that no workflow-memory line follows it — unless the run recorded
|
|
223
|
+
memory unavailable with `--for-run`
|
|
223
224
|
([`continuity.md`](continuity.md), Part 3).
|
|
224
225
|
|
|
225
226
|
**Two lessons from v1.50.0, both shipped as defects and both fixed in v1.51.0.**
|