@volter/supercode-orchestrator 0.4.104 → 0.4.105
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 +19 -6
- package/package.json +1 -1
package/board/dispatch.mjs
CHANGED
|
@@ -176,6 +176,16 @@ export function lanesOf(profiles = {}) {
|
|
|
176
176
|
|
|
177
177
|
function supervise(board, fleet, settings, report, entry, effects) {
|
|
178
178
|
const rows = 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();
|
|
179
|
+
// The catalog can lag a pane. Read the actual machines once, before any board mutation.
|
|
180
|
+
const observed = new Map();
|
|
181
|
+
for (const { id } of rows) {
|
|
182
|
+
const s = currentRun(board.db, id)?.metadata?.supercode;
|
|
183
|
+
if (!s?.pane || observed.has(s.machine)) continue;
|
|
184
|
+
const r = sc(['teams', 'panes', 'ls', '--machine', s.machine ?? localMachine()], { timeout: 60_000 });
|
|
185
|
+
const list = r.code === 0 ? json(r.stdout.trim(), null) : null;
|
|
186
|
+
observed.set(s.machine, Array.isArray(list) ? new Set(list.map((p) => p.pane)) : null);
|
|
187
|
+
if (!Array.isArray(list)) report.failed.push([id, `pane liveness unavailable; retaining run: ${(r.stderr || r.stdout).trim().slice(-200)}`]);
|
|
188
|
+
}
|
|
179
189
|
for (const { id } of rows) {
|
|
180
190
|
tx(board, (db) => {
|
|
181
191
|
const task = getTask(db, id);
|
|
@@ -197,7 +207,9 @@ function supervise(board, fleet, settings, report, entry, effects) {
|
|
|
197
207
|
};
|
|
198
208
|
const limits = limitsOf(db, board, entry, task, session);
|
|
199
209
|
// Hermes's orphan reconciliation: a running card whose claim bookkeeping is broken, with nothing live behind it
|
|
200
|
-
const
|
|
210
|
+
const paneReading = session?.pane ? observed.get(session.machine) : undefined;
|
|
211
|
+
const paneLive = paneReading instanceof Set ? paneReading.has(session.pane) : null;
|
|
212
|
+
const live = session?.surface === 'headless' ? pidAlive(session.pid) : session?.pane ? paneLive !== false : session?.session_id ? (fleet.ok ? sessionAlive(fleet, session) : true) : false;
|
|
201
213
|
// (whether it is reconciled is the workflow's: its `orphaned` transitions and their guard)
|
|
202
214
|
if ((!task.claim_lock || !task.claim_expires) && !live) {
|
|
203
215
|
observe('orphaned', { reason: 'orphaned_running', claim_lock: task.claim_lock, claim_expires: task.claim_expires, error: 'orphaned running card (broken claim bookkeeping)' }, 'reclaimed');
|
|
@@ -226,20 +238,21 @@ function supervise(board, fleet, settings, report, entry, effects) {
|
|
|
226
238
|
return;
|
|
227
239
|
}
|
|
228
240
|
if (session?.session_id) {
|
|
229
|
-
if (
|
|
230
|
-
|
|
231
|
-
const
|
|
241
|
+
if (session.pane && paneLive === null) return; // no machine reading, no loss verdict
|
|
242
|
+
if (!session.pane && !fleet.ok) return;
|
|
243
|
+
const alive = session.pane ? paneLive : sessionAlive(fleet, session);
|
|
244
|
+
const machineUp = paneReading instanceof Set || fleet.online.has(session.machine);
|
|
232
245
|
const young = t - Number(session.launched_at ?? 0) < Number(limits.grace ?? settings.grace);
|
|
233
246
|
const missing = !alive && machineUp && !young;
|
|
234
247
|
const next = { ...session };
|
|
235
248
|
// a machine that is off the fleet: how long, for the workflow's machine_offline (the claim is kept meanwhile)
|
|
236
|
-
if (machineUp)
|
|
249
|
+
if (machineUp) next.offline_since = null; else next.offline_since ??= t;
|
|
237
250
|
if (!machineUp) {
|
|
238
251
|
setRunSession(db, runRow.id, next);
|
|
239
252
|
observe('machine_offline', { machine: session.machine, seconds: t - next.offline_since }, null);
|
|
240
253
|
if (getTask(db, id)?.current_run_id !== runRow.id) return; // the workflow moved it
|
|
241
254
|
}
|
|
242
|
-
if (alive) { next.seen_at ??= t;
|
|
255
|
+
if (alive) { next.seen_at ??= t; next.missing_since = null; }
|
|
243
256
|
if (missing) next.missing_since ??= t;
|
|
244
257
|
if (missing && t - next.missing_since >= Number(limits.grace ?? settings.grace)) {
|
|
245
258
|
// lost: gone from an online machine for the whole grace. A resume that never came up is not resumable.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.105",
|
|
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": {
|