tickmarkr 2.8.7 → 2.8.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.
@@ -48,12 +48,42 @@ export function classifyRepairDisposition(input) {
48
48
  return { paths: r.resolved.filter((path) => !allowed(path)), diagnostics: r.diagnostics };
49
49
  };
50
50
  const owned = (text) => resolveScopeHints(namedPaths(text), inventory).resolved.some(allowed);
51
+ // Queue row 235 (D-2134): acceptance prose quotes declarations; only execution and typed evidence
52
+ // attribute a repair. A misplaced declared landing is authoritative even when it was never written.
53
+ const acceptanceEvidence = (g) => {
54
+ if (Array.isArray(g.meta?.oracles)) {
55
+ const paths = [];
56
+ const landings = [];
57
+ for (const oracle of g.meta.oracles) {
58
+ if (!oracle || typeof oracle !== "object")
59
+ continue;
60
+ if (typeof oracle.output === "string")
61
+ paths.push(...namedPaths(oracle.output));
62
+ if (["absent", "elsewhere", "untitled"].includes(oracle.failure) && typeof oracle.landing === "string" && !allowed(oracle.landing)) {
63
+ landings.push(oracle.landing);
64
+ }
65
+ }
66
+ return { paths, landings };
67
+ }
68
+ const judgment = g.meta?.judgment;
69
+ const criteria = Array.isArray(judgment) ? judgment
70
+ : judgment && typeof judgment === "object" && "criteria" in judgment ? judgment.criteria : undefined;
71
+ const paths = Array.isArray(criteria) ? criteria.flatMap((row) => row?.met === false && Array.isArray(row.paths) ? row.paths.filter((path) => typeof path === "string") : []) : [];
72
+ return { paths, landings: [] };
73
+ };
51
74
  const refusal = input.refusalSummary !== undefined && REFUSAL_RE.test(input.refusalSummary)
52
75
  ? unowned(input.refusalSummary) : { paths: [], diagnostics: [] };
53
76
  // A test gate names where the ASSERTION lives — a detection site, not the code that needs fixing.
54
77
  const sites = reds.filter((g) => g.gate === "test").map((g) => unowned(g.details));
55
78
  const others = reds.filter((g) => g.gate !== "test");
56
- const hints = others.map((g) => unowned(g.details));
79
+ const evidence = others.map((g) => g.gate === "acceptance" ? acceptanceEvidence(g) : undefined);
80
+ const hints = others.map((g, i) => {
81
+ const e = evidence[i];
82
+ if (!e)
83
+ return unowned(g.details);
84
+ const r = resolveScopeHints(e.paths.filter((path) => !allowed(path)), inventory);
85
+ return { paths: [...e.landings, ...r.resolved.filter((path) => !allowed(path))], diagnostics: r.diagnostics };
86
+ });
57
87
  const diagnostics = [refusal, ...sites, ...hints].flatMap((r) => r.diagnostics)
58
88
  .filter((d, i, all) => all.findIndex((o) => o.candidate === d.candidate) === i);
59
89
  const uniq = (rs) => [...new Set(rs.flatMap((r) => r.paths))].sort();
@@ -62,7 +92,8 @@ export function classifyRepairDisposition(input) {
62
92
  reason: `worker refusal names unowned paths: ${refusal.paths.join(", ")}` };
63
93
  }
64
94
  const repair = uniq(hints);
