@volter/supercode-orchestrator 0.5.58 → 0.5.59

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.
Files changed (2) hide show
  1. package/board/dispatch.mjs +11 -7
  2. package/package.json +1 -1
@@ -640,7 +640,7 @@ function startCards(board, fleet, lanes, settings, report, entry, effects, { onl
640
640
  const candidates = [];
641
641
  const waiting = (task, why) => {
642
642
  report.queued.push([task.id, why]);
643
- if (!dry) tx(board, db => noteGuard(db, task.id, why));
643
+ if (!dry && !guardNoted(board.db, task.id, why)) tx(board, db => noteGuard(db, task.id, why));
644
644
  };
645
645
  for (const task of everyCard) {
646
646
  if (only && task.id !== only) continue;
@@ -673,7 +673,7 @@ function startCards(board, fleet, lanes, settings, report, entry, effects, { onl
673
673
  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
674
  const waitingEntries = candidates.map(entryOf);
675
675
  // 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)); };
676
+ const note = (id, why) => { if (!dry && !guardNoted(board.db, id, why)) tx(board, (db) => noteGuard(db, id, why)); };
677
677
  for (const [i, c] of candidates.entries()) {
678
678
  const { task, plan, scope } = c;
679
679
  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 +714,7 @@ function startCards(board, fleet, lanes, settings, report, entry, effects, { onl
714
714
  } catch (error) {
715
715
  const reason = error.refusal ?? String(error.message).slice(-300);
716
716
  // 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));
717
+ if (!error.claimedElsewhere && !guardNoted(board.db, task.id, reason)) tx(board, (db) => noteGuard(db, task.id, reason));
718
718
  report.queued.push([task.id, reason]);
719
719
  continue;
720
720
  }
@@ -1247,12 +1247,16 @@ function memoryPressure() {
1247
1247
 
1248
1248
  /** Record a guard reason once per change, not once per tick. */
1249
1249
  function noteGuard(db, id, reason) {
1250
- // once per reason per entry into the status: a card back in ready (a new `since`) is noted again, so the workflow's
1251
- // after-timers that read the reason (card.queue_reason) see it
1250
+ if (guardNoted(db, id, reason)) return;
1251
+ event(db, id, 'respawn_guarded', { reason });
1252
+ }
1253
+ /** Whether `reason` is already noted: once per reason per entry into the status (a card back in ready, a new `since`, is
1254
+ * noted again, so the workflow's after-timers that read the reason, card.queue_reason, see it). Read before a write
1255
+ * is opened too: a card that waits for the same reason round after round costs no transaction. */
1256
+ function guardNoted(db, id, reason) {
1252
1257
  const since = Number(db.prepare('SELECT since FROM supercode_cards WHERE task_id = ?').get(id)?.since ?? 0);
1253
1258
  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
- if (json(last?.payload, {})?.reason === reason) return;
1255
- event(db, id, 'respawn_guarded', { reason });
1259
+ return json(last?.payload, {})?.reason === reason;
1256
1260
  }
1257
1261
 
1258
1262
  /** Hermes's emergency stop: the `ESTOP` sentinel in the home or in `~/.hermes` stops new starts (running ones go on). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.5.58",
3
+ "version": "0.5.59",
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": {