@volter/supercode-orchestrator 0.4.78 → 0.4.80
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/workflow.mjs +26 -4
- package/board/ztrack.mjs +5 -3
- package/package.json +1 -1
package/board/workflow.mjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// the engine's primitives (the rows Hermes's tables hold); the I/O an action asks for (stopping a worker, closing a
|
|
6
6
|
// pane, sending a session a message, cleaning a workspace) is answered as effects the caller runs after commit.
|
|
7
7
|
import { spawnSync } from 'node:child_process';
|
|
8
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
9
9
|
import { resolve, relative, isAbsolute } from 'node:path';
|
|
10
10
|
import { randomBytes } from 'node:crypto';
|
|
11
11
|
import { actorOf, event as record, json, now } from './store.mjs';
|
|
@@ -78,11 +78,33 @@ function pattern(p) {
|
|
|
78
78
|
|
|
79
79
|
// the time of the latest commit that names `id` in its message, on any ref of the repository at `path` (a worktree's
|
|
80
80
|
// pushes land on the shared remote-tracking refs), or null (asked only when an expression does)
|
|
81
|
+
const commitTimes = new Map();
|
|
81
82
|
function lastCommitAt(path, id) {
|
|
82
83
|
if (!path) return null;
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
84
|
+
const key = `${path}:${id}`;
|
|
85
|
+
const cached = commitTimes.get(key);
|
|
86
|
+
if (cached && now() - cached.at < 15) return cached.value;
|
|
87
|
+
const readCommit = (repo) => {
|
|
88
|
+
const r = spawnSync('git', ['-C', repo, 'log', '--all', '-1', '--format=%ct', '--fixed-strings', `--grep=${id}`], { encoding: 'utf8', timeout: 10_000 });
|
|
89
|
+
const value = Number(r.stdout?.trim());
|
|
90
|
+
return { repo: r.status === 0, value: Number.isFinite(value) && value > 0 ? value : null };
|
|
91
|
+
};
|
|
92
|
+
const own = readCommit(path);
|
|
93
|
+
let value = own.value;
|
|
94
|
+
if (!own.repo) {
|
|
95
|
+
// A fleet card may span sibling repositories under its declared workspace.
|
|
96
|
+
// Only direct children with a Git door participate; never scan arbitrary home trees.
|
|
97
|
+
let entries = []; try { entries = readdirSync(path, { withFileTypes: true }); } catch {}
|
|
98
|
+
for (const child of entries) {
|
|
99
|
+
if (!child.isDirectory() && !child.isSymbolicLink()) continue;
|
|
100
|
+
const repo = resolve(path, child.name);
|
|
101
|
+
if (!existsSync(resolve(repo, '.git'))) continue;
|
|
102
|
+
const t = readCommit(repo).value;
|
|
103
|
+
if (t != null) value = Math.max(value ?? 0, t);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
commitTimes.set(key, { at: now(), value });
|
|
107
|
+
return value;
|
|
86
108
|
}
|
|
87
109
|
|
|
88
110
|
/** The first answer to message `id` in its sender's mailbox (`supercode message show --replies`), as its id; or null. */
|
package/board/ztrack.mjs
CHANGED
|
@@ -140,13 +140,15 @@ class ZtrackBoard {
|
|
|
140
140
|
const status = old.stage ?? task.status;
|
|
141
141
|
const mapped = source.mapping[status];
|
|
142
142
|
if (!mapped) throw new Error(`migration needs an explicit mapping for ${status} (${task.id})`);
|
|
143
|
-
|
|
143
|
+
let stage = typeof mapped === 'string' ? mapped : mapped.status;
|
|
144
|
+
if (mapped.preserve_completed && task.completed_at) stage = 'done';
|
|
144
145
|
const parents = this.mem.prepare('SELECT parent_id FROM task_links WHERE child_id = ?').all(task.id).map((p) => ({ id: p.parent_id, kind: 'card' }));
|
|
145
146
|
const last = this.mem.prepare("SELECT kind, payload FROM task_events WHERE task_id = ? AND kind IN ('blocked','unblocked') ORDER BY id DESC LIMIT 1").get(task.id);
|
|
146
147
|
const wait = last?.kind === 'blocked' ? json(last.payload, {})?.waiting_on : null;
|
|
147
148
|
if (wait) parents.push({ id: wait, kind: 'message' });
|
|
148
149
|
this.insert('supercode_cards', { ...old, task_id: task.id, stage, archived: Number(Boolean(mapped.archived) || stage === 'cancelled'), blocked_by: JSON.stringify(parents),
|
|
149
|
-
|
|
150
|
+
every: mapped.every ?? old.every ?? null, next_run_at: mapped.every ? now() : old.next_run_at,
|
|
151
|
+
paused: mapped.paused ? JSON.stringify({ by: actorOf() ?? 'migration', reason: `migrated ${status}: ${json(last?.payload, {})?.reason ?? 'held by previous workflow'}` }) : null });
|
|
150
152
|
this.mem.prepare('UPDATE tasks SET status = ? WHERE id = ?').run(stage, task.id);
|
|
151
153
|
if (task.current_run_id && ['done','cancelled'].includes(stage)) {
|
|
152
154
|
this.mem.prepare("UPDATE task_runs SET ended_at = COALESCE(ended_at, ?), status = 'reclaimed', outcome = COALESCE(outcome, 'reclaimed') WHERE id = ?").run(now(), task.current_run_id);
|
|
@@ -186,7 +188,7 @@ class ZtrackBoard {
|
|
|
186
188
|
this.taskKeys.set(tid, `${id}:${task.id}`);
|
|
187
189
|
const body = task.metadata?.body ?? '';
|
|
188
190
|
const taskCard = { ...task.metadata?.card, id: tid, title: `${task.id} ${task.text}`, body,
|
|
189
|
-
status: task.status === 'passed' ? 'done' : (task.metadata?.status
|
|
191
|
+
status: task.status === 'passed' ? (task.metadata?.status === 'cancelled' ? 'cancelled' : 'done') : (['done','cancelled'].includes(task.metadata?.status) ? 'todo' : task.metadata?.status ?? 'todo'),
|
|
190
192
|
metadata: task.metadata?.properties ?? {}, assignee: task.metadata?.assignee ?? card.assignee,
|
|
191
193
|
machine: task.metadata?.machine ?? card.machine, acceptanceCriteria: [],
|
|
192
194
|
acceptance: task.lines ?? [], relations: (task.blockedBy ?? []).map((b) => ({ type: 'blocked-by', issueId: b.ac ? `${nativeId(b.issue)}:${b.ac}` : nativeId(b.issue) })) };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.80",
|
|
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": {
|