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.
- package/README.md +22 -0
- package/dist/cli/commands/compile.js +1 -1
- package/dist/cli/commands/report.js +21 -12
- package/dist/cli/commands/status.js +14 -2
- package/dist/cli/commands/verify.js +29 -5
- package/dist/compile/collateral.d.ts +3 -1
- package/dist/compile/collateral.js +8 -16
- package/dist/compile/native.js +7 -2
- package/dist/gates/acceptance.d.ts +8 -0
- package/dist/gates/acceptance.js +54 -37
- package/dist/gates/run-gates.js +31 -22
- package/dist/report/bundle.d.ts +5 -2
- package/dist/report/bundle.js +11 -6
- package/dist/report/compare.d.ts +9 -0
- package/dist/report/compare.js +58 -40
- package/dist/report/operator-record.js +4 -3
- package/dist/run/daemon.d.ts +7 -3
- package/dist/run/daemon.js +221 -42
- package/dist/run/git.d.ts +7 -2
- package/dist/run/git.js +37 -4
- package/dist/run/journal.js +11 -2
- package/dist/run/repair-disposition.d.ts +1 -1
- package/dist/run/repair-disposition.js +33 -2
- package/dist/run/wall-budget.js +8 -4
- package/package.json +1 -1
- package/skills/tickmarkr-auto/SKILL.md +58 -3
- package/skills/tickmarkr-loop/SKILL.md +59 -5
- package/skills/tickmarkr-overseer/SKILL.md +134 -34
- package/skills/tickmarkr-overseer/scripts/watch-artifacts.sh +145 -18
|
@@ -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
|
|
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) =>
|
|
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(", ")}` };
|
package/dist/run/wall-budget.js
CHANGED
|
@@ -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 === "
|
|
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
|
-
//
|
|
43
|
-
|
|
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
|
@@ -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,
|
|
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
|
-
|
|
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
|
|
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,
|
|
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.
|
|
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
|
-
|
|
119
|
-
|
|
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`)
|
|
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
|
|
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
|
|
253
|
-
|
|
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,
|
|
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
|
|
555
|
-
|
|
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.
|
|
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
|
|
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
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
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`.
|
|
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
|
|