@volter/supercode-orchestrator 0.4.157 → 0.4.159
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/capacity.mjs +10 -6
- package/board/dispatch.mjs +10 -6
- package/package.json +1 -1
package/board/capacity.mjs
CHANGED
|
@@ -40,19 +40,22 @@ function sessionsOf(db, taskId) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* What one board holds now, as counted things: each card with a live run (`runs`), each card in any
|
|
44
|
-
* archived, once (`cards`; a cap's `where` names the statuses it counts), each live session its cards hold in any slot (`sessions`, those in a turn also
|
|
43
|
+
* What one board holds now, as counted things: each card with a live run (`runs`), each card (never a subtask) in any
|
|
44
|
+
* status but archived, once (`cards`; a cap's `where` names the statuses it counts), each live session its cards hold in any slot (`sessions`, those in a turn also
|
|
45
45
|
* `turns`). `alive(session)` and `liveRecord(session)` read the fleet; `modelOf(session)` is the model the session's
|
|
46
46
|
* own transcript reports it runs, or null where none can be read; `machineOf` normalises a machine name; `lanes` gives
|
|
47
47
|
* a profile's harness and model.
|
|
48
48
|
*/
|
|
49
|
-
export function holdings(board, { lanes, fleetOk, alive, liveRecord, modelOf = () => null, machineOf }) {
|
|
49
|
+
export function holdings(board, { lanes, fleetOk, alive, liveRecord, modelOf = () => null, storedOf = null, machineOf }) {
|
|
50
50
|
const out = [];
|
|
51
|
-
const rows = board.db.prepare("SELECT t.id, t.status, t.assignee, t.current_run_id, t.model_override, c.machine FROM tasks t LEFT JOIN supercode_cards c ON c.task_id = t.id WHERE t.status != 'archived'").all();
|
|
51
|
+
const rows = board.db.prepare("SELECT t.id, t.status, t.assignee, t.current_run_id, t.model_override, c.machine, c.subtask_of FROM tasks t LEFT JOIN supercode_cards c ON c.task_id = t.id WHERE t.status != 'archived'").all();
|
|
52
52
|
for (const row of rows) {
|
|
53
53
|
const lane = lanes[row.assignee] ?? {};
|
|
54
54
|
const card = {
|
|
55
55
|
card: row.id, board: board.slug, assignee: row.assignee ?? null, status: statusOf(board.db, row),
|
|
56
|
+
// what the board stores for an arc is read through its workflow's stored_as rules now, never the column a write has
|
|
57
|
+
// not yet brought up to date (a paused card counted as running until its row caught up)
|
|
58
|
+
stored: !row.subtask_of && storedOf ? storedOf(row.id) : row.status,
|
|
56
59
|
machine: row.machine ? machineOf(row.machine) : null,
|
|
57
60
|
model: row.model_override ?? lane.model ?? null, harness: lane.harness ?? null,
|
|
58
61
|
};
|
|
@@ -81,7 +84,8 @@ export function holdings(board, { lanes, fleetOk, alive, liveRecord, modelOf = (
|
|
|
81
84
|
out.push(...held);
|
|
82
85
|
// the card itself, whatever its runs and sessions: a cap says which by its status (a started card holds its slot
|
|
83
86
|
// until it is done); its model and harness are its run's session's, else its newest live session's, else its own
|
|
84
|
-
|
|
87
|
+
// a subtask is a task of its arc: it never runs or holds a slot of its own
|
|
88
|
+
if (!row.subtask_of) out.push({ ...(held[0] ?? { ...card, unconfigured: !card.model }), session: undefined, slot: undefined, counts: 'cards' });
|
|
85
89
|
}
|
|
86
90
|
return out;
|
|
87
91
|
}
|
|
@@ -161,7 +165,7 @@ export function capacity(caps, held, evaluate) {
|
|
|
161
165
|
for (const counts of ['runs', 'cards', 'sessions', 'turns', 'starts']) {
|
|
162
166
|
const had = things.find((x) => x.card === entry.card && x.counts === counts);
|
|
163
167
|
// the card is counted already: it is now in the status its start moved it to
|
|
164
|
-
if (had) { if (counts === 'cards') Object.assign(had, { status: entry.status, model: had.model ?? entry.model, harness: had.harness ?? entry.harness }); }
|
|
168
|
+
if (had) { if (counts === 'cards') Object.assign(had, { status: entry.status, stored: entry.stored, model: had.model ?? entry.model, harness: had.harness ?? entry.harness }); }
|
|
165
169
|
else things.push({ ...entry, counts });
|
|
166
170
|
}
|
|
167
171
|
},
|
package/board/dispatch.mjs
CHANGED
|
@@ -24,7 +24,7 @@ import { basename, dirname, join } from 'node:path';
|
|
|
24
24
|
import { createHash, randomUUID } from 'node:crypto';
|
|
25
25
|
import { fileURLToPath } from 'node:url';
|
|
26
26
|
import { view, boardCopyOf, boardPath, claimer, copyRefusal, event, json, listBoards, logsDir, now, openBoard, setActor, tx } from './store.mjs';
|
|
27
|
-
import { doors, fire, loadWorkflow, resumeOf, runSpec, runWorkingSeconds, requestSessionClose, retireSupersededRuns, refreshCardInputs, refreshRelationAnswers, transitionsFor, scopeOf, statusOf, templateValue, workflowFor } from './workflow.mjs';
|
|
27
|
+
import { doors, fire, loadWorkflow, resumeOf, runSpec, runWorkingSeconds, requestSessionClose, retireSupersededRuns, refreshCardInputs, refreshRelationAnswers, transitionsFor, scopeOf, statusOf, storedStatus, templateValue, workflowFor } from './workflow.mjs';
|
|
28
28
|
import { checkWorkspace, assertWorkspaceOwner, notePresence, resolveWorkspace } from './workspace.mjs';
|
|
29
29
|
import { capacity, harnessDefaults, holdings } from './capacity.mjs';
|
|
30
30
|
import { evaluate, holds, render } from './expr.mjs';
|
|
@@ -464,13 +464,17 @@ export function whereOf(board, task) {
|
|
|
464
464
|
const hostOf = (pressure) => ({ memory_pressure: pressure, max_in_progress: derivedMaxInProgress() });
|
|
465
465
|
|
|
466
466
|
/** What every board of the home at `root` holds now, counted for its caps (capacity.mjs). */
|
|
467
|
-
function homeHoldings(root, slugs, lanes, fleet) {
|
|
467
|
+
function homeHoldings(root, slugs, lanes, fleet, entry) {
|
|
468
468
|
const live = (s) => fleet.sessions?.find((x) => x.address === addressOf(s)) ?? null;
|
|
469
469
|
const out = [];
|
|
470
470
|
for (const slug of slugs) {
|
|
471
471
|
try {
|
|
472
472
|
const b = openBoard(root, slug);
|
|
473
|
-
try {
|
|
473
|
+
try {
|
|
474
|
+
b.slug ??= slug; b.label ??= boardLabel(root, slug);
|
|
475
|
+
const storedOf = (id) => storedStatus(b.db, b, entry, id).stored;
|
|
476
|
+
out.push(...holdings(b, { lanes, fleetOk: fleet.ok, alive: (s) => sessionAlive(fleet, s), liveRecord: live, modelOf: transcriptModel, storedOf, machineOf: normalMachine }));
|
|
477
|
+
}
|
|
474
478
|
finally { b.close(); }
|
|
475
479
|
} catch { /* its own tick reports it */ }
|
|
476
480
|
}
|
|
@@ -579,7 +583,7 @@ function startCards(board, fleet, lanes, settings, report, entry, effects, { onl
|
|
|
579
583
|
// the caps, over what the home holds now; what each candidate would be once started
|
|
580
584
|
const caps = capacity(d.capacity, held, evaluate);
|
|
581
585
|
const entryOf = (c) => ({ card: c.task.id, board: board.slug, machine: c.task.machine ? normalMachine(c.task.machine) : null, assignee: c.plan.profile ?? null,
|
|
582
|
-
status: c.plan.target, model: c.task.model_override ?? c.plan.lane?.model ?? held.defaults?.[c.plan.lane?.harness] ?? null, harness: c.plan.lane?.harness ?? null });
|
|
586
|
+
status: c.plan.target, stored: c.plan.target, model: c.task.model_override ?? c.plan.lane?.model ?? held.defaults?.[c.plan.lane?.harness] ?? null, harness: c.plan.lane?.harness ?? null });
|
|
583
587
|
const waitingEntries = candidates.map(entryOf);
|
|
584
588
|
// a dry run (dispatch --dry-run) plans the same way and writes nothing: no notes, no moves, no launches
|
|
585
589
|
const note = (id, why) => { if (!dry) tx(board, (db) => noteGuard(db, id, why)); };
|
|
@@ -1872,7 +1876,7 @@ export async function plan({ root, lanes, settings, slugs = null, params = {} })
|
|
|
1872
1876
|
const fleet = Object.values(lanes).some((l) => l.surface === 'pane') ? observeFleet() : { ok: false, alive: new Set(), online: new Set(), sessions: [], error: 'no pane lanes' };
|
|
1873
1877
|
const out = [];
|
|
1874
1878
|
// the home's caps count every board, whichever boards are planned
|
|
1875
|
-
const held = homeHoldings(root, listBoards(root), lanes, fleet);
|
|
1879
|
+
const held = homeHoldings(root, listBoards(root), lanes, fleet, entry);
|
|
1876
1880
|
const caps = capacity(entry.workflow.dispatch?.capacity, held, evaluate);
|
|
1877
1881
|
// what each cap counts now, before anything this plan would start
|
|
1878
1882
|
Object.defineProperty(out, 'capacity', { value: caps.view().map((cap) => ({ ...cap, groups: cap.groups.map((g) => ({ ...g, max: capMax(cap, g, entry, lanes) })) })) });
|
|
@@ -1982,7 +1986,7 @@ export async function tick({ root, lanes, settings, only = null, slugs = null, d
|
|
|
1982
1986
|
const fleetMs = Date.now() - fleetAt;
|
|
1983
1987
|
const boards = slugs ?? listBoards(root);
|
|
1984
1988
|
// what every board of the home holds, for caps whose scope is the whole home (kanban.max_in_progress counts so)
|
|
1985
|
-
const held = dispatch ? homeHoldings(root, boards, lanes, fleet) : [];
|
|
1989
|
+
const held = dispatch ? homeHoldings(root, boards, lanes, fleet, entry) : [];
|
|
1986
1990
|
const out = [];
|
|
1987
1991
|
for (const slug of boards) {
|
|
1988
1992
|
const report = { board: slug, ms: { fleet: fleetMs }, mailed: [], started: [], queued: [], failed: [], lost: [], crashed: [], timed_out: [], reclaimed: [], auto_blocked: [], promoted: 0, unassigned: [], nonspawnable: [], notified: [], undelivered: [], fleet: fleet.ok ? 'read' : fleet.error };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.159",
|
|
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": {
|