@volter/supercode-orchestrator 0.5.62 → 0.5.64
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/ci.mjs +3 -0
- package/board/dispatch.mjs +20 -3
- package/board/machine-fleet.mjs +3 -0
- package/board/runtime-door.mjs +4 -0
- package/package.json +1 -1
package/board/ci.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { readFileSync, realpathSync, writeFileSync, renameSync, statSync } from
|
|
|
5
5
|
import { dirname, join, relative } from 'node:path';
|
|
6
6
|
import { createHash } from 'node:crypto';
|
|
7
7
|
import { branchCheckouts, checkoutOf, isLocalWorkspace, resolveWorkspace } from './workspace.mjs';
|
|
8
|
+
import { noteStep } from '@volter/supercode-harness-sdk/slow-log';
|
|
8
9
|
|
|
9
10
|
// GitHub is read through its REST API with Node's own fetch, not the gh binary: Node takes a World's trust bundle and
|
|
10
11
|
// injector (NODE_EXTRA_CA_CERTS, NODE_OPTIONS), so a review World's GitHub twin answers it, where gh (Go) trusts only
|
|
@@ -35,7 +36,9 @@ function github(path, all = false) {
|
|
|
35
36
|
const env = token ? { ...process.env, GH_TOKEN: token } : process.env;
|
|
36
37
|
return spawnSync(process.execPath, ['--input-type=module', '-e', GITHUB_READ, path, all ? '1' : '0'], { env, encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024 });
|
|
37
38
|
};
|
|
39
|
+
const started = performance.now();
|
|
38
40
|
let result = read();
|
|
41
|
+
noteStep('github read', performance.now() - started);
|
|
39
42
|
if (result.status !== 0 && !fixed && loginToken && /^GitHub 401 /.test(result.stderr ?? '')) { loginToken = null; result = read(); }
|
|
40
43
|
if (result.status !== 0) throw new Error(`GitHub: ${(result.stderr || result.error?.message || 'read failed').trim().slice(-500)}`);
|
|
41
44
|
return JSON.parse(result.stdout);
|
package/board/dispatch.mjs
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
// `workflow dispatch`) is harmless: every act of a round is a compare-and-set claim, a transaction that re-reads what it
|
|
17
17
|
// acts on and does nothing when another round already acted (see `tick`). Every side effect follows a committed claim, so
|
|
18
18
|
// a crash between the two steps is answered by the next round.
|
|
19
|
+
import { noteStep } from '@volter/supercode-harness-sdk/slow-log';
|
|
19
20
|
import { monitorsRuns, failedObservation, surfaceIncident, auditEndedRuns, originOf } from './incidents.mjs';
|
|
20
21
|
import { readMachineFleet } from './machine-fleet.mjs';
|
|
21
22
|
import { boardLabel, boardName } from '@volter/teams/board-name';
|
|
@@ -77,7 +78,9 @@ function sc(args, { input = null, timeout = 120_000, as = null } = {}) {
|
|
|
77
78
|
// `as`: the board this
|
|
78
79
|
// command acts for, so a card's pane is started and closed by its board, whichever session ran the board's verb
|
|
79
80
|
const env = commandEnv(as);
|
|
81
|
+
const started = performance.now();
|
|
80
82
|
const r = spawnSync(supercodeBin(), args, { cwd: tmpdir(), input: input ?? undefined, encoding: 'utf8', timeout, env, maxBuffer: 512 * 1024 * 1024 });
|
|
83
|
+
noteStep(`supercode ${args[0]}`, performance.now() - started);
|
|
81
84
|
return { code: r.status, stdout: r.stdout ?? '', stderr: (r.stderr ?? '') + (r.error ? r.error.message : '') };
|
|
82
85
|
}
|
|
83
86
|
|
|
@@ -2393,7 +2396,7 @@ export async function plan({ root, lanes, settings, slugs = null, params = {} })
|
|
|
2393
2396
|
const board = openBoard(root, slug);
|
|
2394
2397
|
try {
|
|
2395
2398
|
board.label = boardLabel(root, slug);
|
|
2396
|
-
await activatePullRequestReviews(board, entry, report, [], { dry: true });
|
|
2399
|
+
await activatePullRequestReviews(board, entry, report, [], { dry: true, fleet });
|
|
2397
2400
|
startCards(board, fleet, lanes, settings, report, entry, [], { dry: true, held });
|
|
2398
2401
|
} finally { board.close(); }
|
|
2399
2402
|
out.push(report);
|
|
@@ -2414,7 +2417,19 @@ function noCodeReviewDue(board, id) {
|
|
|
2414
2417
|
|
|
2415
2418
|
/** An opened PR asks for the declared review transition once the arc's tasks are closed. */
|
|
2416
2419
|
// A task written in the card's own Tasks section that did not become a subtask holds its review too.
|
|
2417
|
-
|
|
2420
|
+
/** The arc's session still in a turn: its review, and the close of that session the request brings (end_run), wait for
|
|
2421
|
+
* the turn to end, so work in flight is never cut (t_f34710bc's coder had a proof take running when its review was
|
|
2422
|
+
* requested at 15:01:13Z on 2026-10-04, and the close ended it). A session the reading cannot place waits on nothing. */
|
|
2423
|
+
function turnInFlight(board, id, fleet) {
|
|
2424
|
+
if (!fleet?.ok) return null;
|
|
2425
|
+
const session = currentRun(board.db, id)?.metadata?.supercode;
|
|
2426
|
+
if (!session?.session_id || session.surface === 'headless' || session.close_requested) return null;
|
|
2427
|
+
let turn = fleet.sessions?.find((x) => x.address === addressOf(session))?.turn ?? null;
|
|
2428
|
+
if (turn == null && session.surface === 'native') try { turn = nativeReading(nativeSessions(session.machine, session.harness ?? 'claude-code', session.session_id), session).row?.activity?.turn ?? null; } catch { /* unread: waits on nothing */ }
|
|
2429
|
+
return turn === 'working' ? `its session ${addressOf(session)} is in a turn; the review is requested once the turn ends` : null;
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
async function activatePullRequestReviews(board, entry, report, effects, { only = null, dry = false, fleet = null } = {}) {
|
|
2418
2433
|
const candidates = view(board, db => db.prepare(`SELECT t.id FROM tasks t JOIN supercode_cards c ON c.task_id=t.id
|
|
2419
2434
|
WHERE c.subtask_of IS NULL AND c.every IS NULL
|
|
2420
2435
|
AND t.workspace_kind!='scratch' ${only ? 'AND t.id=?' : ''}`).all(...(only ? [only] : [])));
|
|
@@ -2432,6 +2447,8 @@ async function activatePullRequestReviews(board, entry, report, effects, { only
|
|
|
2432
2447
|
const ready = view(board, eligible);
|
|
2433
2448
|
if (!ready) continue;
|
|
2434
2449
|
if (ready !== true) { report.queued.push([id, `review waits: ${ready.length} open task(s) in the card's Tasks: ${ready[0].id} ${ready[0].title}`]); continue; }
|
|
2450
|
+
const inTurn = turnInFlight(board, id, fleet);
|
|
2451
|
+
if (inTurn) { report.queued.push([id, `review waits: ${inTurn}`]); continue; }
|
|
2435
2452
|
let payload = null;
|
|
2436
2453
|
try {
|
|
2437
2454
|
payload = openReviewPullRequests(board, id);
|
|
@@ -2601,7 +2618,7 @@ export async function tick({ root, lanes, settings, only = null, slugs = null, d
|
|
|
2601
2618
|
report.unsettled = [];
|
|
2602
2619
|
report.promoted = recomputeReady(board, effects, report.unsettled);
|
|
2603
2620
|
tx(board,db=>auditEndedRuns(db,board,entry));
|
|
2604
|
-
if (dispatch) await activatePullRequestReviews(board, entry, report, effects, { only });
|
|
2621
|
+
if (dispatch) await activatePullRequestReviews(board, entry, report, effects, { only, fleet });
|
|
2605
2622
|
if (dispatch && !stopping) startCards(board, fleet, lanes, settings, report, entry, effects, { only, held });
|
|
2606
2623
|
phase('start');
|
|
2607
2624
|
if (dispatch && !only && !report.paused) observeIdle(board, fleet, settings, report, entry, effects);
|
package/board/machine-fleet.mjs
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// not linked (`machine_offline`): then it is offline. This machine's door not answering is no reading at all.
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
12
|
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { noteStep } from '@volter/supercode-harness-sdk/slow-log';
|
|
13
14
|
|
|
14
15
|
const entry = fileURLToPath(new URL('../bin/machine-fleet.mjs', import.meta.url));
|
|
15
16
|
const DEADLINE_MS = 10_000;
|
|
@@ -17,8 +18,10 @@ const DEADLINE_MS = 10_000;
|
|
|
17
18
|
/** One reading of `machines` (normalized names) and this machine, `local`. */
|
|
18
19
|
export function readMachineFleet(machines, local) {
|
|
19
20
|
const names = [...new Set([local, ...machines])];
|
|
21
|
+
const started = performance.now();
|
|
20
22
|
const reply = spawnSync(process.execPath, [entry], { input: JSON.stringify({ machines: names.map((name) => ({ name, at: name === local ? null : name })), deadlineMs: DEADLINE_MS }),
|
|
21
23
|
encoding: 'utf8', timeout: DEADLINE_MS + 5_000, maxBuffer: 64 * 1024 * 1024 });
|
|
24
|
+
noteStep(`fleet reading (${names.length} machine${names.length === 1 ? '' : 's'})`, performance.now() - started);
|
|
22
25
|
let rows = null;
|
|
23
26
|
try { rows = JSON.parse(String(reply.stdout).trim().split('\n').pop()); } catch { /* no reading */ }
|
|
24
27
|
// `panes`: each answering machine's live pane ids, whether or not a session was read in them
|
package/board/runtime-door.mjs
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { noteStep } from '@volter/supercode-harness-sdk/slow-log';
|
|
3
4
|
const entry = fileURLToPath(new URL('../bin/runtime-door.mjs',import.meta.url));
|
|
4
5
|
|
|
5
6
|
/** Public machine RPC only; no Teams binary or implementation/state-file access. */
|
|
6
7
|
export function runtimeDoor(machine,method,params={}, {env=process.env,timeout=60_000,as=null}={}) {
|
|
8
|
+
// a step of the running command (a dispatch round's slow-log line names its doors, and their time, by method)
|
|
9
|
+
const started = performance.now();
|
|
7
10
|
const result = spawnSync(process.execPath,[entry],{
|
|
8
11
|
input:JSON.stringify({machine,method,params}),encoding:'utf8',timeout,
|
|
9
12
|
env:{...env,...(as?{SUPERCODE_CALLER:as}:{})},maxBuffer:512*1024*1024,
|
|
10
13
|
});
|
|
14
|
+
noteStep(`door ${method}${machine ? ' (another machine)' : ''}`, performance.now() - started);
|
|
11
15
|
return {code:result.status,stdout:result.stdout??'',stderr:(result.stderr??'')+(result.error?.message??'')};
|
|
12
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.64",
|
|
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": {
|