65
- if (repair.length && !others.some((g) => owned(g.details))) {
95
+ if (repair.length && !others.some((g, i) => evidence[i]
96
+ ? resolveScopeHints(evidence[i].paths, inventory).resolved.some(allowed) : owned(g.details))) {
66
97
  const review = others.some((g) => g.gate === "review");
67
98
  return { kind: review ? "scope-request" : "authoring", paths: repair, source: others[0].gate, diagnostics,
68
99
  reason: `files[] repair hint: ${repair.join(", ")}` };
@@ -21,8 +21,9 @@ const bucketOf = (gate) => gate === "test" ? "test" : gate === "acceptance" || g
21
21
  // Rows another process writes around a restart — the operator's approval, the resuming daemon's
22
22
  // reclaim and rehash audit — so the prior engagement's own last row is the one before them.
23
23
  // ponytail: a closed list; a new out-of-engagement writer lengthens the interruption it precedes.
24
- const OUTSIDE_ENGAGEMENT = new Set(["task-approved", "graph-rehash", "lock-reclaimed", "superseded"]);
25
- const outsideEngagement = (e) => OUTSIDE_ENGAGEMENT.has(e.event) || (e.event === "exit-cause" && e.data.cause === "unclean");
24
+ const OUTSIDE_ENGAGEMENT = new Set(["task-approved", "graph-rehash", "lock-reclaimed", "superseded", "worktree-removed", "worktree-removal-failed"]);
25
+ const outsideEngagement = (e) => OUTSIDE_ENGAGEMENT.has(e.event) || (e.event === "worktree-preserved" && e.data.by !== undefined)
26
+ || (e.event === "exit-cause" && e.data.cause === "unclean");
26
27
  const WORKER_END = new Set(["worker-result", "worker-dead", "worker-hard-timeout"]);
27
28
  const invocationOf = (data) => {
28
29
  if (typeof data.nonce === "string")
@@ -39,8 +40,11 @@ export function wallBudget(events) {
39
40
  const lastEnd = lastOf("run-end");
40
41
  const lastResume = lastOf("run-resume");
41
42
  const from = at(events[first]);
42
- // A closed engagement ends at its run-end; an open or crashed one at its newest row.
43
- const to = at(events[lastEnd > lastResume ? lastEnd : events.length - 1]);
43
+ // Queue row 240 (D-2138): cleanup by another daemon cannot lengthen an open or crashed engagement.
44
+ let newestInside = events.length - 1;
45
+ while (newestInside > first && outsideEngagement(events[newestInside]))
46
+ newestInside--;
47
+ const to = at(events[lastEnd > lastResume ? lastEnd : newestInside]);
44
48
  if (!Number.isFinite(from) || !Number.isFinite(to) || to < from)
45
49
  return undefined;
46
50
  const spans = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tickmarkr",
3
- "version": "2.8.7",
3
+ "version": "2.8.9",
4
4
  "description": "Spec in, verified work out.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,7 +26,7 @@ When working in a multi-agent terminal environment (herdr or Orca), decide your
26
26
 
27
27
  - **Orchestrator:** your session was started to execute the mission. Rename your own tab/pane `ORCH · <label>` (short labels: ≤20 chars, `ROLE · token`) and run the loop below.
28
28
  - **Supervisor with a live orchestrator:** do not start a second run. Relay the mission to the existing orchestrator with a [verified handoff](#verified-handoffs-agent-to-agent-messaging), then supervise it as OVERSEER.
29
- - **Primary session without an orchestrator:** rename your own tab `OVERSEER · <label>` and your agent `overseer`, spawn one child orchestration session with your host's launch form, label its tab `ORCH · <label>` and name its agent, give it the mission and these rules verbatim, then supervise it. Do not drive a duplicate single-tier run yourself. Before spawning, confirm any PREVIOUS orchestrator has stood down (monitors stopped, input box empty — dim ghost-text suggestions are UI, not queued input; ANSI-verify before alarming) and close its tab — the journal, records, and ledger hold the story; scrollback is disposable.
29
+ - **Primary session without an orchestrator:** rename your own tab `OVERSEER · <label>` and your agent `overseer`, spawn one child orchestration session with your host's launch form, label its tab `ORCH · <label>` and name its agent, give it the mission and these rules verbatim, then supervise it. Do not drive a duplicate single-tier run yourself. Before spawning, retire any PREVIOUS orchestrator through [mission-end teardown](#mission-end-teardown-queue-row-240-d-2138-add1-r3-add4).
30
30
  - **On herdr (`HERDR_ENV=1`)**: **spawning on current herdr is two-step** — the one-shot `agent start --cwd/--tab/--no-focus` form was removed in the herdr CLI redesign and now fails with `unknown option` (OBS-138). First create the pane: `herdr tab create --workspace <ws> --cwd <repo> --label "ORCH · <label>"` (tab create does not steal focus unless `--focus` is passed; parse `result.root_pane.pane_id` from its JSON), then start the agent in it:
31
31
  - **Claude Code:** `herdr agent start orchestrator --kind claude --pane <root-pane-id> -- --permission-mode bypassPermissions`
32
32
  - **Codex:** `herdr agent start orchestrator --kind codex --pane <root-pane-id> -- --dangerously-bypass-approvals-and-sandbox` — the unsandboxed flag is REQUIRED, not optional: codex's `workspace-write` sandbox keeps `.git` refs read-only, so a sandboxed orchestrator's `tickmarkr run` dies at integration-branch creation (`git worktree add` cannot lock the ref). Do not downgrade this flag; the herdr pane and repo scope are the containment.
@@ -69,7 +69,62 @@ agent session that owns no panes (queue row 192; D-2102). The role check above d
69
69
 
70
70
  ## Stand-down (mission end and retirement)
71
71
 
72
- On each mission's terminal state, after the record commit and operator notification: the orchestrator stops every monitor and background task it started, sweeps the heartbeat/beat files its watchers wrote (a stale beat beside a live one reads as coverage to whoever globs the directory), prints one final stand-down line, and leaves nothing queued in its input box. A finished session with an armed watcher or pre-filled input is a loaded gun.
72
+ At each terminal state (green, failed, or parked), finish the execution record beside the source spec.
73
+ The ORCH's artifact is this execution record. Append its named terminal marker BEFORE the record commit
74
+ (queue row 240; D-2138 add.1 R3): `printf '\n<!-- tickmarkr:orch-end %s -->\n' "<runId>" >> "<execution-record>"`.
75
+ Verify the final line is `<!-- tickmarkr:orch-end <runId> -->`, then commit that record when tracked
76
+ and notify the operator. Stop every monitor and background task you started, sweep your watcher
77
+ heartbeat/beat files, print a final stand-down line, and leave nothing queued in your input box.
78
+ After that stand-down, write `pids/<seat>.stood-down` with `mission=<mission>` as the brief requires.
79
+ The supervisor reads back the stand-down and exactly that execution record's end marker, then closes
80
+ the retired ORCH at its recorded address using the host's exact command and ownership proof below;
81
+ a plain host has no spawned terminal to close. Ghost-text suggestions are UI, not queued input.
82
+
83
+ ## Mission-end teardown (queue row 240; D-2138 add.1 R3, add.4)
84
+
85
+ **The spawner closes the seat it created.** Manual closes and watcher closes follow this same law:
86
+ close only once its artifact and terminal marker are on disk, its stand-down is read back, and no
87
+ next mission is named for it. An agent's `done` signal, a bare handle, or a title alone is never enough.
88
+ The ORCH's artifact is the execution record ending in `<!-- tickmarkr:orch-end <runId> -->`;
89
+ the supervisor reads exactly that record and that run's marker before retiring the orchestrator.
90
+ Keep a reused seat only with its next mission named and a `/clear` at the mission boundary.
91
+ Keep the latest settled consult round only while the mission continues; at mission end apply this
92
+ same close or reuse rule. A dedicated consultant tab may outlive the orchestrator tab during that
93
+ continuing mission, never indefinitely after the mission ends.
94
+
95
+ **Record ownership at spawn**, beside watcher pids under `<state-dir>/overseer/pids/<seat>.handle`:
96
+ write `host`, `address`, `title`, `checkout`, and `mission`, one `key=value` per line, from the create
97
+ receipt; use the actual tab title and checkout. This is the spawn ledger, not a list reconstructed
98
+ from titles. Record an owned tab as `tab=<tab-id>` when the seat owns it. Every spawned seat's brief
99
+ ends with: after stand-down, write `pids/<seat>.stood-down` containing `mission=<mission>`.
100
+ On every new assignment, including named-next-mission reuse, rewrite the ledger's `mission` and
101
+ delete the old stood-down file BEFORE that mission starts (D-2138 add.6 V01). Read back the stood-down
102
+ file and require its mission to equal the ledger's current mission; an earlier mission's stand-down
103
+ never retires the reused seat.
104
+
105
+ **Before every close, first match the spawn record against the live tab title and checkout**, at its
106
+ recorded address. A mismatch closes nothing. Never close a tab you did not create, a recycled handle
107
+ now showing an operator's terminal, a seat matched by title alone, or your own launching terminal.
108
+ A stale or mismatched Orca handle permits read-only re-resolution by title and checkout to read the
109
+ seat; never close the replacement by title, never rewrite ownership from a title-only match.
110
+
111
+ - **On herdr (`HERDR_ENV=1`)**: verify `herdr pane list`: the recorded address equals `pane_id`,
112
+ the recorded title equals `label`, and the recorded checkout equals `cwd` (filesystem identity).
113
+ Only then use `herdr pane close <pane>` at the recorded address. Prove the pane absent from
114
+ `herdr pane list`; for a seat owning its tab, use `herdr tab close <tab>` at its recorded tab id
115
+ after the final owned pane closes, and prove the tab absent from `herdr tab list`. A shared tab
116
+ with a pending sibling stays open. Never assume emptied tabs disappear without checking.
117
+ - **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: verify ownership with
118
+ `orca terminal list --include-visual-layouts --json`: the spawn record's address is the leaf handle,
119
+ its title is the live TAB title (never the shell's pane title), and its checkout matches the layout
120
+ worktree and terminal row. An unbound checkout or truncated listing is unverifiable and closes nothing.
121
+ Only then use `orca terminal close --terminal <handle> --json` with the recorded handle. Require
122
+ `result.close.handle` equal to that handle, or the documented live-terminal refusal
123
+ `ok:false`, `error.code:runtime_error`, `error.message:tab_not_found` from that same runtime.
124
+ Prove the handle absent from `orca terminal list --json` AND its owned tab absent from
125
+ `orca terminal list --include-visual-layouts --json` after its final terminal closes, in the same
126
+ runtime as the pre-close listing. A surviving owned tab is a spec question, never permission to
127
+ close by title. The Orca smoke e2e asserts this tab leg; a receipt alone is no close proof.
73
128
 
74
129
  ## Invariants
75
130
 
@@ -132,7 +187,7 @@ Never report "briefed" or "relayed" without the confirmation your host gives:
132
187
  - **On herdr (`HERDR_ENV=1`)**: the consumer is the shipped watcher — `.claude/skills/tickmarkr-overseer/scripts/watch-journal.sh <state-dir>/runs 20 28800`, which grades the run-end summary's execution clauses for you, `EXECUTION COMPLETE` or `NOT GREEN`, never green — or a foreground `until grep` on the run's terminal events; ensure it is re-armed at most every twenty minutes.
133
188
  - **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: the consumer is that same shipped journal watcher or a foreground `until grep` on the run's terminal events; ensure it is re-armed at most every twenty minutes.
134
189
  5. **Verify and consolidate** — continue only after a green run. A run is green when the run-end event exists in the journal, the tip verify is not "failed", the summary's `failed`, `human`, `blocked` and `pending` buckets are all empty, and CURRENT `tickmarkr status <runId>` reads its owed checks outstanding empty AND known (`outstanding 0`) — a run with a parked task is partial, not green. Empty execution buckets alone are not green either (D-660): every bucket empty and the tip passed, but an operator waived one review, leaves one accepted-risk review check owed — status reads `outstanding 1 (T7 review)` and `run`/`resume` still exit 0 on execution alone, so the run is execution complete, not green. It turns green only when a `tickmarkr verify --record <runId>` discharge moves CURRENT status to `outstanding 0`, including a discharge landing after run-end — the historical run-end record keeps the old count, so never read debt from it; `outstanding unknown` is never green. Tickmarkr consolidates accepted work on `tickmarkr/<runId>` and never signs off to the main branch. A human controls any later release merge.
135
- 6. **Record** — `tickmarkr report <runId> --md` prints Markdown to stdout; redirect explicitly beside the spec (for example `tickmarkr report <runId> --md > feature.record.md`) and commit the execution record when the repository tracks those records.
190
+ 6. **Record** — `tickmarkr report <runId> --md` prints Markdown to stdout; redirect explicitly beside the spec (for example `tickmarkr report <runId> --md > feature.record.md`) then follow [stand-down](#stand-down-mission-end-and-retirement) to append the ORCH end marker before committing the execution record when tracked.
136
191
  7. **Continue** — move to the next requested target. If a target fails or is parked, stop with the journal evidence rather than silently skipping it.
137
192
 
138
193
  ## Host-owned daemon and detached beats
@@ -15,7 +15,7 @@ When working in a multi-agent terminal environment (herdr or Orca), decide your
15
15
 
16
16
  - **Orchestrator:** your session was started to execute the mission. Rename your own tab/pane `ORCH · <label>` (short labels: ≤20 chars, `ROLE · token`) and run the loop below.
17
17
  - **Supervisor with a live orchestrator:** do not start a second run. Relay the mission to the existing orchestrator with a [verified handoff](#verified-handoffs-agent-to-agent-messaging), then supervise it as OVERSEER.
18
- - **Primary session without an orchestrator:** rename your own tab `OVERSEER · <label>` and your agent `overseer`, spawn one child orchestration session with your host's launch form, label its tab `ORCH · <label>` and name its agent, give it the mission and these rules verbatim, then supervise it. Do not drive a duplicate single-tier run yourself. Before spawning, confirm any PREVIOUS orchestrator has [stood down](#stand-down-mission-end-and-retirement) and close its tab.
18
+ - **Primary session without an orchestrator:** rename your own tab `OVERSEER · <label>` and your agent `overseer`, spawn one child orchestration session with your host's launch form, label its tab `ORCH · <label>` and name its agent, give it the mission and these rules verbatim, then supervise it. Do not drive a duplicate single-tier run yourself. Before spawning, retire any PREVIOUS orchestrator through [mission-end teardown](#mission-end-teardown-queue-row-240-d-2138-add1-r3-add4).
19
19
  - **On herdr (`HERDR_ENV=1`)**: **spawning on current herdr is two-step** — the one-shot `agent start --cwd/--tab/--no-focus` form was removed in the herdr CLI redesign and now fails with `unknown option` (OBS-138). First create the pane: `herdr tab create --workspace <ws> --cwd <repo> --label "ORCH · <label>"` (tab create does not steal focus unless `--focus` is passed; parse `result.root_pane.pane_id` from its JSON), then start the agent in it:
20
20
  - **Claude Code:** `herdr agent start orchestrator --kind claude --pane <root-pane-id> -- --permission-mode bypassPermissions`
21
21
  - **Codex:** `herdr agent start orchestrator --kind codex --pane <root-pane-id> -- --dangerously-bypass-approvals-and-sandbox` — the unsandboxed flag is REQUIRED, not optional: codex's `workspace-write` sandbox keeps `.git` refs read-only, so a sandboxed orchestrator's `tickmarkr run` dies at integration-branch creation (`git worktree add` cannot lock the ref). Do not downgrade this flag; the herdr pane and repo scope are the containment.
@@ -111,12 +111,66 @@ Never report "briefed" or "relayed" without the confirmation your host gives:
111
111
 
112
112
  ## Dedicated consultant tab rule
113
113
 
114
- When spawning consultants (agents gathering synthesis input for decisions like SCOPER analysis or architectural reviews), create them in a DEDICATED tab separate from the ORCHESTRATOR tab. This ensures that when the orchestrator stands down, the consultant panes persist and their assessments remain available for review and reference.
114
+ When spawning consultants (agents gathering synthesis input for decisions like SCOPER analysis or architectural reviews), create them in a DEDICATED tab separate from the ORCHESTRATOR tab. The dedicated consultant tab persists beyond an orchestrator retirement only while the mission continues; keep the latest settled round during that mission, then apply mission-end teardown to close or reuse it (queue row 240; D-2138 add.1 R3).
115
115
 
116
116
  ## Stand-down (mission end and retirement)
117
117
 
118
- - **Orchestrator, on terminal state** (green, failed, or parked), after the record commit and operator notification: stop every monitor and background task you started, sweep the heartbeat/beat files your watchers wrote (a stale beat beside a live one reads as coverage to whoever globs the directory), print one final stand-down line, and leave NOTHING queued in your input box. A finished session with an armed watcher or pre-filled input is a loaded gun — a retired v1.40 orchestrator sat idle with "merge … tag, publish" unsent in its input; one stray Enter would have shipped a duplicate release.
119
- - **Supervisor, when a mission completes** (and always before spawning the next orchestrator): verify the orchestrator stood down, then close its tab. Seeming input-box text in a retired pane can be the TUI's dim ghost-text suggestion, not queued input — confirm with an ANSI read (dim escape around the text) or type-one-char-and-read-back before treating it as the loaded gun; close the tab either way. The journal, execution record, OBS ledger, and memory hold the story; pane scrollback is disposable. Never leave a retired agent idle with watchers armed.
118
+ At each terminal state (green, failed, or parked), finish the execution record beside the source spec.
119
+ The ORCH's artifact is this execution record. Append its named terminal marker BEFORE the record commit
120
+ (queue row 240; D-2138 add.1 R3): `printf '\n<!-- tickmarkr:orch-end %s -->\n' "<runId>" >> "<execution-record>"`.
121
+ Verify the final line is `<!-- tickmarkr:orch-end <runId> -->`, then commit that record when tracked
122
+ and notify the operator. Stop every monitor and background task you started, sweep your watcher
123
+ heartbeat/beat files, print a final stand-down line, and leave nothing queued in your input box.
124
+ After that stand-down, write `pids/<seat>.stood-down` with `mission=<mission>` as the brief requires.
125
+ The supervisor reads back the stand-down and exactly that execution record's end marker, then closes
126
+ the retired ORCH at its recorded address using the host's exact command and ownership proof below;
127
+ a plain host has no spawned terminal to close. Ghost-text suggestions are UI, not queued input.
128
+
129
+ ## Mission-end teardown (queue row 240; D-2138 add.1 R3, add.4)
130
+
131
+ **The spawner closes the seat it created.** Manual closes and watcher closes follow this same law:
132
+ close only once its artifact and terminal marker are on disk, its stand-down is read back, and no
133
+ next mission is named for it. An agent's `done` signal, a bare handle, or a title alone is never enough.
134
+ The ORCH's artifact is the execution record ending in `<!-- tickmarkr:orch-end <runId> -->`;
135
+ the supervisor reads exactly that record and that run's marker before retiring the orchestrator.
136
+ Keep a reused seat only with its next mission named and a `/clear` at the mission boundary.
137
+ Keep the latest settled consult round only while the mission continues; at mission end apply this
138
+ same close or reuse rule. A dedicated consultant tab may outlive the orchestrator tab during that
139
+ continuing mission, never indefinitely after the mission ends.
140
+
141
+ **Record ownership at spawn**, beside watcher pids under `<state-dir>/overseer/pids/<seat>.handle`:
142
+ write `host`, `address`, `title`, `checkout`, and `mission`, one `key=value` per line, from the create
143
+ receipt; use the actual tab title and checkout. This is the spawn ledger, not a list reconstructed
144
+ from titles. Record an owned tab as `tab=<tab-id>` when the seat owns it. Every spawned seat's brief
145
+ ends with: after stand-down, write `pids/<seat>.stood-down` containing `mission=<mission>`.
146
+ On every new assignment, including named-next-mission reuse, rewrite the ledger's `mission` and
147
+ delete the old stood-down file BEFORE that mission starts (D-2138 add.6 V01). Read back the stood-down
148
+ file and require its mission to equal the ledger's current mission; an earlier mission's stand-down
149
+ never retires the reused seat.
150
+
151
+ **Before every close, first match the spawn record against the live tab title and checkout**, at its
152
+ recorded address. A mismatch closes nothing. Never close a tab you did not create, a recycled handle
153
+ now showing an operator's terminal, a seat matched by title alone, or your own launching terminal.
154
+ A stale or mismatched Orca handle permits read-only re-resolution by title and checkout to read the
155
+ seat; never close the replacement by title, never rewrite ownership from a title-only match.
156
+
157
+ - **On herdr (`HERDR_ENV=1`)**: verify `herdr pane list`: the recorded address equals `pane_id`,
158
+ the recorded title equals `label`, and the recorded checkout equals `cwd` (filesystem identity).
159
+ Only then use `herdr pane close <pane>` at the recorded address. Prove the pane absent from
160
+ `herdr pane list`; for a seat owning its tab, use `herdr tab close <tab>` at its recorded tab id
161
+ after the final owned pane closes, and prove the tab absent from `herdr tab list`. A shared tab
162
+ with a pending sibling stays open. Never assume emptied tabs disappear without checking.
163
+ - **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: verify ownership with
164
+ `orca terminal list --include-visual-layouts --json`: the spawn record's address is the leaf handle,
165
+ its title is the live TAB title (never the shell's pane title), and its checkout matches the layout
166
+ worktree and terminal row. An unbound checkout or truncated listing is unverifiable and closes nothing.
167
+ Only then use `orca terminal close --terminal <handle> --json` with the recorded handle. Require
168
+ `result.close.handle` equal to that handle, or the documented live-terminal refusal
169
+ `ok:false`, `error.code:runtime_error`, `error.message:tab_not_found` from that same runtime.
170
+ Prove the handle absent from `orca terminal list --json` AND its owned tab absent from
171
+ `orca terminal list --include-visual-layouts --json` after its final terminal closes, in the same
172
+ runtime as the pre-close listing. A surviving owned tab is a spec question, never permission to
173
+ close by title. The Orca smoke e2e asserts this tab leg; a receipt alone is no close proof.
120
174
 
121
175
  ## The loop
122
176
 
@@ -127,7 +181,7 @@ When spawning consultants (agents gathering synthesis input for decisions like S
127
181
  - **On herdr (`HERDR_ENV=1`)**: the consumer is the shipped watcher — `.claude/skills/tickmarkr-overseer/scripts/watch-journal.sh <state-dir>/runs 20 28800`, which grades the run-end summary's execution clauses for you, `EXECUTION COMPLETE` or `NOT GREEN`, never green — or a foreground `until grep` on the run's terminal events; ensure it is re-armed at most every twenty minutes.
128
182
  - **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: the consumer is that same shipped journal watcher or a foreground `until grep` on the run's terminal events; ensure it is re-armed at most every twenty minutes.
129
183
  5. **Verify and consolidate** — accept only a green run. A run is green when the run-end event exists in the journal, the tip verify is not "failed", the summary's `failed`, `human`, `blocked` and `pending` buckets are all empty, and CURRENT `tickmarkr status <runId>` reads its owed checks outstanding empty AND known (`outstanding 0`) — a run with a parked task is partial, not green. Empty execution buckets alone are not green either (D-660): every bucket empty and the tip passed, but an operator waived one review, leaves one accepted-risk review check owed — status reads `outstanding 1 (T7 review)` and `run`/`resume` still exit 0 on execution alone, so the run is execution complete, not green. It turns green only when a `tickmarkr verify --record <runId>` discharge moves CURRENT status to `outstanding 0`, including a discharge landing after run-end — the historical run-end record keeps the old count, so never read debt from it; `outstanding unknown` is never green. Tickmarkr consolidates accepted task work on `tickmarkr/<runId>`; it never signs off to the main branch. A human may later merge that integration branch through the repository's normal release process.
130
- 6. **Record** — `tickmarkr report <runId> --md` prints Markdown to stdout. Redirect it explicitly beside the source spec (for example `tickmarkr report <runId> --md > feature.record.md`) and commit the execution record when the repository tracks those records. Then [stand down](#stand-down-mission-end-and-retirement).
184
+ 6. **Record** — `tickmarkr report <runId> --md` prints Markdown to stdout. Redirect it explicitly beside the source spec (for example `tickmarkr report <runId> --md > feature.record.md`) then follow [stand-down](#stand-down-mission-end-and-retirement) to append the ORCH end marker before committing the execution record when tracked.
131
185
 
132
186
  ## Host-owned daemon and detached beats
133
187
 
@@ -71,6 +71,53 @@ the answer took session-file archaeology). The flip from the engine (P89, journa
71
71
  GSD legs (P92) had been RULED NOWHERE — no ledger entry decides it — and then propagated for six phases
72
72
  through brief lineage. **An executor choice nobody made is still an executor choice, and it compounds.**
73
73
 
74
+ ## Hand-made checkout law (queue row 240; D-2138 add.1 R4, add.4; gap G7)
75
+
76
+ This one law applies on herdr, on Orca and on a plain host, to EVERY hand-made checkout:
77
+ integration snapshots, SCOPER, REF, oracle and any other manually created worktree. `<repo>` is the
78
+ repository's primary root, never a task checkout. Its seats-directory home is `<repo>-seats/<name>`,
79
+ a sibling of the repository root; on Orca an Orca-managed worktree is also allowed. Never create one
80
+ inside `.tickmarkr/worktrees.noindex`, or under `/private/tmp` (including the `/tmp` alias): a reboot
81
+ wipes that temporary root. Product-journaled task checkouts, Orca-managed run checkouts and throwaway
82
+ clones retain their existing lifecycle; this is the creating seat's duty, never a product cleanup sweep.
83
+
84
+ **Creation and ledger.** Before creation, make the seats directory and `<repo>/.tickmarkr/overseer/`
85
+ if absent. Immediately after each successful creation, before using the checkout, append one line to
86
+ `<repo>/.tickmarkr/overseer/checkouts.ledger` (the repository's `.tickmarkr/overseer/checkouts.ledger`):
87
+
88
+ ```text
89
+ path=<repo>-seats/<name> | purpose=<snapshot/scoper/REF/oracle/...> | owner=<seat> | remove-when=mission <mission> ends | keep=none | state=open
90
+ ```
91
+
92
+ For an Orca-managed checkout, record its actual path instead. Use a stable owner seat identity even on
93
+ a plain host; a successor never silently adopts another seat's lines. Each refresh closes the old
94
+ checkout's line and appends a new line for the newly created checkout. A keep reason is recorded as
95
+ `keep=<reason>; owner=<seat>; until=<condition>`, never inferred from a directory's name.
96
+
97
+ **Mission-end removal, per owned ledger line.** At mission end (green, failed or parked), after users
98
+ of the checkout have stood down, read only open lines whose `owner` is THIS seat. Use each line's exact
99
+ `path`: an unledgered checkout or another seat's checkout is untouched. Never discover removal targets
100
+ by directory glob, directory sweep or worktree-list inventory. For each owned line:
101
+
102
+ 1. Run `git -C <dir> status --porcelain` at that exact ledger path; require successful exit and capture
103
+ the entire output. Nonempty means **dirty → kept**: record `state=kept` and report its status and path.
104
+ 2. A recorded keep reason means **kept**, even if clean: record `state=kept`, the reason, owner seat and
105
+ condition for eventual removal, and report them. A dirty checkout with a keep reason records both.
106
+ 3. Only a clean checkout with no keep reason can proceed. Before ANY such removal (including a snapshot
107
+ refresh), determine whether HEAD is detached with `git -C <dir> symbolic-ref -q HEAD` (exit 1 means
108
+ detached). Resolve its exact head with `git -C <dir> rev-parse --verify HEAD`. For a detached head,
109
+ prove it reachable from a retained named ref using
110
+ `git -C <repo> for-each-ref --contains <sha> --format='%(refname)'`. Record the retained ref on the
111
+ ledger line and retain it after removal; HEAD and a reflog are not named refs. A successful query
112
+ with no retained named ref means **pin first**: run
113
+ `git -C <repo> update-ref refs/tickmarkr/preserved/<sha> <sha>`, verify that ref resolves to `<sha>`,
114
+ and write `preserved=refs/tickmarkr/preserved/<sha>` on THIS checkout's ledger line BEFORE removal.
115
+ Keep that recovery ref after removal. A failed status, HEAD/ref query, pin or ledger write means
116
+ kept and reported, never permission to continue.
117
+ 4. Then use `git worktree remove <dir>` from `<repo>`, **without force, never `--force` or `-f`**.
118
+ Only successful removal closes that ledger line (`state=closed`); a refusal leaves it open/kept
119
+ and is reported. Never delete the directory directly or override a dirty/locked refusal.
120
+
74
121
  ## On a plain host (neither herdr nor Orca)
75
122
 
76
123
  Neither `HERDR_ENV=1` nor the Orca markers are set: the Claude Desktop Code tab, a plain terminal, any
@@ -197,7 +244,8 @@ replaces the two-tier setup.
197
244
  (own tab, or a shared WORKERS tab), never the ORCH tab.
198
245
  - `CONSULT · <topic>` — ONE shared tab for ALL consultants of a round, side-by-side splits; never one
199
246
  tab per consultant; do NOT auto-close after adjudication (operator, 2026-08-09 — keep the round's
200
- panes until the thread is confirmed finished or a successor round supersedes them).
247
+ panes while the mission continues or until a successor round supersedes them; at mission end apply
248
+ mission-end teardown, queue row 240; D-2138 add.1 R3).
201
249
  - `REVIEW <task>` — reviewer panes.
202
250
  Never multiply beyond these without asking. **Tabs you did not create are the OPERATOR'S — provenance
203
251
  decides: never close, rename, reuse, or send input to one, however idle it looks.** An "idle
@@ -249,8 +297,8 @@ replaces the two-tier setup.
249
297
  **Handles do not survive an Orca restart (OBS-1050, three gates lost to it in v2.5.6).** The restart
250
298
  re-issues every terminal handle; a recorded one answers `terminal_handle_stale` and any watcher or gate
251
299
  keyed to it is already dead. So: record every seat's handle in `pids/<seat>.handle` beside its title at
252
- spawn; on `terminal_handle_stale`, re-list terminals and re-resolve the seat by TITLE, then rewrite the
253
- handle file; and treat a stale handle as a dead seat until the read-back of the new handle proves
300
+ spawn with host, address, title, checkout and mission; on `terminal_handle_stale`, re-list terminals
301
+ and re-resolve by title and checkout for READS ONLY, never rewrite the spawn record from title alone; and treat a stale handle as a dead seat until the read-back of the new handle proves
254
302
  otherwise — a gate that was running in that seat has to be re-launched, never assumed to continue.
255
303
  When briefing a seat on either host, take its current address from the handoff file; never hardcode a pane id
256
304
  or terminal handle in a brief or command template.
@@ -343,7 +391,8 @@ Kimi `-y`, artifact plus terminal marker, and verified file-brief delivery. Flee
343
391
  into it (measured 2026-09-20: `terminal create` timed out on an unmanaged spec worktree, the overseer
344
392
  split instead, and the run had to be re-seated before GO). Before delivering the brief, prove the seat
345
393
  is in its own tab: `orca terminal list --json`, the new handle's `tabId` must differ from the
346
- overseer's; if it does not, close the seat and create it again the lawful way. `split` is for seats
394
+ overseer's; if it does not, withhold the brief and report the misplaced seat; never treat the
395
+ launching tab as owned (queue row 240; D-2138 add.4). `split` is for seats
347
396
  that BELONG beside another seat (consultant pairs, a reviewer beside its surgeon), never for the
348
397
  orchestrator or a gate seat.
349
398
  **Seat names on Orca are TAB titles, and a tab title HOLDS; the pane title is the agent's and drifts.**
@@ -551,8 +600,15 @@ journal tail to decide what happens next, or sweeping orphans — you have taken
551
600
  branch name alone, which moves while you are reading it;
552
601
  - **the operator view of that branch** — a live run has NO integration checkout: the daemon publishes
553
602
  each merge onto `tickmarkr/<runId>` by compare-and-swap from the repository root. View it through a
554
- detached snapshot (`git worktree add --detach <dir> tickmarkr/<runId>`), refreshed by removing it
555
- (`git worktree remove <dir>`) and re-adding it; check the branch out attached only with the daemon
603
+ detached snapshot in the seats-directory home `<repo>-seats/<name>`:
604
+ `git worktree add --detach <repo>-seats/<name> tickmarkr/<runId>`. Append its path, snapshot purpose,
605
+ owner seat and mission-end removal condition to `.tickmarkr/overseer/checkouts.ledger` before use.
606
+ Follow the hand-made checkout law (queue row 240; D-2138 add.1 R4, add.4): before refresh or
607
+ mission-end removal, prove a clean detached HEAD reachable from a retained named ref with
608
+ `git for-each-ref --contains <sha>`; otherwise pin `refs/tickmarkr/preserved/<sha>` and write that
609
+ handle on its ledger line first. Refresh only through that law's clean/no-keep check and
610
+ `git worktree remove <repo>-seats/<name>` without force, close its line, then re-add and append a
611
+ new line; dirty or kept snapshots stay and are reported. Check the branch out attached only with the daemon
556
612
  stopped (no live `graph.lock`) — an attached checkout taken while the run is live goes stale at the next
557
613
  publication, and any write to the ref parks the next merge infra. Run `tickmarkr verify` and `report`
558
614
  from the main checkout or a snapshot;
@@ -1526,43 +1582,87 @@ orchestrator turn boundary.
1526
1582
 
1527
1583
  At seat spawn, arm file/journal watchers for artifact completion, run events, missing progress and context evidence. Record each watcher owner and bounded expiry; renew on every wake and stop on stand-down. Read `orca terminal read --terminal <handle> --screen --json` on each wake to detect blocked or pending input. For a human gate, write a checkpoint evidence file and announce it through verified terminal send; the moment a successor opens that file (or any other cited file) back, log the open per CITE-IS-NOT-READ (`opened <path>` appended to `.tickmarkr/overseer/opened-files.log`). Use Orca notifications only when the installed host advertises a notification capability; the current CLI has no `notification` command, so the file and terminal receipt remain the delivery path. A notification or accepted input alone never proves delivery or completion. A seat-liveness watcher on the ORCHESTRATOR handle is mandatory, not optional: poll `orca terminal read --terminal <handle> --screen --json` on a bounded interval and key liveness on `result.terminal.status === "running"` — never on the envelope's own `ok`. `ok: true` proves only that the READ command executed; a closed seat's read still returns that same `ok: true` with `result.terminal.status: "exited"`, and a matcher keyed on `ok` reads that exited seat as alive and never fires (OBS-1087). Treat `result.terminal.status !== "running"`, `terminal_handle_stale`, or a missing terminal as seat death, and re-resolve by title before re-arming (OBS-1050 — the orchestrator seat exited silently and the daemon ran unsupervised to a PARTIAL run-end).
1528
1584
 
1585
+ The artifact watcher is available on Orca (queue row 240; D-2138 add.4):
1586
+ `TKR_CLOSE_TERMINALS="<handle>,<handle>" bash skills/tickmarkr-overseer/scripts/watch-artifacts.sh <MARKER> <cap-s> <poll-s> <file>...`.
1587
+ Supply one recorded address per artifact in argument order; a length mismatch is refused at arm time.
1588
+ Both all-complete and wake-on-any exits close only each completed artifact's stood-down seat after
1589
+ matching the spawn ledger to its live tab title, leaf handle and layout checkout. Pending siblings,
1590
+ missing markers, missing/current-mission-mismatched stand-downs and timeouts close nothing.
1591
+ The verified close uses `orca terminal close --terminal <handle> --json`, checks the handle receipt
1592
+ or documented live refusal, then handle absence from the terminal list and owned-tab absence from
1593
+ visual layouts. A stale handle permits read-only re-resolution by title; it never licenses a close.
1594
+ Do not arm closure for the latest settled consult round while its mission continues.
1595
+
1596
+ ## Mission-end teardown (queue row 240; D-2138 add.1 R3, add.4)
1597
+
1598
+ **The spawner closes the seat it created.** Manual closes and watcher closes follow this same law:
1599
+ close only once its artifact and terminal marker are on disk, its stand-down is read back, and no
1600
+ next mission is named for it. An agent's `done` signal, a bare handle, or a title alone is never enough.
1601
+ The ORCH's artifact is the execution record ending in `<!-- tickmarkr:orch-end <runId> -->`;
1602
+ the supervisor reads exactly that record and that run's marker before retiring the orchestrator.
1603
+ Keep a reused seat only with its next mission named and a `/clear` at the mission boundary.
1604
+ Keep the latest settled consult round only while the mission continues; at mission end apply this
1605
+ same close or reuse rule. A dedicated consultant tab may outlive the orchestrator tab during that
1606
+ continuing mission, never indefinitely after the mission ends.
1607
+
1608
+ **Record ownership at spawn**, beside watcher pids under `<state-dir>/overseer/pids/<seat>.handle`:
1609
+ write `host`, `address`, `title`, `checkout`, and `mission`, one `key=value` per line, from the create
1610
+ receipt; use the actual tab title and checkout. This is the spawn ledger, not a list reconstructed
1611
+ from titles. Record an owned tab as `tab=<tab-id>` when the seat owns it. Every spawned seat's brief
1612
+ ends with: after stand-down, write `pids/<seat>.stood-down` containing `mission=<mission>`.
1613
+ On every new assignment, including named-next-mission reuse, rewrite the ledger's `mission` and
1614
+ delete the old stood-down file BEFORE that mission starts (D-2138 add.6 V01). Read back the stood-down
1615
+ file and require its mission to equal the ledger's current mission; an earlier mission's stand-down
1616
+ never retires the reused seat.
1617
+
1618
+ **Before every close, first match the spawn record against the live tab title and checkout**, at its
1619
+ recorded address. A mismatch closes nothing. Never close a tab you did not create, a recycled handle
1620
+ now showing an operator's terminal, a seat matched by title alone, or your own launching terminal.
1621
+ A stale or mismatched Orca handle permits read-only re-resolution by title and checkout to read the
1622
+ seat; never close the replacement by title, never rewrite ownership from a title-only match.
1623
+
1624
+ - **On herdr (`HERDR_ENV=1`)**: verify `herdr pane list`: the recorded address equals `pane_id`,
1625
+ the recorded title equals `label`, and the recorded checkout equals `cwd` (filesystem identity).
1626
+ Only then use `herdr pane close <pane>` at the recorded address. Prove the pane absent from
1627
+ `herdr pane list`; for a seat owning its tab, use `herdr tab close <tab>` at its recorded tab id
1628
+ after the final owned pane closes, and prove the tab absent from `herdr tab list`. A shared tab
1629
+ with a pending sibling stays open. Never assume emptied tabs disappear without checking.
1630
+ - **On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`)**: verify ownership with
1631
+ `orca terminal list --include-visual-layouts --json`: the spawn record's address is the leaf handle,
1632
+ its title is the live TAB title (never the shell's pane title), and its checkout matches the layout
1633
+ worktree and terminal row. An unbound checkout or truncated listing is unverifiable and closes nothing.
1634
+ Only then use `orca terminal close --terminal <handle> --json` with the recorded handle. Require
1635
+ `result.close.handle` equal to that handle, or the documented live-terminal refusal
1636
+ `ok:false`, `error.code:runtime_error`, `error.message:tab_not_found` from that same runtime.
1637
+ Prove the handle absent from `orca terminal list --json` AND its owned tab absent from
1638
+ `orca terminal list --include-visual-layouts --json` after its final terminal closes, in the same
1639
+ runtime as the pre-close listing. A surviving owned tab is a spec question, never permission to
1640
+ close by title. The Orca smoke e2e asserts this tab leg; a receipt alone is no close proof.
1641
+
1529
1642
  ## Specialist pipeline rules
1530
1643
 
1531
1644
  ### On herdr (`HERDR_ENV=1`) — specialist panes
1532
1645
 
1533
- - **Dedicated consultant tab**: Consultants (agents spawned to gather synthesis input for decisions like SCOPER analysis or architectural reviews) must run in a DEDICATED tab separate from the ORCHESTRATOR tab. When the orchestrator stands down, the consultant panes should persist so their assessments remain available for review and reference.
1534
- - **Scoper worktree rule**: The SCOPER (or any worktree-based specialist synthesizing into the spec pipeline) must do ALL git operations in a dedicated worktree (e.g., `git worktree add /private/tmp/tkr-scoper-v155 -b spec/...`), never switching the main checkout's branch. This prevents race conditions between the specialist's branch operations and the orchestrator's shipping logic.
1646
+ - **Dedicated consultant tab**: Consultants (agents spawned to gather synthesis input for decisions like SCOPER analysis or architectural reviews) must run in a DEDICATED tab separate from the ORCHESTRATOR tab. The dedicated consultant tab persists beyond an orchestrator retirement only while the mission continues; the latest settled round follows mission-end teardown at that mission's end (queue row 240; D-2138 add.1 R3).
1647
+ - **Scoper worktree rule**: The SCOPER (or any worktree-based specialist synthesizing into the spec pipeline) must do ALL git operations in a dedicated worktree in the seats-directory home `<repo>-seats/<name>` (e.g., `git worktree add -b spec/<mission> <repo>-seats/scoper-<mission>`), never switching the main checkout's branch. Append its path, scoper purpose, owner seat and mission-end removal condition to `.tickmarkr/overseer/checkouts.ledger` before use. The hand-made checkout law (queue row 240; D-2138 add.1 R4, add.4) governs it: at mission end remove only a clean owned checkout with no keep reason using `git worktree remove <repo>-seats/scoper-<mission>` without force and close its line; dirty or kept checkouts stay and are reported. Before removing a detached HEAD, prove reachability from a retained named ref with `git for-each-ref --contains <sha>`, otherwise pin `refs/tickmarkr/preserved/<sha>` and write that handle on its ledger line first. This prevents race conditions between the specialist's branch operations and the orchestrator's shipping logic.
1535
1648
  - **One fresh pane per consult ROUND** (operator rule, 2026-08-04): every consult round spawns a NEW pane in
1536
1649
  the consult tab rather than re-prompting the seat that answered last round — unless there is a stated
1537
1650
  reason to reuse. Two payoffs: each round starts with a clean context window instead of inheriting the
1538
1651
  previous round's, which is what fills a long mission's seats and forces mid-mission `/clear`; and the
1539
1652
  prior round's pane persists as a readable record of what that seat actually saw and said. Reuse only when
1540
1653
  continuity of the seat's own reasoning is the point, and say so when you do.
1541
- - **CLOSE WHAT YOU SPAWNED** (operator observation, 2026-08-04: *"orch doesn't auto close the panes that he
1542
- created when no more needed"*). Panes accumulate silently — one mission reached **15 panes and 10 tabs**,
1543
- ten of them holding live agent sessions for work that had been on disk and fully consumed for hours.
1544
- Neither seat cleaned up, because neither had been told to.
1545
- - **Whoever spawns a pane owns closing it.** The orchestrator closes its workers; the overseer closes the
1546
- consultants and sweeps it spawned. The overseer sweeps whatever is left at mission end.
1547
- - **Verify the deliverable is ON DISK before closing** — a pane is the only place an unwritten finding
1548
- exists, and an agent that rendered "Done" without writing its artifact did not deliver (the
1549
- trust-disk-over-transcripts rule — cited by NAME, because a renumbered list orphans a "rule N").
1550
- **Non-empty is the FLOOR, not the test: completeness is the artifact's own TERMINAL MARKER.** One
1551
- consult verdict was 10KB on disk while its seat still read `working` — size proved it had started, and
1552
- only the closing `VERDICT:` line proved it had finished. Require the terminal marker a report is
1553
- supposed to end with, per seat, then close.
1554
- - **A pane is not an archive; the report is.** Once a worker's findings are written and synthesized, its
1555
- transcript adds nothing the report does not.
1556
- - **KEEP: the active seat, and the most recent SETTLED consult round.** That last one earns its place —
1557
- re-prompting the seat that found a defect to confirm its own fix is cheaper and stricter than briefing
1558
- a fresh one, which is the stated-reason exception above. Close consult rounds only once a later round
1559
- has re-derived their findings.
1560
- - Emptied tabs disappear on their own; do not close tabs by hand.
1561
- - **CLOSE IT AUTOMATICALLY, because remembering is what fails.** `watch-artifacts.sh` already fires on
1562
- the one signal that means a seat is finished — the artifact plus its terminal marker — so hand it the
1563
- panes too: `TKR_CLOSE_PANES="w1:p1,w1:p2" watch-artifacts.sh …`. It closes them on completion and
1564
- **never on timeout**, where the seats are still working. Closing on the marker cannot reap a seat
1565
- mid-write, which is exactly why `done` would be the wrong trigger.
1654
+ - **CLOSE WHAT YOU SPAWNED**: apply the universal mission-end teardown, including the spawn record
1655
+ ownership check and current mission's stand-down. The spawner is responsible for closure.
1656
+ Keep the active seat and latest settled consult round while the mission continues; at its end close
1657
+ or name the next mission and clear before reuse (queue row 240; D-2138 add.1 R3, add.4).
1658
+ - For a seat owning its tab, after verified `herdr pane close <pane>`, explicitly use
1659
+ `herdr tab close <tab>` at the recorded tab id and prove absence from `herdr tab list`; shared tabs
1660
+ stay while a pending sibling owns a pane. The spawn record must match live label and checkout first.
1661
+ - **Automatic closure**: `TKR_CLOSE_PANES="w1:p1,w1:p2" watch-artifacts.sh …` supplies one recorded
1662
+ pane address per artifact, in argument order. Both all-complete and wake-on-any exits close only
1663
+ completed artifacts with current-mission stood-down files and verified ledger identity, never
1664
+ pending siblings or timeout. No ledger record means a reported refusal and an open pane.
1665
+ Do not arm closure for the latest settled consult round while its mission continues.
1566
1666
 
1567
1667
  - **MEASURE BEFORE EVERY SPLIT, AND JOIN *DOWN* WHEN A RIGHT-SPLIT WOULD GO UNDER THE FLOOR.**
1568
1668
  **Operator-observed 2026-08-06, with a screenshot:** five consult panes in one tab rendered **14 columns
@@ -1593,7 +1693,7 @@ At seat spawn, arm file/journal watchers for artifact completion, run events, mi
1593
1693
 
1594
1694
  ### On Orca (`TERM_PROGRAM=Orca` and non-empty `ORCA_TERMINAL_HANDLE`) — specialist terminals
1595
1695
 
1596
- Create specialist seats using `orca terminal create --worktree path:<repo> --command "<agent-cmd>" --json` and record each returned handle. For a deliberate split use `orca terminal split --terminal <owned-handle> --direction horizontal --command "<agent-cmd>" --json`, retaining the child receipt. Deliver briefs with `terminal send --enter --wait-submit 15`, verify observed submission (`result.send.prompt.stages.includes("turn_started")`), and collect files beside `orca terminal read --terminal <handle> --screen --json`. File/journal completion watchers close only recorded seats after the terminal artifact marker; timeout never authorizes closure.
1696
+ Create specialist seats using `orca terminal create --worktree path:<repo> --command "<agent-cmd>" --json` and record each returned handle. For a deliberate split use `orca terminal split --terminal <owned-handle> --direction horizontal --command "<agent-cmd>" --json`, retaining the child receipt. Deliver briefs with `terminal send --enter --wait-submit 15`, verify observed submission (`result.send.prompt.stages.includes("turn_started")`), and collect files beside `orca terminal read --terminal <handle> --screen --json`. Completion watchers use the universal mission-end teardown: artifact plus terminal marker, current-mission stand-down read back, and spawn ledger matched to the live tab title and checkout before closing the recorded handle with `orca terminal close --terminal <handle> --json`; require the handle receipt or documented live refusal, handle absence and final owned-tab absence. Timeout never authorizes closure (queue row 240; D-2138 add.4).
1597
1697
 
1598
1698
  ## Non-negotiable rules
1599
1699