@volter/supercode-orchestrator 0.5.74 → 0.5.75
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/cli.mjs +19 -2
- package/board/store.mjs +1 -1
- package/board/ztrack.mjs +8 -8
- package/package.json +1 -1
package/board/cli.mjs
CHANGED
|
@@ -20,6 +20,8 @@ import { takeEpoch } from './fence.mjs';
|
|
|
20
20
|
import { dispatcherNotice, holdOwnerHealth, holdRound, holdSwitch } from './owner-health.mjs';
|
|
21
21
|
import { boardTool } from './tools.mjs';
|
|
22
22
|
import { recordSlow, takeSteps } from '@volter/supercode-harness-sdk/slow-log';
|
|
23
|
+
// read by name, so an older harness SDK without them still loads: the owner then keeps no per-verb or loop lines
|
|
24
|
+
import * as slowLog from '@volter/supercode-harness-sdk/slow-log';
|
|
23
25
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
24
26
|
import { fileURLToPath } from 'node:url';
|
|
25
27
|
import { homedir, tmpdir, userInfo } from 'node:os';
|
|
@@ -1518,8 +1520,20 @@ async function answerVerbs(root, log) {
|
|
|
1518
1520
|
return () => { server.close(); try { unlinkSync(path); } catch { /* gone */ } lock.release(); };
|
|
1519
1521
|
}
|
|
1520
1522
|
|
|
1521
|
-
/** One request to the owner, answered whole: the verb run in the caller's call, its output kept for the answer.
|
|
1523
|
+
/** One request to the owner, answered whole: the verb run in the caller's call, its output kept for the answer. A
|
|
1524
|
+
* verb that takes more than a second is a slow line of its own, with the steps that ended while it ran (its own and,
|
|
1525
|
+
* in this one process, any other call's that held it). */
|
|
1522
1526
|
async function answerOne(root, line) {
|
|
1527
|
+
const began = performance.now();
|
|
1528
|
+
let named = null, by = null;
|
|
1529
|
+
try { return await answerRequest(root, line, (verb, caller) => { named = verb; by = caller; }); }
|
|
1530
|
+
finally {
|
|
1531
|
+
const ms = performance.now() - began;
|
|
1532
|
+
if (named) recordSlow({ kind: 'call', name: `owner verb ${named}`, ms, slowest: null, extra: { caller: by, steps: slowLog.stepsWithin?.(began, performance.now()) ?? null } });
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
async function answerRequest(root, line, naming) {
|
|
1523
1537
|
try {
|
|
1524
1538
|
const request = JSON.parse(line);
|
|
1525
1539
|
const tool = request?.tool && typeof request.tool.name === 'string' ? request.tool : null;
|
|
@@ -1529,6 +1543,7 @@ async function answerOne(root, line) {
|
|
|
1529
1543
|
if (BOARD_OPERATION_VERBS.has(verb)) return { code: 1, stdout: '', stderr: `supercode workflow: ${verb} is run on the board's machine as its own act, not sent to the owner\n` };
|
|
1530
1544
|
const session = request.session && typeof request.session.id === 'string' && ['claude-code', 'codex'].includes(request.session.harness) ? request.session : null;
|
|
1531
1545
|
const caller = typeof request.caller === 'string' ? request.caller : session ? `sc:${localMachine()}:${session.harness}:${session.id}` : null;
|
|
1546
|
+
naming(tool ? `tool ${tool.name}` : verb, caller);
|
|
1532
1547
|
const facts = Object.fromEntries(Object.entries(request.facts ?? {}).filter(([key, value]) => CALLER_FACTS.includes(key) && typeof value === 'string'));
|
|
1533
1548
|
// a caller names its Teams context (the CLI and the daemon always do): one that names none is refused before anything
|
|
1534
1549
|
// is done, never answered with the owner's
|
|
@@ -1630,6 +1645,8 @@ async function serve(root, args = {}) {
|
|
|
1630
1645
|
try { (await import('../hermes-cli.mjs')).hermesInstall(); } catch { /* none installed */ }
|
|
1631
1646
|
let closeVerbs;
|
|
1632
1647
|
try { closeVerbs = await answerVerbs(root, log); } catch (error) { unfollowHome(); throw error; }
|
|
1648
|
+
// a held event loop is every caller's wait at once: each hold over a second is a slow line naming what held it
|
|
1649
|
+
const unwatchLoop = slowLog.watchEventLoop?.({ name: 'board owner event loop blocked' });
|
|
1633
1650
|
log(`owning the boards of ${root} on ${localMachine()} (orchestrator ${running ?? 'unknown'}); dispatching where a board's dispatching is on (\`supercode workflow dispatching\`)`);
|
|
1634
1651
|
events = watchBoard({ root, binary: supercodeBin(), env: commandEnv(), log });
|
|
1635
1652
|
// The board's events are published by this machine's connector, not by the dispatcher (D137, D138 step 4): the home is
|
|
@@ -1718,7 +1735,7 @@ async function serve(root, args = {}) {
|
|
|
1718
1735
|
} finally {
|
|
1719
1736
|
// a fetch in flight lands, and what it brought is merged, while this owner still holds the home's lock
|
|
1720
1737
|
try { const { settleDocuments } = await import('./git-document.mjs'); await settleDocuments(); } catch { /* nothing in flight */ }
|
|
1721
|
-
closeVerbs();
|
|
1738
|
+
unwatchLoop?.(); closeVerbs();
|
|
1722
1739
|
unfollowHome();
|
|
1723
1740
|
await closeDoors();
|
|
1724
1741
|
events?.close();
|
package/board/store.mjs
CHANGED
|
@@ -217,7 +217,7 @@ export const tx = (board, fn) => {
|
|
|
217
217
|
const caller = /at (?:async )?([\w.$<>]+) /.exec(String(new Error().stack).split('\n')[2] ?? '')?.[1] ?? 'unknown';
|
|
218
218
|
const started = performance.now();
|
|
219
219
|
try {
|
|
220
|
-
const result = board.tx(db => {const result=fn(db);recordCardPublications(db,actorOf());return result;});
|
|
220
|
+
const result = board.tx(db => {const result=fn(db);const began=performance.now();try{recordCardPublications(db,actorOf());}finally{noteStep('board tx publications',performance.now()-began);}return result;});
|
|
221
221
|
signalBoardWrite(board.root, actorOf());
|
|
222
222
|
return result;
|
|
223
223
|
} finally { noteStep(`board tx from ${caller}`, performance.now() - started); }
|
package/board/ztrack.mjs
CHANGED
|
@@ -17,6 +17,7 @@ import { DatabaseSync } from 'node:sqlite';
|
|
|
17
17
|
import { actorOf, contention, event, json, now, principalOf } from './store.mjs';
|
|
18
18
|
import { GitDocument } from './git-document.mjs';
|
|
19
19
|
import { noteStep, recordSlow } from '@volter/supercode-harness-sdk/slow-log';
|
|
20
|
+
import * as slowLog from '@volter/supercode-harness-sdk/slow-log';
|
|
20
21
|
|
|
21
22
|
/** Run `fn` as a named step of the running command (the slow log names its slowest step). */
|
|
22
23
|
const timedStep = (step, fn) => { const started = performance.now(); try { return fn(); } finally { noteStep(step, performance.now() - started); } };
|
|
@@ -100,7 +101,7 @@ class ZtrackBoard {
|
|
|
100
101
|
const said = current().said;
|
|
101
102
|
if (this.git && !said.has(`behind:${this.path}`)) {
|
|
102
103
|
said.add(`behind:${this.path}`);
|
|
103
|
-
const late = this.git.behind();
|
|
104
|
+
const late = timedStep('board open git behind', () => this.git.behind());
|
|
104
105
|
// A push younger than a minute is still on its way.
|
|
105
106
|
if (late && Date.now() - late.since > 60_000) current().err(`board: warning: ${late.commits} board document commit${late.commits === 1 ? '' : 's'} not published since ${new Date(late.since).toISOString().slice(0, 16)}Z${late.error ? ` (last push: ${late.error})` : ''}; the dispatcher's next round retries\n`);
|
|
106
107
|
}
|
|
@@ -112,12 +113,12 @@ class ZtrackBoard {
|
|
|
112
113
|
// `sqlite3 <store> "select …"` made the empty file the next release then opened instead of importing).
|
|
113
114
|
if (existsSync(this.file) && statSync(this.file).size === 0) unlinkSync(this.file);
|
|
114
115
|
if (!existsSync(this.file)) this.create(legacy);
|
|
115
|
-
this.conn = new DatabaseSync(this.file);
|
|
116
|
+
this.conn = timedStep('board open connection', () => new DatabaseSync(this.file));
|
|
116
117
|
this.refuseUnimported(legacy);
|
|
117
118
|
this.errors = new Map(); this.statements = new Map(); this.hashes = new Map();
|
|
118
119
|
this.active = false; this.overlay = false; this.seen = null; this.refused = new Set();
|
|
119
|
-
this.prepareConnection();
|
|
120
|
-
this.loadErrors();
|
|
120
|
+
timedStep('board open schema', () => this.prepareConnection());
|
|
121
|
+
timedStep('board open errors', () => this.loadErrors());
|
|
121
122
|
const self = this;
|
|
122
123
|
this.db = {
|
|
123
124
|
boardErrors: self.errors,
|
|
@@ -396,8 +397,7 @@ class ZtrackBoard {
|
|
|
396
397
|
try {
|
|
397
398
|
txStarted = performance.now();
|
|
398
399
|
this.dropOverlay();
|
|
399
|
-
this.conn.exec('BEGIN');
|
|
400
|
-
fenced(this.conn);
|
|
400
|
+
timedStep('board tx begin', () => { this.conn.exec('BEGIN'); fenced(this.conn); });
|
|
401
401
|
this.active = true; this.contended = false;
|
|
402
402
|
this.conn.exec('DELETE FROM temp.board_dirty; DELETE FROM temp.board_touched');
|
|
403
403
|
this.refused = new Set();
|
|
@@ -418,12 +418,12 @@ class ZtrackBoard {
|
|
|
418
418
|
this.put('pending', { intent, files });
|
|
419
419
|
this.put('pending_hashes', Object.fromEntries(files.map((f) => [f.role, { before: f.before, after: f.after }])));
|
|
420
420
|
}
|
|
421
|
-
this.conn.exec('COMMIT');
|
|
421
|
+
timedStep('board tx commit', () => this.conn.exec('COMMIT'));
|
|
422
422
|
// A long transaction holds every other writer of this board (the dispatcher's tick included), so it is a line
|
|
423
423
|
// of its own in the slow log, from whichever process ran it.
|
|
424
424
|
const held = performance.now() - txStarted;
|
|
425
425
|
noteStep('board transaction', held);
|
|
426
|
-
recordSlow({ kind: 'call', name: 'board transaction', ms: held, slowest: null, extra: { board: this.path } });
|
|
426
|
+
recordSlow({ kind: 'call', name: 'board transaction', ms: held, slowest: null, extra: { board: this.path, steps: slowLog.stepsWithin?.(txStarted, performance.now()) ?? null } });
|
|
427
427
|
outcome = { result, files, intent, recovered };
|
|
428
428
|
} catch (error) {
|
|
429
429
|
try { this.conn.exec('ROLLBACK'); } catch { /* not begun */ }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.75",
|
|
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": {
|