@volter/supercode-orchestrator 0.5.128 → 0.5.130

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.
@@ -179,7 +179,11 @@ const addressOf = (s) => s?.address ?? (s?.session_id && s.machine ? `sc:${s.mac
179
179
  // A session in a live pane of its machine is the fleet's reading; any other run is read on its own machine: a headless
180
180
  // worker by its pid, a pane by that machine's pane list, a session in no pane (an adopted native one) by that machine's
181
181
  // harness discovery. Null only when the machine cannot answer.
182
- const sessionAlive = (fleet, session) => fleet.native?.has(addressOf(session)) ? fleet.native.get(addressOf(session)).alive : unpublishedAlive(session);
182
+ // A pane is read from the machine's record when the fleet reading holds its panes (current, or the machine is not in
183
+ // it): the pane list asked through its door serves READING_MS, so a pane that ended since that reading was read live
184
+ // for up to those 15 s more, and a session's loss was read that much late.
185
+ const paneInRecord = (fleet, session) => session?.surface !== 'headless' && session?.pane && session.machine && fleet?.panes?.has(normalMachine(session.machine)) ? fleet.panes.get(normalMachine(session.machine)).has(session.pane) : null;
186
+ const sessionAlive = (fleet, session) => fleet.native?.has(addressOf(session)) ? fleet.native.get(addressOf(session)).alive : paneInRecord(fleet, session) ?? unpublishedAlive(session);
183
187
  /** A subscriber's address as the session it names, for sessionAlive (its machine, harness and native id). */
184
188
  const sessionAt = (address) => { const m = /^sc:([^:]+):([^:]+):(.+)$/.exec(String(address)); return m && HARNESSES[m[2]] ? { address, machine: normalMachine(m[1]), harness: m[2], session_id: m[3] } : null; };
185
189
  /** A subscriber's liveness, read first (readBefore): true, false, or null when it could not be read (unknown, never dead). */
@@ -563,7 +567,11 @@ async function supervise(board, fleet, settings, report, entry, effects) {
563
567
  const alive = sessionAlive(fleet,session);
564
568
  if (alive == null) return;
565
569
  const machineUp = fleet.online.has(session.machine);
566
- const young = t - Number(session.launched_at ?? 0) < Number(limits.grace ?? settings.grace);
570
+ // the grace after a launch is for a session that has not come up yet: one already seen live (bound at its
571
+ // launch, verified at its adoption) has, and is missed from the first reading it is gone from, so its loss is
572
+ // read one grace after it went, not two (an adopted session that ended inside the grace of its adoption waited
573
+ // out both)
574
+ const young = !session.seen_at && t - Number(session.launched_at ?? 0) < Number(limits.grace ?? settings.grace);
567
575
  const missing = !alive && machineUp && !young;
568
576
  const next = { ...session };
569
577
  if (alive) { next.seen_at ??= t; next.missing_since = null; }
package/hermes-home.mjs CHANGED
@@ -10,7 +10,7 @@
10
10
  // skillSources(dir) every skill a profile has, by name, and where it lives
11
11
  // adoptMcp(dir) `.mcp.json` the source, `config.yaml`'s `mcp_servers:` its shadow, an edit on
12
12
  // either side carried to the other against the last state written (row 4)
13
- import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, renameSync, rmdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
13
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, renameSync, rmdirSync, rmSync, statSync, symlinkSync, writeFileSync } from 'node:fs';
14
14
  import { dirname, join, relative, resolve } from 'node:path';
15
15
  import { homedir } from 'node:os';
16
16
  import { createHash } from 'node:crypto';
@@ -39,7 +39,16 @@ const kind = (path) => { try { const s = lstatSync(path); return s.isSymbolicLin
39
39
  export function linkTo(path, target) {
40
40
  if (kind(path) === 'link' && readlinkSync(path) === target) return false;
41
41
  rmSync(path, { force: true });
42
- symlinkSync(target, path);
42
+ try { symlinkSync(target, path); }
43
+ catch (error) {
44
+ // Windows lets only an elevated or developer-mode user make a symlink (EPERM otherwise, and every board launch
45
+ // there failed on its agent home's SOUL.md): a folder is linked as a junction, which needs no grant, and a file is
46
+ // copied, which each refresh of the home copies again
47
+ if (process.platform !== 'win32' || error.code !== 'EPERM') throw error;
48
+ const source = resolve(dirname(path), target);
49
+ if (statSync(source).isDirectory()) symlinkSync(source, path, 'junction');
50
+ else copyFileSync(source, path);
51
+ }
43
52
  return true;
44
53
  }
45
54
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.5.128",
3
+ "version": "0.5.130",
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": {
@@ -24,8 +24,8 @@
24
24
  "check-types": "node scripts/generate-types.mjs --check"
25
25
  },
26
26
  "dependencies": {
27
- "@volter/supercode-harness-sdk": "^0.3.60",
28
- "@volter/teams": "0.2.51",
27
+ "@volter/supercode-harness-sdk": "^0.3.89",
28
+ "@volter/teams": "0.2.52",
29
29
  "@volter/ztrack": "^2.4.23",
30
30
  "yaml": "^2.9.0"
31
31
  },