@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.
@@ -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 r = spawnSync('git', ['-C', path, 'log', '--all', '-1', '--format=%ct', '--fixed-strings', `--grep=${id}`], { encoding: 'utf8', timeout: 10_000 });
84
- const t = Number(r.stdout?.trim());
85
- return r.status === 0 && Number.isFinite(t) && t > 0 ? t : null;
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
- const stage = typeof mapped === 'string' ? mapped : mapped.status;
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
- paused: mapped.paused ? JSON.stringify({ by: 'migration', reason: `migrated ${status}: ${json(last?.payload, {})?.reason ?? 'held by previous workflow'}` }) : null });
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 === 'done' ? 'todo' : task.metadata?.status ?? 'todo'),
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.78",
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": {