@volter/supercode-orchestrator 0.4.26 → 0.4.27

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.
@@ -23,7 +23,7 @@ import { fileURLToPath } from 'node:url';
23
23
  import { boardPath, event, json, listBoards, now, openBoard, tx } from './store.mjs';
24
24
  import { holdBoardTickLock } from '../hermes-locks.mjs';
25
25
  import {
26
- cardContext, claimIn, claimTtl, currentRun, DEFAULT_FAILURE_LIMIT, extendClaim, getTask, lastSession,
26
+ blockIn, cardContext, claimIn, claimTtl, currentRun, DEFAULT_FAILURE_LIMIT, extendClaim, getTask, lastSession,
27
27
  recomputeReady, recordFailure, release, setRunSession, subscribeIn, subscriptions,
28
28
  } from './engine.mjs';
29
29
 
@@ -943,9 +943,7 @@ function pursueGoals(board, fleet, settings, report) {
943
943
  const turns = session.worked_since_ask && !task.goal_mode ? 0 : Number(session.goal_turns ?? 0);
944
944
  const budget = task.goal_max_turns ?? settings.goalMaxTurns;
945
945
  if (turns >= budget) {
946
- db.prepare("UPDATE tasks SET status = 'blocked', claim_lock = NULL, claim_expires = NULL WHERE id = ?").run(id);
947
- const ended = endRun(db, id, { outcome: 'blocked', summary: `idle ${budget} times without deciding done or blocked` });
948
- event(db, id, 'blocked', { reason: `its session went idle ${budget} times without deciding done or blocked; review it`, kind: 'needs_input', source_status: 'running' }, ended);
946
+ blockIn(db, id, { reason: `its session went idle ${budget} times without deciding done or blocked; review it`, kind: 'needs_input' });
949
947
  return null;
950
948
  }
951
949
  setRunSession(db, runRow.id, { ...session, goal_turns: turns + 1, goal_nudged_at: now(), worked_since_ask: false });
package/board/engine.mjs CHANGED
@@ -396,25 +396,28 @@ function completeIn(board, id, { result = null, summary = null, metadata = null
396
396
  }
397
397
 
398
398
  export function block(board, id, { reason = null, kind = null } = {}) {
399
+ return tx(board, (db) => blockIn(db, id, { reason, kind }));
400
+ }
401
+
402
+ /** `block` inside the caller's transaction (the dispatcher's own blocks keep the same recurrence accounting). */
403
+ export function blockIn(db, id, { reason = null, kind = null } = {}) {
399
404
  if (kind && !BLOCK_KINDS.includes(kind)) throw new Error(`block kind is one of ${BLOCK_KINDS.join(', ')}`);
400
- return tx(board, (db) => {
401
- const task = must(db, id);
402
- if (!['running', 'ready'].includes(task.status)) throw new Error(`${id} is ${task.status}; only a running or ready card blocks`);
403
- const source = task.status === 'running' ? retryStatus(db, id) : 'ready';
404
- if (kind === 'dependency') {
405
- run(db, "UPDATE tasks SET status = 'todo', claim_lock = NULL, claim_expires = NULL, worker_pid = NULL, block_kind = ? WHERE id = ?", kind, id);
406
- const runId = endRun(db, id, { outcome: 'blocked', summary: reason }) ?? (reason ? synthesizeRun(db, id, { outcome: 'blocked', summary: reason }) : null);
407
- event(db, id, 'dependency_wait', { reason, kind, source_status: source }, runId);
408
- return 'todo';
409
- }
410
- const recurrences = task.block_kind === kind ? Number(task.block_recurrences || 0) + 1 : 1;
411
- const loop = recurrences >= BLOCK_RECURRENCE_LIMIT;
412
- const status = loop ? 'triage' : 'blocked';
413
- run(db, 'UPDATE tasks SET status = ?, claim_lock = NULL, claim_expires = NULL, worker_pid = NULL, block_kind = ?, block_recurrences = ? WHERE id = ?', status, kind, recurrences, id);
405
+ const task = must(db, id);
406
+ if (!['running', 'ready'].includes(task.status)) throw new Error(`${id} is ${task.status}; only a running or ready card blocks`);
407
+ const source = task.status === 'running' ? retryStatus(db, id) : 'ready';
408
+ if (kind === 'dependency') {
409
+ run(db, "UPDATE tasks SET status = 'todo', claim_lock = NULL, claim_expires = NULL, worker_pid = NULL, block_kind = ? WHERE id = ?", kind, id);
414
410
  const runId = endRun(db, id, { outcome: 'blocked', summary: reason }) ?? (reason ? synthesizeRun(db, id, { outcome: 'blocked', summary: reason }) : null);
415
- event(db, id, loop ? 'block_loop_detected' : 'blocked', { reason, kind, recurrences, ...(loop ? { limit: BLOCK_RECURRENCE_LIMIT } : {}), source_status: source }, runId);
416
- return status;
417
- });
411
+ event(db, id, 'dependency_wait', { reason, kind, source_status: source }, runId);
412
+ return 'todo';
413
+ }
414
+ const recurrences = task.block_kind === kind ? Number(task.block_recurrences || 0) + 1 : 1;
415
+ const loop = recurrences >= BLOCK_RECURRENCE_LIMIT;
416
+ const status = loop ? 'triage' : 'blocked';
417
+ run(db, 'UPDATE tasks SET status = ?, claim_lock = NULL, claim_expires = NULL, worker_pid = NULL, block_kind = ?, block_recurrences = ? WHERE id = ?', status, kind, recurrences, id);
418
+ const runId = endRun(db, id, { outcome: 'blocked', summary: reason }) ?? (reason ? synthesizeRun(db, id, { outcome: 'blocked', summary: reason }) : null);
419
+ event(db, id, loop ? 'block_loop_detected' : 'blocked', { reason, kind, recurrences, ...(loop ? { limit: BLOCK_RECURRENCE_LIMIT } : {}), source_status: source }, runId);
420
+ return status;
418
421
  }
419
422
 
420
423
  export function unblock(board, id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.4.26",
3
+ "version": "0.4.27",
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": {