@volter/supercode-orchestrator 0.5.60 → 0.5.61
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/board/dispatch.mjs +24 -24
- package/board/workflow.mjs +6 -3
- package/package.json +1 -1
package/board/dispatch.mjs
CHANGED
|
@@ -192,7 +192,7 @@ function unpublishedAlive(session) {
|
|
|
192
192
|
if (!session.machine) return null;
|
|
193
193
|
if (!session.pane) {
|
|
194
194
|
if (!session.session_id) return null;
|
|
195
|
-
try { return nativeReading(nativeSessions(session.machine, session.harness ?? 'claude-code'), session).alive; } catch { return null; }
|
|
195
|
+
try { return nativeReading(nativeSessions(session.machine, session.harness ?? 'claude-code', session.session_id), session).alive; } catch { return null; }
|
|
196
196
|
}
|
|
197
197
|
let entry = paneLists.get(session.machine);
|
|
198
198
|
if (!entry || Date.now() - entry.at > READING_MS) {
|
|
@@ -205,9 +205,9 @@ function unpublishedAlive(session) {
|
|
|
205
205
|
return entry.panes ? entry.panes.some((p) => p.pane === session.pane && !p.dead) : null;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
/** Native activity comes from the machine's harness discovery, not catalogue age
|
|
209
|
-
*
|
|
210
|
-
* them
|
|
208
|
+
/** Native activity comes from the machine's harness discovery, not catalogue age: each session the round reads is
|
|
209
|
+
* discovered by its id (about 0.2 s), once per round (tick clears them). Listing the machine's every session to find
|
|
210
|
+
* them (up to 2000, 1-6 s each) cost more than the sessions a board runs. */
|
|
211
211
|
const discoveries = new Map();
|
|
212
212
|
// A machine's pane list and harness discovery are read before a board write opens, never inside one: a door that
|
|
213
213
|
// takes seconds would hold the board's write lock past a worker's own command's busy wait. A write that needs a
|
|
@@ -218,25 +218,26 @@ const txRead = (board, fn) => { readingsOnly += 1; try { return tx(board, fn); }
|
|
|
218
218
|
/** Take the readings a board write about `session` will need, before the write. */
|
|
219
219
|
function readBefore(fleet, session) {
|
|
220
220
|
if (!session?.session_id || !session.machine || session.surface === 'headless') return;
|
|
221
|
-
try { nativeSessions(session.machine, session.harness ?? 'claude-code'); } catch { /* unread: unknown inside the write */ }
|
|
221
|
+
try { nativeSessions(session.machine, session.harness ?? 'claude-code', session.session_id); } catch { /* unread: unknown inside the write */ }
|
|
222
222
|
sessionAlive(fleet, session);
|
|
223
223
|
}
|
|
224
|
-
function nativeSessions(machine, harness) {
|
|
225
|
-
const key =
|
|
224
|
+
function nativeSessions(machine, harness, sessionId) {
|
|
225
|
+
const key = nativeKey(machine, harness, sessionId), seen = discoveries.get(key);
|
|
226
226
|
if (seen) return seen.sessions;
|
|
227
227
|
if (readingsOnly) throw unavailable('native liveness is read before a board write, not inside it');
|
|
228
|
-
const sessions = discoverNative(machine, harness);
|
|
228
|
+
const sessions = discoverNative(machine, harness, sessionId);
|
|
229
229
|
discoveries.set(key, { at: Date.now(), sessions });
|
|
230
230
|
return sessions;
|
|
231
231
|
}
|
|
232
232
|
// A native discovery is bounded as the fleet reading is: one that does not answer in time is unknown, read next round.
|
|
233
233
|
const NATIVE_DISCOVERY_MS = 15_000;
|
|
234
|
-
|
|
234
|
+
const nativeKey = (machine, harness, sessionId) => `${normalMachine(machine)}\u0000${harness}\u0000${sessionId}`;
|
|
235
|
+
function discoverNative(machine, harness, sessionId) {
|
|
235
236
|
if (offlineMachine(machine)) throw unavailable(`native liveness unavailable: machine ${normalMachine(machine)} is offline`);
|
|
236
237
|
// This machine's discovery is its harness door, as every other harness read here is; another machine's is supercode's fleet arm
|
|
237
238
|
const result = normalMachine(machine) === localMachine()
|
|
238
|
-
? doorOn(machine, 'harness.v1.sessions.discover', { harnesses: [harness], limit: 2000 }, { timeout: NATIVE_DISCOVERY_MS })
|
|
239
|
-
: sc(['discover', '--on', machine, '--harness', harness, '--limit', '2000'], { timeout: NATIVE_DISCOVERY_MS });
|
|
239
|
+
? doorOn(machine, 'harness.v1.sessions.discover', { harnesses: [harness], query: sessionId, limit: 2000 }, { timeout: NATIVE_DISCOVERY_MS })
|
|
240
|
+
: sc(['discover', '--on', machine, '--harness', harness, '--query', sessionId, '--limit', '2000'], { timeout: NATIVE_DISCOVERY_MS });
|
|
240
241
|
const page = result.code === 0 ? lastJson(result.stdout) : null;
|
|
241
242
|
if (!Array.isArray(page?.sessions)) throw unavailable(`native liveness unavailable on ${machine}: ${(result.stderr || result.stdout).trim().slice(-300)}`);
|
|
242
243
|
return page.sessions;
|
|
@@ -526,8 +527,8 @@ function stopSession(board, session) {
|
|
|
526
527
|
const r = sc(['close', addressOf(session)], { timeout: 120_000, as: boardAddress(board.label) });
|
|
527
528
|
if (r.code !== 0) throw new Error(`${doorTransient(r) ? 'close deferred: ' : ''}closing native session ${addressOf(session)}: ${(r.stderr || r.stdout).trim().slice(-500)}`);
|
|
528
529
|
// the close's receipt is a discovery taken after it, never the round's cached one from before
|
|
529
|
-
discoveries.delete(
|
|
530
|
-
const reading = nativeReading(nativeSessions(session.machine, session.harness), session);
|
|
530
|
+
discoveries.delete(nativeKey(session.machine, session.harness, session.session_id));
|
|
531
|
+
const reading = nativeReading(nativeSessions(session.machine, session.harness, session.session_id), session);
|
|
531
532
|
if (reading.alive !== false) throw new Error(`native close has no confirmed stopped receipt for ${addressOf(session)}`);
|
|
532
533
|
return;
|
|
533
534
|
}
|
|
@@ -932,7 +933,7 @@ export function closeRequested(board, report, { taskId = null, caller = null, tt
|
|
|
932
933
|
try {
|
|
933
934
|
const machine = session.machine ?? localMachine();
|
|
934
935
|
if (session.surface === 'native' && !session.pane) {
|
|
935
|
-
const reading = nativeReading(nativeSessions(machine, session.harness), session);
|
|
936
|
+
const reading = nativeReading(nativeSessions(machine, session.harness, session.session_id), session);
|
|
936
937
|
if (reading.alive == null) throw new Error(`close deferred: native liveness unknown for ${addressOf(session)}`);
|
|
937
938
|
if (reading.alive) {
|
|
938
939
|
const protectedNow = active.some(r => addressOf(json(r.metadata, {})?.supercode) === addressOf(session));
|
|
@@ -998,13 +999,12 @@ export function closeRequested(board, report, { taskId = null, caller = null, tt
|
|
|
998
999
|
function observeIdle(board, fleet, settings, report, entry, effects) {
|
|
999
1000
|
if (!fleet.ok) return;
|
|
1000
1001
|
// The published fleet says whether a session runs and its turn, not when it last wrote: that is the session's own
|
|
1001
|
-
// record, read from its machine's discovery (
|
|
1002
|
+
// record, read from its machine's discovery (once a round, only when a card needs it).
|
|
1002
1003
|
// Without it every reading was 'no_timestamp' and no session was ever found idle.
|
|
1003
|
-
const discovered = new Map();
|
|
1004
1004
|
const updatedAt = (session) => {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
return Number(
|
|
1005
|
+
let rows = null;
|
|
1006
|
+
try { rows = nativeSessions(session.machine ?? localMachine(), session.harness ?? 'claude-code', session.session_id); } catch { /* unread: no timestamp */ }
|
|
1007
|
+
return Number(rows?.find((row) => row.locator?.session_id === session.session_id)?.updated_at_ms) || null;
|
|
1008
1008
|
};
|
|
1009
1009
|
const managers = [].concat(entry.params.managers ?? []).filter(Boolean);
|
|
1010
1010
|
const running = board.db.prepare(entry.workflow.run ? "SELECT id FROM tasks WHERE current_run_id IS NOT NULL" : "SELECT id FROM tasks WHERE status = 'running'").all();
|
|
@@ -1022,7 +1022,7 @@ function observeIdle(board, fleet, settings, report, entry, effects) {
|
|
|
1022
1022
|
if (session.surface === 'native' && sessionAlive(fleet, session) !== true) return;
|
|
1023
1023
|
// a session in no pane has its turn on its machine's discovery row, which sessionAlive just read
|
|
1024
1024
|
let nativeRow = null;
|
|
1025
|
-
if (session.surface === 'native') try { nativeRow = nativeReading(nativeSessions(session.machine, session.harness ?? 'claude-code'), session).row; } catch { /* unread: no turn */ }
|
|
1025
|
+
if (session.surface === 'native') try { nativeRow = nativeReading(nativeSessions(session.machine, session.harness ?? 'claude-code', session.session_id), session).row; } catch { /* unread: no turn */ }
|
|
1026
1026
|
const live = fleet.sessions.find((x) => x.address === addressOf(session)) ?? (nativeRow ? { address: addressOf(session), turn: nativeRow.activity?.turn ?? null } : undefined);
|
|
1027
1027
|
const observedAt = now();
|
|
1028
1028
|
const lastAtMs = Number(live?.last_message_at_ms) || updatedAt(session);
|
|
@@ -1538,7 +1538,7 @@ function launchPane(board, task, runId, lane, fleet, { input = null, slot = 'wor
|
|
|
1538
1538
|
// session it did not launch, left running at its run's end) is its owner's while it runs: it is never resumed beside
|
|
1539
1539
|
// itself, and the launch waits for the owner to end it.
|
|
1540
1540
|
if (prev?.surface === 'native' && !prev.pane && (!prev.close_confirmed_at || prev.released)) {
|
|
1541
|
-
const reading = nativeReading(nativeSessions(prev.machine, prev.harness), prev);
|
|
1541
|
+
const reading = nativeReading(nativeSessions(prev.machine, prev.harness, prev.session_id), prev);
|
|
1542
1542
|
if (reading.alive == null) throw unavailable(`cannot establish native continuation liveness for ${addressOf(prev)}`);
|
|
1543
1543
|
fleet.native ??= new Map(); fleet.native.set(addressOf(prev), reading);
|
|
1544
1544
|
if (reading.alive && prev.released) throw unavailable(`released session ${addressOf(prev)} still runs; the launch waits for its owner to end it`);
|
|
@@ -1790,7 +1790,7 @@ function nativeListing(who) {
|
|
|
1790
1790
|
const m = /^sc:([^:]+):([^:]+):(.+)$/.exec(String(who));
|
|
1791
1791
|
if (!m || !HARNESSES[m[2]]) return null;
|
|
1792
1792
|
const [, host, harness, session_id] = m;
|
|
1793
|
-
try { return nativeReading(nativeSessions(host, harness), { session_id, harness }).alive === true ? { address: who, machine: normalMachine(host), harness, session_id, pane: null, name: null } : null; }
|
|
1793
|
+
try { return nativeReading(nativeSessions(host, harness, session_id), { session_id, harness }).alive === true ? { address: who, machine: normalMachine(host), harness, session_id, pane: null, name: null } : null; }
|
|
1794
1794
|
catch { return null; }
|
|
1795
1795
|
}
|
|
1796
1796
|
|
|
@@ -1817,7 +1817,7 @@ function adoptSession(board, id, who, { request = null, open = request, progress
|
|
|
1817
1817
|
if (!found) throw Object.assign(new Error(`the fleet lists no live session ${who}`), { notListed: true });
|
|
1818
1818
|
const [, host, harness, sessionId] = found.address.split(':');
|
|
1819
1819
|
if (!HARNESSES[harness]) throw new Error(`${found.address} is ${harness}; the board keeps and resumes ${Object.keys(HARNESSES).join(' and ')} sessions`);
|
|
1820
|
-
const native = found.pane ? null : nativeReading(nativeSessions(host, harness), { session_id: sessionId, harness });
|
|
1820
|
+
const native = found.pane ? null : nativeReading(nativeSessions(host, harness, sessionId), { session_id: sessionId, harness });
|
|
1821
1821
|
if (found.pane ? !panePresent(host, found.pane) : native.alive !== true) throw new Error(`${found.address} has no verified live native process or pane`);
|
|
1822
1822
|
const beforeRun = view(board, (db) => currentRun(db, id));
|
|
1823
1823
|
const beforeSession = beforeRun?.metadata?.supercode;
|
|
@@ -1827,7 +1827,7 @@ function adoptSession(board, id, who, { request = null, open = request, progress
|
|
|
1827
1827
|
// the session's own working directory, as discovery records it (where `--resume` finds it), else its pane's
|
|
1828
1828
|
let dir = workspace ?? native?.row?.cwd;
|
|
1829
1829
|
if (!dir) {
|
|
1830
|
-
dir = nativeSessions(host, harness).find((x) => x.locator?.session_id === sessionId)?.cwd ?? null;
|
|
1830
|
+
dir = nativeSessions(host, harness, sessionId).find((x) => x.locator?.session_id === sessionId)?.cwd ?? null;
|
|
1831
1831
|
}
|
|
1832
1832
|
if (!dir && found.pane) {
|
|
1833
1833
|
const r = runtimeDoor(normalMachine(host)===localMachine()?null:host,'harness.v1.panes.list',{}, { timeout: 60_000 });
|
package/board/workflow.mjs
CHANGED
|
@@ -167,9 +167,12 @@ const execFileAsync = promisify(execFile);
|
|
|
167
167
|
export async function refreshRelationAnswers(board) {
|
|
168
168
|
const ids = new Set();
|
|
169
169
|
const entry = workflowFor(board.root);
|
|
170
|
-
for (const row of board.db.prepare("SELECT t.*,c.blocked_by FROM tasks t JOIN supercode_cards c ON c.task_id=t.id WHERE c.blocked_by IS NOT NULL AND c.blocked_by!='[]'").all()) {
|
|
171
|
-
|
|
172
|
-
for (
|
|
170
|
+
for (const row of board.db.prepare("SELECT t.*,c.blocked_by FROM tasks t JOIN supercode_cards c ON c.task_id=t.id WHERE c.blocked_by IS NOT NULL AND c.blocked_by!='[]' AND t.status NOT IN ('done','cancelled','archived') AND NOT COALESCE(c.archived,0)").all()) {
|
|
171
|
+
// only an open card's message has an answer to read: a closed card, or one blocked by cards alone, needs no scope
|
|
172
|
+
// built for its guard (75 walked on 2026-10-04, one of them a live message blocker)
|
|
173
|
+
const messages = (json(row.blocked_by, []) ?? []).filter((block) => block.kind === 'message');
|
|
174
|
+
if (!messages.length || !relationActive(board.db, board, entry, row)) continue;
|
|
175
|
+
for (const block of messages) ids.add(block.id);
|
|
173
176
|
}
|
|
174
177
|
for (const row of board.db.prepare("SELECT e.payload FROM task_events e JOIN (SELECT task_id, MAX(id) id FROM task_events WHERE kind IN ('blocked','unblocked') GROUP BY task_id) last ON e.id=last.id JOIN tasks t ON t.id=e.task_id WHERE e.kind='blocked' AND t.status='blocked'").all()) {
|
|
175
178
|
const id = json(row.payload, {})?.waiting_on; if (id) ids.add(id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.61",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
|
|
6
6
|
"exports": {
|