tickmarkr 2.6.7 → 2.6.9
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/dist/adapters/catalog-remote.js +5 -2
- package/dist/adapters/codex.d.ts +1 -0
- package/dist/adapters/codex.js +18 -10
- package/dist/adapters/model-lints.js +21 -11
- package/dist/adapters/model-windows.js +0 -1
- package/dist/adapters/registry.js +7 -3
- package/dist/adapters/types.d.ts +2 -0
- package/dist/cli/commands/beat.d.ts +3 -3
- package/dist/cli/commands/beat.js +39 -19
- package/dist/cli/commands/doctor.js +3 -0
- package/dist/cli/commands/fleet.js +2 -0
- package/dist/cli/commands/plan.js +16 -18
- package/dist/cli/commands/verify.js +4 -2
- package/dist/cli/help.js +5 -2
- package/dist/config/config.js +6 -5
- package/dist/drivers/herdr.js +2 -2
- package/dist/drivers/orca.d.ts +12 -4
- package/dist/drivers/orca.js +200 -39
- package/dist/gates/evidence.js +3 -3
- package/dist/gates/review.d.ts +1 -1
- package/dist/gates/review.js +62 -13
- package/dist/gates/run-gates.d.ts +3 -0
- package/dist/gates/run-gates.js +115 -20
- package/dist/gates/test-manifest.d.ts +36 -2
- package/dist/gates/test-manifest.js +55 -10
- package/dist/run/beat-lifecycle.d.ts +109 -24
- package/dist/run/beat-lifecycle.js +1173 -216
- package/dist/run/daemon.d.ts +4 -0
- package/dist/run/daemon.js +111 -33
- package/dist/run/git-trust.d.ts +78 -3
- package/dist/run/git-trust.js +175 -19
- package/dist/run/git.d.ts +24 -3
- package/dist/run/git.js +140 -21
- package/dist/run/merge.js +2 -2
- package/dist/run/verification-job.d.ts +2 -0
- package/dist/run/verification-job.js +32 -10
- package/dist/tui/ink/fleet-app.d.ts +7 -2
- package/dist/tui/ink/fleet-app.js +81 -23
- package/package.json +4 -1
- package/skills/tickmarkr-auto/SKILL.md +58 -14
- package/skills/tickmarkr-loop/SKILL.md +65 -14
- package/skills/tickmarkr-overseer/SKILL.md +97 -28
- package/skills/tickmarkr-overseer/scripts/watch-journal.sh +9 -7
|
@@ -26,6 +26,30 @@ again on the new token; never re-issue the old one (D-470: an unbound approve wa
|
|
|
26
26
|
gate). A failed task keeps its recheck with its bound failure token: status prints
|
|
27
27
|
`failed — T3 — failure <line>@<ts>`, and `tickmarkr approve <runId> T3 --recheck --park <line>@<ts>`
|
|
28
28
|
re-gates its landed commits with no worker.
|
|
29
|
+
|
|
30
|
+
**A waive is funded by EXECUTED evidence, never by a static read.** Every out-of-band (OOB) read
|
|
31
|
+
behind a ruling records its mode: `OOB: static` — the diff and source were read and nothing ran — or
|
|
32
|
+
`OOB: executed` — the finding's claim was run against the task's head commit (a test, a reproduction
|
|
33
|
+
or a command) with its exit code and log path on file. Only an executed read backs a waive. A static
|
|
34
|
+
CLEAN never does, however confident: a static read that missed an executed material defect reads
|
|
35
|
+
exactly like one that found nothing, and a static read relabelled `executed` is a false record.
|
|
36
|
+
Replay it before ruling. The reviewer's material finding says a killed taker strands the claim; a
|
|
37
|
+
static OOB read of the diff reports CLEAN; the finding's reproduction, executed at the task head,
|
|
38
|
+
exits 1 with the strand on disk — that static CLEAN would have waived a real defect, so the ruling
|
|
39
|
+
is uphold or recheck. Waive only on a supported executed read: the same reproduction at the task head
|
|
40
|
+
exits 0, its log is on file, and the record names both. The waive keeps its park and gate binding and
|
|
41
|
+
its debt: CURRENT `tickmarkr status <runId>` reads `outstanding 1 (T2 review)` until
|
|
42
|
+
`tickmarkr verify --record <runId>` discharges it. Record example:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
D-NNN WAIVE T2 review — park <line>@<ts> --gate review
|
|
46
|
+
OOB: executed — `<reproduction>` at <task-head-sha>: exit 0, log <path>
|
|
47
|
+
finding: <the reviewer's material claim> — not reproduced by that execution
|
|
48
|
+
debt: outstanding 1 (T2 review) until `tickmarkr verify --record <runId>`
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A record whose OOB line reads `static`, or names no command, exit code and log, funds no waive: the
|
|
52
|
+
ruling is uphold or recheck.
|
|
29
53
|
Manual UI retains the receipt; the daemon-owned board gracefully stands down only its own
|
|
30
54
|
presence before closing its owned pane. Non-TTY supervision keeps `status`, `report` and
|
|
31
55
|
default-watch line output (`--watch --plain` is also available on a TTY). Keep the canonical
|
|
@@ -121,13 +145,13 @@ through brief lineage. **An executor choice nobody made is still an executor cho
|
|
|
121
145
|
tab OVERSEER; create ONE tab ORCHESTRATOR.
|
|
122
146
|
**FIVE-TAB CANON (standing operator layout — corrected three times on 2026-07-27, layout approved
|
|
123
147
|
2026-07-29, re-earned 2026-08-17):**
|
|
124
|
-
- `OVERSEER` — you. Do not add a live run surface here: launch the daemon
|
|
125
|
-
|
|
126
|
-
- `ORCH` — the orchestrator
|
|
148
|
+
- `OVERSEER` — you. Do not add a live run surface here: launch the daemon detached at the ORCH's
|
|
149
|
+
recorded address (the detached launch below); it self-places the shipped board in the ORCH tab.
|
|
150
|
+
- `ORCH` — the orchestrator and the daemon-placed, run-id-pinned shipped board BESIDE it (the daemon itself runs detached, with no pane): the board
|
|
127
151
|
takes the RIGHT half of the tab and the orchestrator's own narration keeps the LEFT half. (It was a
|
|
128
152
|
full-width board above a narration rail until 2026-08-25; the operator changed it, because a task
|
|
129
153
|
table is a few rows and it was spending height it did not need while squeezing the narration.) **Look for that `role: "watch"` pane; never hand-place or hand-roll a live
|
|
130
|
-
run surface. Only the orchestrator
|
|
154
|
+
run surface. Only the orchestrator and board belong here: a work seat NEVER splits into the ORCH tab.** Operator verbatim:
|
|
131
155
|
*"in orch tab should be the orch and the watcher only."* Re-earned 2026-08-17: a planning seat split
|
|
132
156
|
beside the orchestrator, and the operator caught it, again. The daemon owns this vertical stack and
|
|
133
157
|
places it the same way at every terminal width; neither the worker-pane halving floor, nor a
|
|
@@ -147,7 +171,7 @@ through brief lineage. **An executor choice nobody made is still an executor cho
|
|
|
147
171
|
fraction (`ORCH · v1.19 4/5`, updated on every task-done); tickmarkr opens ONE TAB PER TASK, labelled
|
|
148
172
|
with the task id and holding that task's worker plus its judge/review/consult panes (tickmarkr
|
|
149
173
|
updates it). Never long context strings or ✓-chains.
|
|
150
|
-
- **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: Do not load the `herdr` skill and do not map a Herdr workspace. Work from the current Orca terminal context. Keep the overseer in the launching terminal, name it in the same act — `orca terminal rename --terminal "$ORCA_TERMINAL_HANDLE" --title "OVERSEER · <version>"` (tab title; see the seat-name law under Seat-spawn recipes) — and inspect terminals with `orca terminal list --json`. Launch the daemon
|
|
174
|
+
- **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: Do not load the `herdr` skill and do not map a Herdr workspace. Work from the current Orca terminal context. Keep the overseer in the launching terminal, name it in the same act — `orca terminal rename --terminal "$ORCA_TERMINAL_HANDLE" --title "OVERSEER · <version>"` (tab title; see the seat-name law under Seat-spawn recipes) — and inspect terminals with `orca terminal list --json`. Launch the daemon detached at the orchestrator terminal's recorded handle using the detached launch below — no pane of its own; its self-placed watch board stays in the ORCH tab.
|
|
151
175
|
2. **Orchestrator**: First consume a successful `tickmarkr fleet --pick consult` in the seat repository, per the Fleet selection contract below; then launch the returned adapter/model with your agent host.
|
|
152
176
|
- **On herdr (`HERDR_ENV=1`)**: Spawning on current herdr is two-step — the one-shot `agent start --cwd` form was removed in the herdr CLI redesign and now fails with `unknown option` (OBS-138): first create the pane with `herdr tab create --workspace <ws> --cwd <repo> --label "ORCH · <version>"` and parse `result.root_pane.pane_id` from its JSON, then start the agent in it. For Claude Code, use `herdr agent start orchestrator --kind claude --pane <root-pane-id> -- --permission-mode bypassPermissions` (append `--model <picked-model>` after the `--` from the Fleet receipt). For Codex, use `herdr agent start orchestrator --kind codex --pane <root-pane-id> -- --dangerously-bypass-approvals-and-sandbox` (add `--model <picked-model>` from the Fleet receipt). The unsandboxed flag is REQUIRED: codex's `workspace-write` sandbox keeps `.git` refs read-only, so a sandboxed orchestrator's `tickmarkr run` dies at integration-branch creation — do not downgrade it. Workers you never spawn — tickmarkr spawns its own visible worker panes. Auxiliary agents you do spawn (consultants, reviewers, scouts) follow the same forms: never launch a claude session in plan mode or default permission mode for autonomous work — both stall on per-command approval prompts nobody is watching; claude is always `--permission-mode bypassPermissions --settings '{"promptSuggestionEnabled":false}'`. **For a codex consultant, use `-a never --sandbox workspace-write` — NOT `--sandbox read-only`.** ⚠ **`--sandbox read-only` CONTRADICTS this skill's own completion protocol and will hang the seat.** Every seat you spawn is told to deliver an ARTIFACT ending in a terminal MARKER, because that is the only completion signal the artifact watcher can key on (`done` is turn end). A read-only sandbox cannot write that artifact, so codex blocks on `Would you like to make the following edits?` for its OWN report — and the report exists ONLY in the pending edit, so abandoning the prompt destroys the work rather than merely delaying it. Measured 2026-08-28: a consultant spawned `--sandbox read-only` finished a 14,604-byte verdict, sat blocked on the write, and the operator saw the prompt before the supervising tier did. `read-only` is correct ONLY for a seat that writes nothing at all — which, under the artifact+marker rule, is no seat this skill tells you to spawn. When the prompt does appear, answer **"Yes, and don't ask again for these files"** rather than plain yes: plain yes re-blocks on the next write of the same file. **That `--settings` pair is not cosmetic and it is not optional:** claude-code's AUTOSUGGEST renders context-plausible ghost text into an idle seat's prompt line that is BYTE-IDENTICAL to a typed draft in text-format reads (OBS-482), so a supervising tier cannot tell a seat's own unsent work from a rendering artifact without `agent read --format ansi`. Turning the suggester off at spawn removes the ambiguity at its source instead of paying for the discrimination at every read. Verified against the shipped binary: `claude --settings '{"promptSuggestionEnabled":false}' -p …` exits 0 with a real response, and the key appears in the binary's own settings schema. **For kimi, pass `-y`** (`herdr agent start <name> --kind kimi --pane <id> -- -y`) — the adapter already launches its own workers that way (`src/adapters/kimi.ts:204`), and a kimi seat spawned without it sits on an approval prompt having done nothing. **Herdr cannot see that state**: it reports a kimi pane as `agent_status: working` with `screen_detection_skipped: true` while the prompt is up, so the BLOCKED-STATE watcher below is blind on this vendor and the spawn flag is the ONLY control. Every vendor you spawn needs its auto-approve form named here; a vendor absent from this list is a seat that will hang.
|
|
153
177
|
- **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: Seats spawn with `orca terminal create` on a path worktree selector with a command:
|
|
@@ -197,20 +221,20 @@ through brief lineage. **An executor choice nobody made is still an executor cho
|
|
|
197
221
|
The orchestrator's run log, handoff, and plan live inside its sandbox root and are artifacts of that orchestrator.
|
|
198
222
|
The overseer reads them from there, using the path the orchestrator reports; do not substitute the
|
|
199
223
|
overseer's repository or a machine-global planning directory. The orchestrator brief must say: if the seat's
|
|
200
|
-
sandbox denies writes under `.git`, report the denial to the overseer and stop; the overseer launches the daemon itself; use the
|
|
224
|
+
sandbox denies writes under `.git`, report the denial to the overseer and stop; the overseer launches the daemon itself; use the detached launch at the recorded ORCH address, never a pane and never the overseer tab;
|
|
201
225
|
and the daemon host is never sandboxed.
|
|
202
226
|
|
|
203
227
|
**Sandbox-denial daemon launch (OVERSEER):** use the ORCH address recorded at seat creation,
|
|
204
228
|
re-resolved by title if stale; the launching overseer's own terminal is not the target.
|
|
205
229
|
|
|
206
230
|
- **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: record the ORCH's
|
|
207
|
-
`result.terminal.handle` from its seat-create receipt. For the fallback, run
|
|
208
|
-
`
|
|
231
|
+
`result.terminal.handle` from its seat-create receipt. For the fallback, run the detached
|
|
232
|
+
`ORCA_TERMINAL_HANDLE="<ORCH handle>"` line of the detached launch below with that recorded handle.
|
|
209
233
|
Here `$ORCA_TERMINAL_HANDLE` names the OVERSEER's own terminal; use it only when the ORCH
|
|
210
234
|
launches its own daemon, never when the OVERSEER launches on the ORCH's behalf.
|
|
211
235
|
- **On herdr (`HERDR_ENV=1`)**: record the ORCH's `result.root_pane.pane_id` from its tab-create
|
|
212
|
-
receipt. For the fallback,
|
|
213
|
-
|
|
236
|
+
receipt. For the fallback, run the detached `HERDR_PANE_ID="<ORCH pane id>"` line of the detached
|
|
237
|
+
launch below with that recorded ORCH pane id; never target the OVERSEER's pane.
|
|
214
238
|
|
|
215
239
|
The same recorded ORCH address is required for a fallback `tickmarkr resume <runId>`.
|
|
216
240
|
|
|
@@ -308,23 +332,38 @@ For Leg-2 (both hosts), a Codex reviewer under `workspace-write` must be briefed
|
|
|
308
332
|
`<repo>/.tickmarkr/overseer/verdicts/<task>.md`, and its verdict must be written there before it is read.
|
|
309
333
|
## Host-owned daemon and detached beats
|
|
310
334
|
|
|
311
|
-
Launch the daemon
|
|
312
|
-
|
|
313
|
-
|
|
335
|
+
Launch the daemon DETACHED, with no pane of its own: one `tickmarkr run` or `tickmarkr resume <runId>`
|
|
336
|
+
process in its own session, its stdout and stderr appended to `<state-dir>/daemon.log`, and the
|
|
337
|
+
ORCH's recorded address as its board anchor, so the daemon self-places its one board beside the
|
|
338
|
+
ORCH in the ORCH tab. Never launch it in a visible split, pane or tab, as an agent harness
|
|
339
|
+
background task, or tied to an agent session: the launching shell may end, and the daemon keeps
|
|
340
|
+
running and logging. The detach wrapper is `node`, which tickmarkr already requires — no private
|
|
341
|
+
script, no extra visible daemon pane and no CLI log flag:
|
|
314
342
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
343
|
+
```bash
|
|
344
|
+
# On Orca: <ORCH handle> is the ORCH terminal handle
|
|
345
|
+
cd <repo> && ORCA_TERMINAL_HANDLE="<ORCH handle>" node -e "require('child_process').spawn(process.argv[1], process.argv.slice(2), { detached: true, stdio: 'inherit' }).unref()" tickmarkr run >> <state-dir>/daemon.log 2>&1 < /dev/null
|
|
346
|
+
cd <repo> && ORCA_TERMINAL_HANDLE="<ORCH handle>" node -e "require('child_process').spawn(process.argv[1], process.argv.slice(2), { detached: true, stdio: 'inherit' }).unref()" tickmarkr resume <runId> >> <state-dir>/daemon.log 2>&1 < /dev/null
|
|
347
|
+
# On herdr: <ORCH pane id> is the ORCH pane id
|
|
348
|
+
cd <repo> && HERDR_PANE_ID="<ORCH pane id>" node -e "require('child_process').spawn(process.argv[1], process.argv.slice(2), { detached: true, stdio: 'inherit' }).unref()" tickmarkr run >> <state-dir>/daemon.log 2>&1 < /dev/null
|
|
349
|
+
cd <repo> && HERDR_PANE_ID="<ORCH pane id>" node -e "require('child_process').spawn(process.argv[1], process.argv.slice(2), { detached: true, stdio: 'inherit' }).unref()" tickmarkr resume <runId> >> <state-dir>/daemon.log 2>&1 < /dev/null
|
|
350
|
+
```
|
|
323
351
|
|
|
324
|
-
|
|
325
|
-
`
|
|
326
|
-
|
|
327
|
-
|
|
352
|
+
- **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: run the
|
|
353
|
+
`ORCA_TERMINAL_HANDLE` lines. Only when the ORCH
|
|
354
|
+
launches its own daemon is `<ORCH handle>` its own `$ORCA_TERMINAL_HANDLE`. When the OVERSEER
|
|
355
|
+
launches the sandbox-denial fallback, substitute the ORCH handle recorded
|
|
356
|
+
at seat creation; the OVERSEER's own `$ORCA_TERMINAL_HANDLE` would put the board in its tab.
|
|
357
|
+
- **On herdr (`HERDR_ENV=1`)**: run the `HERDR_PANE_ID` lines; `<ORCH pane id>` is the ORCH's own
|
|
358
|
+
`$HERDR_PANE_ID`. When the OVERSEER launches the fallback, substitute the ORCH pane id recorded
|
|
359
|
+
at seat creation, never the OVERSEER's pane.
|
|
360
|
+
|
|
361
|
+
After either launch, read this repository's lock pid from `<state-dir>/graph.lock` and confirm it:
|
|
362
|
+
`kill -0 <pid>` succeeds, `ps -o pgid= -p <pid>` prints that same pid (its own session group;
|
|
363
|
+
ppid 1 is never proof on its own), walk its ppid chain and verify no agent session is an ancestor,
|
|
364
|
+
and read `<state-dir>/daemon.log`. No live holder means the launch failed: read the log, fix the
|
|
365
|
+
cause and run the same line again — never a second daemon beside a live holder, and never a
|
|
366
|
+
visible split to watch it; the daemon-placed board is the live surface.
|
|
328
367
|
|
|
329
368
|
Detached beats are product-owned, one per (tier, seat), from the repository root, through the
|
|
330
369
|
shipped lifecycle verbs — never a hand-rolled setsid plus nohup wrapper, pidfile or shell loop:
|
|
@@ -346,6 +385,34 @@ generation and identity still match, and reads back DISARMED. Never put beats in
|
|
|
346
385
|
background task or a visible tab. Include a run-end `beat stop` item for every beat started, also
|
|
347
386
|
on failure, park or handoff, and require its DISARMED read-back.
|
|
348
387
|
|
|
388
|
+
**Legacy beat migration.** `beat start` refuses a legacy (pre-lifecycle, unowned) arm nonzero and
|
|
389
|
+
prints its exit under the RECORDED seat; `beat stop` refuses it too, so a stop followed by a start
|
|
390
|
+
is a dead end, never a migration. When the refusal names `stop pid <N> first`, that pid is the old
|
|
391
|
+
`--loop` writer: stop exactly that pid yourself (`kill <N>`, then confirm `kill -0 <N>` fails) —
|
|
392
|
+
tickmarkr never signals a process it did not launch. Then run the printed step under the seat it
|
|
393
|
+
names, start again and read back ARMED:
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
cd <repo> && tickmarkr beat <tier> --seat <recorded seat> --stand-down
|
|
397
|
+
cd <repo> && tickmarkr beat start <tier> --seat <seat>
|
|
398
|
+
cd <repo> && tickmarkr beat status <tier> --seat <seat>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Crash recovery.** A crashed owner, a writer killed inside its claimed tick or a killed recovery
|
|
402
|
+
taker leaves its claim, removal lock or stage directory behind. `beat status` only observes: it
|
|
403
|
+
exits nonzero, names the dead pids, prints the command that recovers them and changes no file —
|
|
404
|
+
status never recovers. Run the command it prints; the next ordinary `stop` or `start` recovers what
|
|
405
|
+
was left, with a notice naming each dead pid, and the start reads back ARMED:
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
cd <repo> && tickmarkr beat status <tier> --seat <seat>
|
|
409
|
+
cd <repo> && tickmarkr beat stop <tier> --seat <seat>
|
|
410
|
+
cd <repo> && tickmarkr beat start <tier> --seat <seat>
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Never delete a claim, lock or stage file by hand. A live or unprovable holder refuses BUSY naming
|
|
414
|
+
it: wait for that holder to finish or exit, then run the same command.
|
|
415
|
+
|
|
349
416
|
Keep only watchers that must WAKE the seat in the harness. Re-arm them on each wake and at
|
|
350
417
|
their harness cap; daemon and beat lifetimes must not depend on that cap.
|
|
351
418
|
|
|
@@ -461,8 +528,9 @@ journal tail to decide what happens next, or sweeping orphans — you have taken
|
|
|
461
528
|
ensure it is re-armed at most every twenty minutes. Never rely on a `Monitor`-only wake.
|
|
462
529
|
- **On herdr (`HERDR_ENV=1`)**: Use the shipped journal instruments:
|
|
463
530
|
**All four are covered by one shipped instrument** — `scripts/watch-journal.sh <runs-dir> [poll] [cap]
|
|
464
|
-
[events-csv]` — which arms on a line baseline, wakes once, and grades a `run-end`
|
|
465
|
-
|
|
531
|
+
[events-csv]` — which arms on a line baseline, wakes once, and grades a `run-end`'s execution clauses —
|
|
532
|
+
`EXECUTION COMPLETE` or `NOT GREEN`, never green: green is CURRENT `tickmarkr status <runId>` at
|
|
533
|
+
`outstanding 0`. `scripts/watch-parks.sh` stays the park-specific wake for THIS seat (it counts parks and speaks
|
|
466
534
|
about rulings); the two overlap on `task-human` deliberately, and arming both is coverage, not a bug.
|
|
467
535
|
- **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: Arm a file/journal consumer for the same terminal events and inspect the seat with `orca terminal read --terminal <handle> --screen --json`; re-arm after every wake.
|
|
468
536
|
- **Daemon liveness ≠ journal activity.** A dead daemon emits no events, so journal watchers sleep through
|
|
@@ -1194,7 +1262,8 @@ wrote, so a stray shell loop left running by a predecessor seat kept a stood-dow
|
|
|
1194
1262
|
shell or not, never does. The pre-2.1.3 forms `while :; do tickmarkr beat overseer; sleep 10; done`
|
|
1195
1263
|
and `tickmarkr beat overseer --stand-down` are preserved here only as older migration warnings: both
|
|
1196
1264
|
are now rejected outright because neither declares which seat the tier speaks for. Do not copy or
|
|
1197
|
-
run either legacy form.
|
|
1265
|
+
run either legacy form. To leave an arm a legacy writer left, run the **Legacy beat migration** steps in Host-owned
|
|
1266
|
+
daemon and detached beats: the printed `--stand-down` under the recorded seat, then `beat start`.
|
|
1198
1267
|
|
|
1199
1268
|
One beat per LIVE PROCESS, deliberately: `--loop`'s recorded pid is that process's own, so the tier's
|
|
1200
1269
|
liveness is exactly as verifiable as the process table — stop the loop, or let it die, and the
|
|
@@ -82,19 +82,21 @@ report() {
|
|
|
82
82
|
done=$(bucket done "$line"); failed=$(bucket failed "$line")
|
|
83
83
|
human=$(bucket human "$line"); blocked=$(bucket blocked "$line")
|
|
84
84
|
pending=$(bucket pending "$line")
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
85
|
+
# NO RUN-END RECORD CERTIFIES GREEN. "run-end plus tip verify" passes a run that ended
|
|
86
|
+
# `done=[T1,T3,T4] human=[T2]` — three delivered, one PARKED — and even empty buckets leave the debt
|
|
87
|
+
# clause open: a waived review is still owed (D-660), and a `verify --record` discharge that lands
|
|
88
|
+
# AFTER run-end moves only CURRENT status. This row is history, so the best it can say is
|
|
89
|
+
# EXECUTION COMPLETE; green is read from CURRENT `tickmarkr status <runId>` at `outstanding 0`.
|
|
88
90
|
if [ "$tv" != "failed" ] && [ -z "$failed$human$blocked$pending" ]; then
|
|
89
|
-
verdict="
|
|
91
|
+
verdict="EXECUTION COMPLETE"
|
|
90
92
|
else
|
|
91
93
|
verdict="NOT GREEN"
|
|
92
94
|
fi
|
|
93
95
|
echo "RUN_END $run — $verdict (tipVerify=${tv:-unknown})"
|
|
94
96
|
echo " done=[${done}] failed=[${failed}] human=[${human}] blocked=[${blocked}] pending=[${pending}]"
|
|
95
|
-
[ "$verdict" = "
|
|
96
|
-
&& echo "
|
|
97
|
-
|| echo " a non-empty bucket above is the reason; name it, never report this run as green"
|
|
97
|
+
[ "$verdict" = "EXECUTION COMPLETE" ] \
|
|
98
|
+
&& echo " execution buckets empty and tip verify is not failed — not yet green: read CURRENT \`tickmarkr status $run\`; only \`outstanding 0\` is green, \`outstanding N (...)\` and \`outstanding unknown\` are not, and this run-end record's own count is historical" \
|
|
99
|
+
|| echo " a non-empty bucket or a failed tip above is the reason; name it, never report this run as green"
|
|
98
100
|
;;
|
|
99
101
|
task-human)
|
|
100
102
|
echo "TASK_HUMAN $(field taskId "$line") — $run"
|