@volter/supercode-orchestrator 0.4.45 → 0.4.47
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 +17 -5
- package/board/workflow.mjs +6 -5
- package/package.json +1 -1
package/board/dispatch.mjs
CHANGED
|
@@ -419,7 +419,11 @@ function closeRequested(board, report) {
|
|
|
419
419
|
const session = json(row.metadata, {})?.supercode;
|
|
420
420
|
if (!session?.pane) continue;
|
|
421
421
|
try { stopSession(board, session); } catch (error) { report.undelivered.push([row.task_id, session.address, `closing it: ${String(error.message).slice(-200)}`]); continue; }
|
|
422
|
-
|
|
422
|
+
const address = session.address ?? `sc:${session.machine}:claude-code:${session.session_id}`;
|
|
423
|
+
tx(board, (db) => {
|
|
424
|
+
setRunSession(db, row.id, { ...session, closed_at: now() });
|
|
425
|
+
db.prepare("DELETE FROM kanban_notify_subs WHERE task_id = ? AND platform = 'supercode' AND chat_id = ?").run(row.task_id, address);
|
|
426
|
+
});
|
|
423
427
|
}
|
|
424
428
|
}
|
|
425
429
|
|
|
@@ -473,7 +477,12 @@ export async function sessionEffect(board, e) {
|
|
|
473
477
|
const caller = process.env.CLAUDE_CODE_SESSION_ID || process.env.CODEX_THREAD_ID;
|
|
474
478
|
if (caller && caller === session.session_id) { tx(board, (db) => setRunSession(db, row.id, { ...session, close_requested: now() })); return; }
|
|
475
479
|
stopSession(board, session);
|
|
476
|
-
|
|
480
|
+
// a closed session hears nothing more of the card
|
|
481
|
+
const address = session.address ?? `sc:${session.machine}:claude-code:${session.session_id}`;
|
|
482
|
+
tx(board, (db) => {
|
|
483
|
+
setRunSession(db, row.id, { ...session, closed_at: now() });
|
|
484
|
+
db.prepare("DELETE FROM kanban_notify_subs WHERE task_id = ? AND platform = 'supercode' AND chat_id = ?").run(e.id, address);
|
|
485
|
+
});
|
|
477
486
|
return;
|
|
478
487
|
}
|
|
479
488
|
}
|
|
@@ -577,8 +586,10 @@ function launchPane(board, task, runId, lane, fleet, { input = null, slot = 'wor
|
|
|
577
586
|
// a kept session is told what this run is for (its card came back to it, with what happened since)
|
|
578
587
|
if (input) deliverNow(board, prev.address ?? `sc:${prev.machine}:claude-code:${prev.session_id}`, input, `board-run-${task.id}-r${runId}`);
|
|
579
588
|
} else if (prev.resumable !== false) {
|
|
580
|
-
|
|
581
|
-
|
|
589
|
+
// a resumed session is told what this run is for, as a kept one is: the run's own prompt (a reviewer resumed for
|
|
590
|
+
// its next round gets that round's prompt, its arc's context with it), not only that it was resumed
|
|
591
|
+
const told = input ? `The board resumed this session for this run of card ${task.id}.\n\n${input}` : `The board resumed this session after it was lost; you are still on card ${task.id}: ${task.title}. Carry on.`;
|
|
592
|
+
const r = sc([...base, '--key', `board-${task.id}-r${runId}-resume`, '--input', told, '--', '--resume', prev.session_id, ...tail], { timeout: 180_000, as: boardAddress(board.label) });
|
|
582
593
|
const pane = r.code === 0 ? lastJson(r.stdout)?.pane ?? null : null;
|
|
583
594
|
// a resume the harness refuses (its transcript is gone) ends the pane at once; another machine's launch
|
|
584
595
|
// answers before that shows, so the pane is looked for again a moment later
|
|
@@ -796,7 +807,8 @@ async function notify(board, fleet, report, entry) {
|
|
|
796
807
|
const events = board.db.prepare(`SELECT id, kind, payload, created_at FROM task_events WHERE task_id = ? AND id > ? AND kind IN (${kinds.map(() => '?').join(', ')}) ORDER BY id`)
|
|
797
808
|
.all(sub.task_id, sub.last_event_id, ...kinds);
|
|
798
809
|
if (!events.length) return;
|
|
799
|
-
|
|
810
|
+
// the card as the workflow names it (its status the workflow's: triaging, reviewing, stopped; `stored_as` kanban.db's)
|
|
811
|
+
const task = tx(board, (db) => { const t = getTask(db, sub.task_id); return t ? { ...t, status: statusOf(db, t), stored_as: t.status } : t; });
|
|
800
812
|
let cursor = Number(sub.last_event_id);
|
|
801
813
|
let failed = null;
|
|
802
814
|
try {
|
package/board/workflow.mjs
CHANGED
|
@@ -70,10 +70,11 @@ function pattern(p) {
|
|
|
70
70
|
return text.startsWith('(?i)') ? new RegExp(text.slice(4), 'i') : new RegExp(text);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
// the time of the latest commit
|
|
74
|
-
|
|
73
|
+
// the time of the latest commit that names `id` in its message, on any ref of the repository at `path` (a worktree's
|
|
74
|
+
// pushes land on the shared remote-tracking refs), or null (asked only when an expression does)
|
|
75
|
+
function lastCommitAt(path, id) {
|
|
75
76
|
if (!path) return null;
|
|
76
|
-
const r = spawnSync('git', ['-C', path, 'log', '-1', '--format=%ct', '
|
|
77
|
+
const r = spawnSync('git', ['-C', path, 'log', '--all', '-1', '--format=%ct', '--fixed-strings', `--grep=${id}`], { encoding: 'utf8', timeout: 10_000 });
|
|
77
78
|
const t = Number(r.stdout?.trim());
|
|
78
79
|
return r.status === 0 && Number.isFinite(t) && t > 0 ? t : null;
|
|
79
80
|
}
|
|
@@ -120,11 +121,11 @@ export function scopeOf(db, board, task, { params, event = {}, extra = {} } = {}
|
|
|
120
121
|
last_events: Object.fromEntries(all(db, 'SELECT e.kind, e.created_at, e.payload FROM task_events e JOIN (SELECT kind, MAX(id) AS id FROM task_events WHERE task_id = ? GROUP BY kind) l ON l.id = e.id', task.id)
|
|
121
122
|
.map((r) => [r.kind, { created_at: r.created_at, payload: json(r.payload, {}) ?? {} }])),
|
|
122
123
|
comments_since: (t) => all(db, 'SELECT author, body, created_at FROM task_comments WHERE task_id = ? AND created_at >= ?', task.id, t),
|
|
123
|
-
// the latest commit in
|
|
124
|
+
// the latest commit naming this card, in its workspace's repository (a subtask's: its arc's), as epoch seconds
|
|
124
125
|
last_commit_at: () => {
|
|
125
126
|
const own = task.workspace_kind !== 'scratch' ? task.workspace_path : null;
|
|
126
127
|
const arcWs = !own && task.subtask_of ? one(db, "SELECT workspace_path FROM tasks WHERE id = ? AND workspace_kind != 'scratch'", task.subtask_of)?.workspace_path : null;
|
|
127
|
-
return lastCommitAt(own ?? arcWs ?? null);
|
|
128
|
+
return lastCommitAt(own ?? arcWs ?? null, task.id);
|
|
128
129
|
},
|
|
129
130
|
};
|
|
130
131
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.47",
|
|
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": {
|