@volter/supercode-orchestrator 0.4.27 → 0.4.28
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 -14
- package/package.json +1 -1
package/board/dispatch.mjs
CHANGED
|
@@ -475,7 +475,7 @@ function launchPane(board, task, runId, lane, fleet, { input = null } = {}) {
|
|
|
475
475
|
if (prev && prev.machine === machine) {
|
|
476
476
|
if (sessionAlive(fleet, prev)) {
|
|
477
477
|
// the session is kept; the heartbeat's count belongs to the run that ended, so the new run starts it again
|
|
478
|
-
const { missing_since: _m, goal_turns: _t, goal_nudged_at: _n,
|
|
478
|
+
const { missing_since: _m, goal_turns: _t, goal_nudged_at: _n, ...kept } = prev;
|
|
479
479
|
session = { ...kept, mode: 'adopt', launched_at: now(), seen_at: now() };
|
|
480
480
|
} else if (prev.resumable !== false) {
|
|
481
481
|
const r = sc([...base, '--key', `board-${task.id}-r${runId}-resume`, '--input',
|
|
@@ -915,8 +915,10 @@ function readMailbox(board, address, report) {
|
|
|
915
915
|
* The board's heartbeat for a pane session: a running card's session never sits idle without deciding. Each tick, a
|
|
916
916
|
* session that is idle while its card is still running is asked to decide: `request-review` when the work is done,
|
|
917
917
|
* `block` with its kind when it cannot go on (waiting on a person, a capability, another card), or keep working. A
|
|
918
|
-
* goal card (Hermes's goal loop) is told to keep going.
|
|
919
|
-
*
|
|
918
|
+
* goal card (Hermes's goal loop) is told to keep going. Idle is judged by the session's last message time (supercode
|
|
919
|
+
* reads it from the transcript), never by its status label: a session is asked once its last message is a whole tick
|
|
920
|
+
* old; one whose messages ran on a whole tick past the last ask answered it by working, and its count starts again
|
|
921
|
+
* (a reply to the ask alone is not work). After the turn budget (`goal_max_turns`, else
|
|
920
922
|
* `kanban.goal_max_turns`) of asks in a row with no work and no decision (a goal card: of turns), the card is blocked `needs_input` and its creator is told.
|
|
921
923
|
* Whether the work is done is the session's call through its card, not an auxiliary judge's.
|
|
922
924
|
*/
|
|
@@ -930,23 +932,22 @@ function pursueGoals(board, fleet, settings, report) {
|
|
|
930
932
|
const session = runRow?.metadata?.supercode;
|
|
931
933
|
if (!session?.session_id || session.surface !== 'pane') return null;
|
|
932
934
|
const live = fleet.sessions.find((x) => x.address?.endsWith(`:${session.session_id}`));
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
return null;
|
|
939
|
-
}
|
|
940
|
-
if (!session.idle_since) { setRunSession(db, runRow.id, { ...session, idle_since: now() }); return null; }
|
|
941
|
-
if (now() - session.idle_since < settings.interval) return null;
|
|
935
|
+
// a supercode that reports no last message time gives no reading, and no reading gives no verdict
|
|
936
|
+
const lastAt = Math.floor(Number(live.last_message_at_ms) / 1000);
|
|
937
|
+
if (!(lastAt > 0)) return null;
|
|
938
|
+
// a message within the last tick is a session working or between turns, not idle
|
|
939
|
+
if (now() - lastAt < settings.interval) return null;
|
|
942
940
|
if (session.goal_nudged_at && now() - session.goal_nudged_at < settings.interval * 2) return null;
|
|
943
|
-
|
|
941
|
+
// messages that ran on a whole tick past the last ask answered it by working: the count starts again (a goal
|
|
942
|
+
// card keeps Hermes's budget of turns)
|
|
943
|
+
const worked = Boolean(session.goal_nudged_at) && lastAt >= session.goal_nudged_at + settings.interval;
|
|
944
|
+
const turns = worked && !task.goal_mode ? 0 : Number(session.goal_turns ?? 0);
|
|
944
945
|
const budget = task.goal_max_turns ?? settings.goalMaxTurns;
|
|
945
946
|
if (turns >= budget) {
|
|
946
947
|
blockIn(db, id, { reason: `its session went idle ${budget} times without deciding done or blocked; review it`, kind: 'needs_input' });
|
|
947
948
|
return null;
|
|
948
949
|
}
|
|
949
|
-
setRunSession(db, runRow.id, { ...session, goal_turns: turns + 1, goal_nudged_at: now()
|
|
950
|
+
setRunSession(db, runRow.id, { ...session, goal_turns: turns + 1, goal_nudged_at: now() });
|
|
950
951
|
event(db, id, task.goal_mode ? 'goal_continued' : 'decision_asked', { turn: turns + 1, budget }, runRow.id);
|
|
951
952
|
const local = normalMachine(task.machine) === localMachine();
|
|
952
953
|
const where = local ? `--root ${board.root}${board.slug !== 'default' ? ` --board ${board.slug}` : ''}` : `--at ${boardAddress(board.label)}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.28",
|
|
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": {
|