@volter/supercode-orchestrator 0.5.58 → 0.5.60
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 +15 -9
- package/package.json +1 -1
package/board/dispatch.mjs
CHANGED
|
@@ -206,7 +206,8 @@ function unpublishedAlive(session) {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
/** Native activity comes from the machine's harness discovery, not catalogue age. One discovery (up to 2000
|
|
209
|
-
* sessions, seconds each) serves a round's every native session on that machine
|
|
209
|
+
* sessions, seconds each) serves a round's every native session on that machine: taken once per round (tick clears
|
|
210
|
+
* them), however long the round runs. A round of 163 s took it 28 times when a reading lasted 15 s. */
|
|
210
211
|
const discoveries = new Map();
|
|
211
212
|
// A machine's pane list and harness discovery are read before a board write opens, never inside one: a door that
|
|
212
213
|
// takes seconds would hold the board's write lock past a worker's own command's busy wait. A write that needs a
|
|
@@ -222,7 +223,7 @@ function readBefore(fleet, session) {
|
|
|
222
223
|
}
|
|
223
224
|
function nativeSessions(machine, harness) {
|
|
224
225
|
const key = `${normalMachine(machine)}\u0000${harness}`, seen = discoveries.get(key);
|
|
225
|
-
if (seen
|
|
226
|
+
if (seen) return seen.sessions;
|
|
226
227
|
if (readingsOnly) throw unavailable('native liveness is read before a board write, not inside it');
|
|
227
228
|
const sessions = discoverNative(machine, harness);
|
|
228
229
|
discoveries.set(key, { at: Date.now(), sessions });
|
|
@@ -640,7 +641,7 @@ function startCards(board, fleet, lanes, settings, report, entry, effects, { onl
|
|
|
640
641
|
const candidates = [];
|
|
641
642
|
const waiting = (task, why) => {
|
|
642
643
|
report.queued.push([task.id, why]);
|
|
643
|
-
if (!dry) tx(board, db => noteGuard(db, task.id, why));
|
|
644
|
+
if (!dry && !guardNoted(board.db, task.id, why)) tx(board, db => noteGuard(db, task.id, why));
|
|
644
645
|
};
|
|
645
646
|
for (const task of everyCard) {
|
|
646
647
|
if (only && task.id !== only) continue;
|
|
@@ -673,7 +674,7 @@ function startCards(board, fleet, lanes, settings, report, entry, effects, { onl
|
|
|
673
674
|
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 });
|
|
674
675
|
const waitingEntries = candidates.map(entryOf);
|
|
675
676
|
// a dry run (dispatch --dry-run) plans the same way and writes nothing: no notes, no moves, no launches
|
|
676
|
-
const note = (id, why) => { if (!dry) tx(board, (db) => noteGuard(db, id, why)); };
|
|
677
|
+
const note = (id, why) => { if (!dry && !guardNoted(board.db, id, why)) tx(board, (db) => noteGuard(db, id, why)); };
|
|
677
678
|
for (const [i, c] of candidates.entries()) {
|
|
678
679
|
const { task, plan, scope } = c;
|
|
679
680
|
if (!plan.profile) { report.unassigned.push(task.id); note(task.id, 'no profile runs it (no assignee, and the workflow names none)'); continue; }
|
|
@@ -714,7 +715,7 @@ function startCards(board, fleet, lanes, settings, report, entry, effects, { onl
|
|
|
714
715
|
} catch (error) {
|
|
715
716
|
const reason = error.refusal ?? String(error.message).slice(-300);
|
|
716
717
|
// another round's start is that round's to say; this one writes nothing for it
|
|
717
|
-
if (!error.claimedElsewhere) tx(board, (db) => noteGuard(db, task.id, reason));
|
|
718
|
+
if (!error.claimedElsewhere && !guardNoted(board.db, task.id, reason)) tx(board, (db) => noteGuard(db, task.id, reason));
|
|
718
719
|
report.queued.push([task.id, reason]);
|
|
719
720
|
continue;
|
|
720
721
|
}
|
|
@@ -1247,12 +1248,16 @@ function memoryPressure() {
|
|
|
1247
1248
|
|
|
1248
1249
|
/** Record a guard reason once per change, not once per tick. */
|
|
1249
1250
|
function noteGuard(db, id, reason) {
|
|
1250
|
-
|
|
1251
|
-
|
|
1251
|
+
if (guardNoted(db, id, reason)) return;
|
|
1252
|
+
event(db, id, 'respawn_guarded', { reason });
|
|
1253
|
+
}
|
|
1254
|
+
/** Whether `reason` is already noted: once per reason per entry into the status (a card back in ready, a new `since`, is
|
|
1255
|
+
* noted again, so the workflow's after-timers that read the reason, card.queue_reason, see it). Read before a write
|
|
1256
|
+
* is opened too: a card that waits for the same reason round after round costs no transaction. */
|
|
1257
|
+
function guardNoted(db, id, reason) {
|
|
1252
1258
|
const since = Number(db.prepare('SELECT since FROM supercode_cards WHERE task_id = ?').get(id)?.since ?? 0);
|
|
1253
1259
|
const last = db.prepare("SELECT payload FROM task_events WHERE task_id = ? AND kind IN ('respawn_guarded', 'claimed') AND created_at >= ? ORDER BY id DESC LIMIT 1").get(id, since);
|
|
1254
|
-
|
|
1255
|
-
event(db, id, 'respawn_guarded', { reason });
|
|
1260
|
+
return json(last?.payload, {})?.reason === reason;
|
|
1256
1261
|
}
|
|
1257
1262
|
|
|
1258
1263
|
/** Hermes's emergency stop: the `ESTOP` sentinel in the home or in `~/.hermes` stops new starts (running ones go on). */
|
|
@@ -2555,6 +2560,7 @@ export async function deliver({ root, slugs = null }) {
|
|
|
2555
2560
|
*/
|
|
2556
2561
|
export async function tick({ root, lanes, settings, only = null, slugs = null, dispatch = true, params = {}, deploymentReceipt = false }) {
|
|
2557
2562
|
fleetRoot = root;
|
|
2563
|
+
discoveries.clear();
|
|
2558
2564
|
// a verb's flags (dispatch --max, --failure-limit) are params of this tick, read by the workflow as its own
|
|
2559
2565
|
const deployment = deploymentReceipt ? workflowRevision(root) : null;
|
|
2560
2566
|
const loaded = await loadWorkflow(root, { fresh: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.60",
|
|
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": {
|