@volter/supercode-orchestrator 0.5.197 → 0.5.199
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/ci.mjs +8 -2
- package/board/dispatch.mjs +3 -1
- package/board/store.mjs +20 -0
- package/board/workflow.mjs +71 -44
- package/package.json +3 -3
package/board/ci.mjs
CHANGED
|
@@ -197,8 +197,12 @@ function checkoutPresent(path) {
|
|
|
197
197
|
* workspace and a branch, e.g. `create "<what>" --subtask-of <arc> --workspace worktree:<repository> --branch <name>`.
|
|
198
198
|
* Their PRs are the arc's whatever the branch is named. */
|
|
199
199
|
function registeredBranches(board, id) {
|
|
200
|
+
// Keep the two keys in their own lookups. An OR across the joined tables makes SQLite scan every task.
|
|
201
|
+
// Exclude the arc from the second arm even if a malformed record names itself as its subtask.
|
|
200
202
|
const rows = board.db.prepare(`SELECT t.branch_name, t.workspace_kind, c.workspace_anchor FROM tasks t JOIN supercode_cards c ON c.task_id=t.id
|
|
201
|
-
WHERE
|
|
203
|
+
WHERE t.id=? AND t.status != 'cancelled' AND t.workspace_kind IN ('worktree','dir') AND t.branch_name IS NOT NULL
|
|
204
|
+
UNION ALL SELECT t.branch_name, t.workspace_kind, c.workspace_anchor FROM supercode_cards c JOIN tasks t ON t.id=c.task_id
|
|
205
|
+
WHERE c.subtask_of=? AND t.id!=? AND t.status != 'cancelled' AND t.workspace_kind IN ('worktree','dir') AND t.branch_name IS NOT NULL`).all(id, id, id);
|
|
202
206
|
const out = [];
|
|
203
207
|
for (const row of rows) {
|
|
204
208
|
if (!row.workspace_anchor || /^(\/|~|[A-Za-z]:[\\/])/.test(row.workspace_anchor)) continue;
|
|
@@ -374,7 +378,9 @@ async function commitTime({ url, head }) {
|
|
|
374
378
|
* a review request naming that head, before the next request. A head is reviewed once. */
|
|
375
379
|
export function judgedHead(board, id, head) {
|
|
376
380
|
if (!head) return null;
|
|
377
|
-
|
|
381
|
+
// A request's JSON head list is checked once before visiting its verdicts. Without CROSS JOIN SQLite starts
|
|
382
|
+
// from every verdict and reparses the same older requests for each of them (including heads never requested).
|
|
383
|
+
return board.db.prepare(`SELECT v.id, v.kind FROM task_events r CROSS JOIN task_events v ON v.task_id = r.task_id
|
|
378
384
|
AND v.kind IN ('changes_requested', 'review_pass') AND v.id > r.id
|
|
379
385
|
AND v.id < COALESCE((SELECT MIN(n.id) FROM task_events n WHERE n.task_id = r.task_id AND n.kind = 'review_requested' AND n.id > r.id), 9223372036854775807)
|
|
380
386
|
AND NOT EXISTS (SELECT 1 FROM task_events x WHERE x.task_id=r.task_id AND x.kind='review_voided' AND x.id>v.id AND json_extract(x.payload,'$.review_request')=r.id)
|
package/board/dispatch.mjs
CHANGED
|
@@ -300,7 +300,9 @@ const nativeKey = (machine, harness, sessionId) => `${normalMachine(machine)}\u0
|
|
|
300
300
|
async function discoverNative(machine, harness, sessionId) {
|
|
301
301
|
if (offlineMachine(machine)) throw unavailable(`native liveness unavailable: machine ${normalMachine(machine)} is offline`);
|
|
302
302
|
// the machine's own harness door, this one's or another's, as every other harness read here is
|
|
303
|
-
|
|
303
|
+
// Liveness uses the native activity receipt, never transcript previews. A name miss can match many retained
|
|
304
|
+
// rows; opening every one for its messages delays the board's liveness decision for data it never reads.
|
|
305
|
+
const result = await doorOn(machine, 'harness.v1.sessions.discover', { harnesses: [harness], query: sessionId, limit: 2000, include_latest_candidates: false }, { timeout: NATIVE_DISCOVERY_MS });
|
|
304
306
|
const page = result.code === 0 ? lastJson(result.stdout) : null;
|
|
305
307
|
if (!Array.isArray(page?.sessions)) throw unavailable(`native liveness unavailable on ${machine}: ${(result.stderr || result.stdout).trim().slice(-300)}`);
|
|
306
308
|
// whole: every source read, nothing truncated, from an index that keeps every session's own row (subscriberGone)
|
package/board/store.mjs
CHANGED
|
@@ -237,6 +237,25 @@ function layOutSummaryIndex(db) {
|
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
// Human card reads ask for insertion order. The older task/timestamp and task/kind indexes filter the card but
|
|
241
|
+
// sort its whole history (payloads included) on the owner's thread. Keep those indexes for their other queries;
|
|
242
|
+
// these carry only the card key and row id. Report each one-time creation before it holds the connection.
|
|
243
|
+
function layOutHistoryIndexes(db) {
|
|
244
|
+
for (const [table, index] of [['task_events', 'idx_events_task_id'], ['task_comments', 'idx_comments_task_id'], ['task_runs', 'idx_runs_task_id']]) {
|
|
245
|
+
if (indexed(db, index)) continue;
|
|
246
|
+
const report = text => { writeSync(2, text); if (current().kind === 'caller') current().err(text); };
|
|
247
|
+
report(`board: creating index ${index}: one-time history scan and index write on the owner connection\n`);
|
|
248
|
+
const began = performance.now();
|
|
249
|
+
let made = false;
|
|
250
|
+
try { db.exec(`CREATE INDEX IF NOT EXISTS ${index} ON ${table}(task_id, id)`); made = true; }
|
|
251
|
+
finally {
|
|
252
|
+
const ms = performance.now() - began;
|
|
253
|
+
noteStep(`board open index ${index}`, ms);
|
|
254
|
+
report(`board: index ${index} ${made ? 'created' : 'creation failed'} after ${Math.round(ms)} ms\n`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
240
259
|
/** Hermes's tables on a fresh board, supercode's own table and columns on every one. */
|
|
241
260
|
export function layOut(db, { fresh }) {
|
|
242
261
|
if (fresh) db.exec(SCHEMA);
|
|
@@ -249,6 +268,7 @@ export function layOut(db, { fresh }) {
|
|
|
249
268
|
// any statement is prepared; no statement names it, so a store without it is only slower.
|
|
250
269
|
db.exec('CREATE INDEX IF NOT EXISTS idx_supercode_cards_subtask_of ON supercode_cards(subtask_of)');
|
|
251
270
|
layOutEventIndex(db);
|
|
271
|
+
layOutHistoryIndexes(db);
|
|
252
272
|
// A covering summary index keeps human listings out of task records' body overflow pages.
|
|
253
273
|
layOutSummaryIndex(db);
|
|
254
274
|
// The calling session's run (CALLER_RUN_ADDRESS) and its cards (SESSION_CURRENT_RUNS, SESSION_BOUND, SESSION_RUNS):
|
package/board/workflow.mjs
CHANGED
|
@@ -383,33 +383,36 @@ function timeOf(db, task) {
|
|
|
383
383
|
function askedOf(id) { return mailboxAnswers.get(id)?.askedOf ?? null; }
|
|
384
384
|
|
|
385
385
|
/** The scope an expression is evaluated in: the card (with its relations), the event, params, time, extras. */
|
|
386
|
-
export function scopeOf(db, board, task, { params, event = {}, extra = {} } = {}) {
|
|
386
|
+
export function scopeOf(db, board, task, { params, event = {}, extra = {}, lazy = false } = {}) {
|
|
387
|
+
// Only read-only guards opt into demand reads. Mutation scopes materialize before any write,
|
|
388
|
+
// keeping `before` and run-history fields pinned to their original snapshot.
|
|
389
|
+
const once = (read) => { let done = false, value; return () => { if (!done) { value = read(); done = true; } return value; }; };
|
|
387
390
|
const status = statusOf(db, task);
|
|
388
391
|
// a related card's status is the workflow's, as the card's own is (`stored_as`: what kanban.db holds)
|
|
389
392
|
const related = 'COALESCE(c.stage, t.status) AS status, t.status AS stored_as';
|
|
390
|
-
const parents = all(db, `SELECT t.id, ${related}, t.title FROM tasks t JOIN task_links l ON l.parent_id = t.id LEFT JOIN supercode_cards c ON c.task_id = t.id WHERE l.child_id = ?`, task.id);
|
|
391
|
-
const children = all(db, `SELECT t.id, ${related} FROM tasks t JOIN task_links l ON l.child_id = t.id LEFT JOIN supercode_cards c ON c.task_id = t.id WHERE l.parent_id = ?`, task.id);
|
|
392
|
-
const lastRun = one(db, 'SELECT * FROM task_runs WHERE task_id = ? AND ended_at IS NOT NULL ORDER BY ended_at DESC, id DESC LIMIT 1', task.id);
|
|
393
|
-
const lastCompleted = one(db, "SELECT * FROM task_runs WHERE task_id = ? AND outcome = 'completed' ORDER BY ended_at DESC LIMIT 1", task.id);
|
|
394
|
-
const asked = json(one(db, "SELECT payload FROM task_events WHERE task_id = ? AND kind = 'review_requested' ORDER BY id DESC LIMIT 1", task.id)?.payload, {}) ?? {};
|
|
395
|
-
const changes = json(one(db, "SELECT payload FROM task_events WHERE task_id = ? AND kind = 'changes_requested' ORDER BY id DESC LIMIT 1", task.id)?.payload, {}) ?? {};
|
|
396
|
-
const interruption = json(one(db, `SELECT payload FROM task_events WHERE task_id = ? AND kind IN ('blocked', 'block_loop_detected', 'dependency_wait', 'gave_up',
|
|
393
|
+
const parents = once(() => all(db, `SELECT t.id, ${related}, t.title FROM tasks t JOIN task_links l ON l.parent_id = t.id LEFT JOIN supercode_cards c ON c.task_id = t.id WHERE l.child_id = ?`, task.id));
|
|
394
|
+
const children = once(() => all(db, `SELECT t.id, ${related} FROM tasks t JOIN task_links l ON l.child_id = t.id LEFT JOIN supercode_cards c ON c.task_id = t.id WHERE l.parent_id = ?`, task.id));
|
|
395
|
+
const lastRun = once(() => one(db, 'SELECT * FROM task_runs WHERE task_id = ? AND ended_at IS NOT NULL ORDER BY ended_at DESC, id DESC LIMIT 1', task.id));
|
|
396
|
+
const lastCompleted = once(() => one(db, "SELECT * FROM task_runs WHERE task_id = ? AND outcome = 'completed' ORDER BY ended_at DESC LIMIT 1", task.id));
|
|
397
|
+
const asked = once(() => json(one(db, "SELECT payload FROM task_events WHERE task_id = ? AND kind = 'review_requested' ORDER BY id DESC LIMIT 1", task.id)?.payload, {}) ?? {});
|
|
398
|
+
const changes = once(() => json(one(db, "SELECT payload FROM task_events WHERE task_id = ? AND kind = 'changes_requested' ORDER BY id DESC LIMIT 1", task.id)?.payload, {}) ?? {});
|
|
399
|
+
const interruption = once(() => json(one(db, `SELECT payload FROM task_events WHERE task_id = ? AND kind IN ('blocked', 'block_loop_detected', 'dependency_wait', 'gave_up',
|
|
397
400
|
'unblocked', 'changes_requested', 'review_reopened', 'status', 'reclaimed', 'stale', 'timed_out', 'crashed', 'spawn_failed', 'rate_limited', 'session_lost')
|
|
398
|
-
ORDER BY id DESC LIMIT 1`, task.id)?.payload, {}) ?? {};
|
|
399
|
-
const lastBlock = one(db, "SELECT kind, payload FROM task_events WHERE task_id = ? AND kind IN ('blocked', 'unblocked', 'dependency_wait') ORDER BY id DESC LIMIT 1", task.id);
|
|
400
|
-
const waitingOn = lastBlock?.kind === 'blocked' ? json(lastBlock.payload, {})?.waiting_on ?? null : null;
|
|
401
|
-
const currentRun = task.current_run_id ? one(db, 'SELECT metadata FROM task_runs WHERE id = ?', task.current_run_id) : null;
|
|
402
|
-
const session = json(currentRun?.metadata, {})?.supercode ?? {};
|
|
401
|
+
ORDER BY id DESC LIMIT 1`, task.id)?.payload, {}) ?? {});
|
|
402
|
+
const lastBlock = once(() => one(db, "SELECT kind, payload FROM task_events WHERE task_id = ? AND kind IN ('blocked', 'unblocked', 'dependency_wait') ORDER BY id DESC LIMIT 1", task.id));
|
|
403
|
+
const waitingOn = once(() => lastBlock()?.kind === 'blocked' ? json(lastBlock().payload, {})?.waiting_on ?? null : null);
|
|
404
|
+
const currentRun = once(() => task.current_run_id ? one(db, 'SELECT metadata FROM task_runs WHERE id = ?', task.current_run_id) : null);
|
|
405
|
+
const session = once(() => json(currentRun()?.metadata, {})?.supercode ?? {});
|
|
403
406
|
const state = one(db, 'SELECT * FROM supercode_cards WHERE task_id = ?', task.id) ?? {};
|
|
404
407
|
const blocks = json(state.blocked_by, []) ?? [];
|
|
405
408
|
const card = {
|
|
406
409
|
...task,
|
|
407
|
-
creator_address
|
|
408
|
-
completion_owner_address
|
|
409
|
-
latest_review
|
|
410
|
-
review_candidate
|
|
410
|
+
get creator_address() { return creatorOf(db, task.id); },
|
|
411
|
+
get completion_owner_address() { return completionOwnerOf(db, task.id); },
|
|
412
|
+
get latest_review() { return latestReview(db, task.id) ?? {}; },
|
|
413
|
+
get review_candidate() { return reviewCandidate(board, task.id) ?? {}; },
|
|
411
414
|
ci: completionEvidence(board, task.id),
|
|
412
|
-
dispatch_hold
|
|
415
|
+
get dispatch_hold() { return one(db, "SELECT kind FROM task_events WHERE task_id=? AND kind IN ('dispatch_held','dispatch_released','session_adopted') ORDER BY id DESC LIMIT 1", task.id)?.kind === 'dispatch_held'; },
|
|
413
416
|
status,
|
|
414
417
|
blocked_by: blocks,
|
|
415
418
|
paused: json(state.paused, null),
|
|
@@ -419,8 +422,8 @@ export function scopeOf(db, board, task, { params, event = {}, extra = {} } = {}
|
|
|
419
422
|
|
|
420
423
|
stored_as: task.status,
|
|
421
424
|
board: board.slug,
|
|
422
|
-
parents,
|
|
423
|
-
children,
|
|
425
|
+
get parents() { return parents(); },
|
|
426
|
+
get children() { return children(); },
|
|
424
427
|
acceptance_complete: () => {
|
|
425
428
|
const lines = String(task.body ?? '').split('\n');
|
|
426
429
|
let acceptance = false;
|
|
@@ -431,33 +434,38 @@ export function scopeOf(db, board, task, { params, event = {}, extra = {} } = {}
|
|
|
431
434
|
return /^\s*[-*] \[[xX]\] .+: \S.+$/.test(line);
|
|
432
435
|
});
|
|
433
436
|
},
|
|
434
|
-
counters
|
|
437
|
+
get counters() { return { failures: Number(task.consecutive_failures || 0), block_recurrences: Number(task.block_recurrences || 0), goal_turns: Number(session().goal_turns || 0) }; },
|
|
435
438
|
goal_mode: Boolean(task.goal_mode),
|
|
436
|
-
implementer
|
|
437
|
-
last_reviewer
|
|
438
|
-
arc
|
|
439
|
+
get implementer() { return asked().implementer ?? task.assignee; },
|
|
440
|
+
get last_reviewer() { return changes().reviewer ?? null; },
|
|
441
|
+
get arc() { return task.subtask_of ? one(db, `SELECT t.id, ${related}, t.title, t.body, t.assignee FROM tasks t LEFT JOIN supercode_cards c ON c.task_id = t.id WHERE t.id = ?`, task.subtask_of) ?? null : null; },
|
|
439
442
|
// the cards filed as its subtasks (`create --subtask-of`), in the order they were filed
|
|
440
|
-
subtasks
|
|
441
|
-
queue_reason
|
|
442
|
-
task.id, Number(one(db, 'SELECT since FROM supercode_cards WHERE task_id = ?', task.id)?.since ?? 0))?.payload, {})?.reason ?? null,
|
|
443
|
+
get subtasks() { return all(db, `SELECT t.id, ${related}, t.title, t.assignee FROM tasks t JOIN supercode_cards c ON c.task_id = t.id WHERE c.subtask_of = ? ORDER BY t.created_at`, task.id); },
|
|
444
|
+
get queue_reason() { return json(one(db, "SELECT payload FROM task_events WHERE task_id = ? AND kind = 'respawn_guarded' AND created_at >= ? ORDER BY id DESC LIMIT 1",
|
|
445
|
+
task.id, Number(one(db, 'SELECT since FROM supercode_cards WHERE task_id = ?', task.id)?.since ?? 0))?.payload, {})?.reason ?? null; },
|
|
443
446
|
// the message whose answer the standing block waits for (`block --waiting-on`), and that answer's id once it has landed
|
|
444
|
-
waiting_on
|
|
445
|
-
answer: () => answerTo(waitingOn),
|
|
447
|
+
get waiting_on() { return waitingOn(); },
|
|
448
|
+
answer: () => answerTo(waitingOn()),
|
|
446
449
|
// the seconds its runs spent, by the role each run was for (implementer: coding, reviewer: reviewing, …), an open
|
|
447
450
|
// run counted to now; `waiting` is the rest of its life since it was filed
|
|
448
|
-
time
|
|
451
|
+
get time() { return timeOf(db, task); },
|
|
449
452
|
// whether an edit of its text only ticks outcome lines (the card's own session's door to its acceptance)
|
|
450
453
|
only_ticks: (body) => onlyTicks(task.body, body),
|
|
451
|
-
asked_of: () => askedOf(waitingOn),
|
|
452
|
-
last_block_event
|
|
454
|
+
asked_of: () => askedOf(waitingOn()),
|
|
455
|
+
get last_block_event() { return one(db, "SELECT kind FROM task_events WHERE task_id = ? AND kind IN ('blocked', 'unblocked') ORDER BY id DESC LIMIT 1", task.id)?.kind ?? null; },
|
|
453
456
|
// where the latest interruption says the card resumes (any status the workflow declares); none recorded: null
|
|
454
|
-
resume_status
|
|
455
|
-
last_run
|
|
456
|
-
last_completed
|
|
457
|
+
get resume_status() { const value = interruption(); return value.resume_status ?? value.retry_status ?? value.source_status ?? null; },
|
|
458
|
+
get last_run() { return lastRun() ?? {}; },
|
|
459
|
+
get last_completed() { return lastCompleted() ?? null; },
|
|
457
460
|
events_since: (t, kinds = []) => all(db, `SELECT kind FROM task_events WHERE task_id = ? AND created_at >= ?${kinds.length ? ` AND kind IN (${kinds.map(() => '?').join(', ')})` : ''}`, task.id, t, ...kinds),
|
|
458
461
|
// the latest event of each kind on the card: kind → { created_at, payload }
|
|
459
|
-
last_events
|
|
460
|
-
.
|
|
462
|
+
get last_events() {
|
|
463
|
+
const events = Object.fromEntries(all(db, 'SELECT e.id, e.kind, e.created_at, e.payload FROM task_events e JOIN (SELECT kind, MAX(id) AS id FROM task_events WHERE task_id = ? GROUP BY kind) l ON l.id = e.id', task.id)
|
|
464
|
+
.map((r) => [r.kind, { id: r.id, created_at: r.created_at, payload: json(r.payload, {}) ?? {} }]));
|
|
465
|
+
const runMeta = json(currentRun()?.metadata, {}) ?? {};
|
|
466
|
+
for (const e of [...Object.values(runMeta.last_events ?? {}), ...(runMeta.events ?? [])]) events[e.kind] = { created_at: e.at, payload: e.payload ?? {} };
|
|
467
|
+
return events;
|
|
468
|
+
},
|
|
461
469
|
comments_since: (t) => all(db, 'SELECT author, body, created_at FROM task_comments WHERE task_id = ? AND created_at >= ?', task.id, t),
|
|
462
470
|
// the latest commit naming this card on its work branches and default branch, in its workspace's repository (a
|
|
463
471
|
// subtask's: its arc's), as epoch seconds
|
|
@@ -467,9 +475,21 @@ export function scopeOf(db, board, task, { params, event = {}, extra = {} } = {}
|
|
|
467
475
|
return lastCommitAt(own ?? arcWs ?? null, task.id);
|
|
468
476
|
},
|
|
469
477
|
};
|
|
470
|
-
|
|
471
|
-
for (const
|
|
472
|
-
|
|
478
|
+
// Cache each field for this scope only. Never share a history snapshot between calls or writes.
|
|
479
|
+
for (const [key, property] of Object.entries(Object.getOwnPropertyDescriptors(card))) {
|
|
480
|
+
if (!property.get) continue;
|
|
481
|
+
const read = () => {
|
|
482
|
+
const value = property.get.call(card);
|
|
483
|
+
Object.defineProperty(card, key, { value, writable: true, enumerable: true, configurable: true });
|
|
484
|
+
return value;
|
|
485
|
+
};
|
|
486
|
+
Object.defineProperty(card, key, { get: read, enumerable: true, configurable: true });
|
|
487
|
+
if (!lazy) read();
|
|
488
|
+
}
|
|
489
|
+
for (const [key, expr] of Object.entries(loaded.get(board.root)?.workflow?.derived ?? {})) {
|
|
490
|
+
const value = evaluate(expr, { card, event, params, now: now() });
|
|
491
|
+
Object.defineProperty(card, key, { value, writable: true, enumerable: true, configurable: true });
|
|
492
|
+
}
|
|
473
493
|
return {
|
|
474
494
|
card,
|
|
475
495
|
requester: actorOf(),
|
|
@@ -694,10 +714,17 @@ export function settle(db, board, entry, id, effects = []) {
|
|
|
694
714
|
for (let hops = 0; hops < 16; hops += 1) {
|
|
695
715
|
const task = cardOf(db, id);
|
|
696
716
|
const from = statusOf(db, task);
|
|
697
|
-
const
|
|
698
|
-
|
|
717
|
+
const state = workflow.statuses[from];
|
|
718
|
+
// An unchanged card with no automatic/timed moves needs no history scope at all. The organization's five
|
|
719
|
+
// statuses have none, but recomputeReady used to read every history field on every unsettled card anyway.
|
|
720
|
+
if (!state?.always?.length && !state?.after?.length) { projectStatus(db, board, entry, id); return effects; }
|
|
721
|
+
// Timed moves may record their fired marker in dueAfter: pin their scope before that write. Other guards
|
|
722
|
+
// remain read-only until a transition is selected, then capture every `before` field before take mutates it.
|
|
723
|
+
const scope = scopeOf(db, board, task, { params, lazy: !state?.after?.length, extra: { lanes: lanesIn(entry) } });
|
|
724
|
+
let t = (state?.always ?? []).find((x) => holds(x.guard ?? null, scope));
|
|
699
725
|
if (!t) t = dueAfter(db, workflow, task, from, scope);
|
|
700
726
|
if (!t) { projectStatus(db, board, entry, id); return effects; }
|
|
727
|
+
Object.values(scope.card);
|
|
701
728
|
const to = take(db, board, entry, task, from, t, scope, effects);
|
|
702
729
|
if (to === from) return effects;
|
|
703
730
|
}
|
|
@@ -1225,7 +1252,7 @@ export function fireRun(db, board, entry, id, name, { roles = [], payload = {},
|
|
|
1225
1252
|
|
|
1226
1253
|
function relationActive(db, board, entry, task) {
|
|
1227
1254
|
const policy = entry.workflow.relations?.blocked_by;
|
|
1228
|
-
return Boolean(policy) && holds(policy.guard ?? null, scopeOf(db, board, task, { params: entry.params }));
|
|
1255
|
+
return Boolean(policy) && holds(policy.guard ?? null, scopeOf(db, board, task, { params: entry.params, lazy: true }));
|
|
1229
1256
|
}
|
|
1230
1257
|
function settleRelations(db, board, entry, id, effects) {
|
|
1231
1258
|
if (!relationActive(db, board, entry, cardOf(db, id))) return;
|
|
@@ -1266,7 +1293,7 @@ export function storedStatus(db, board, entry, id) {
|
|
|
1266
1293
|
const task = cardOf(db, id);
|
|
1267
1294
|
const status = statusOf(db, task);
|
|
1268
1295
|
if (!entry.workflow.stored_as?.length) return { status, stored: task.status };
|
|
1269
|
-
const scope = scopeOf(db, board, task, { params: entry.params });
|
|
1296
|
+
const scope = scopeOf(db, board, task, { params: entry.params, lazy: true });
|
|
1270
1297
|
const rule = entry.workflow.stored_as.find((r) => holds(r.guard, scope));
|
|
1271
1298
|
return { status, stored: rule?.status ?? storedAs(entry.workflow, status) };
|
|
1272
1299
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.199",
|
|
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": {
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"check-types": "node scripts/generate-types.mjs --check"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@volter/supercode-teams": "^0.3.
|
|
31
|
+
"@volter/supercode-teams": "^0.3.332",
|
|
32
32
|
"@volter/supercode-terminal": "^0.3.8",
|
|
33
33
|
"@volter/supercode-harness-sdk": "^0.3.101",
|
|
34
|
-
"@volter/teams": "0.2.
|
|
34
|
+
"@volter/teams": "0.2.92",
|
|
35
35
|
"@volter/ztrack": "^2.4.23",
|
|
36
36
|
"yaml": "^2.9.0"
|
|
37
37
|
},
|