@volter/supercode-orchestrator 0.5.195 → 0.5.197

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.
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ // Check before handing off or importing board/runtime dependencies.
3
+ let lockedNative;
4
+ try { ({ lockedNative } = await import('../source-lock.mjs')); }
5
+ catch (error) { process.stderr.write(`${error.message}\n`); process.exit(1); }
2
6
  // Any command on a home whose record names another orchestrator is that orchestrator's (hand-off.mjs).
3
7
  {
4
8
  const { handOff, homeOfArgs } = await import('../hand-off.mjs');
@@ -7,6 +11,11 @@
7
11
  catch (error) { process.stderr.write(`supercode ${process.argv[2] ?? ''}: ${error.message}\n`); process.exit(1); }
8
12
  if (handed !== null) process.exit(await handed);
9
13
  }
14
+ // Hand-off may have selected the home's SUPERCODE_BIN. Verify it too, then use the proved native for every child.
15
+ try {
16
+ const pinnedNative = lockedNative();
17
+ if (pinnedNative) process.env.SUPERCODE_BIN = pinnedNative;
18
+ } catch (error) { process.stderr.write(`${error.message}\n`); process.exit(1); }
10
19
  // Board commands do not load daemon transports, platform adapters or the MCP server.
11
20
  if (process.argv[2] === 'workflow') {
12
21
  const [{runWorkflow},{timeCommand}]=await Promise.all([import('../board/client.mjs'),import('@volter/supercode-harness-sdk/slow-log')]);
package/hand-off.mjs CHANGED
@@ -12,6 +12,7 @@ import { spawn } from 'node:child_process';
12
12
  import { existsSync, readFileSync, realpathSync } from 'node:fs';
13
13
  import { join, resolve } from 'node:path';
14
14
  import { fileURLToPath } from 'node:url';
15
+ import { enforceSourceLock } from '@volter/supercode-teams/source-lock';
15
16
 
16
17
  /** The home a command (the whole of it, after the entry) names: --root, wherever it stands (the gateway's form,
17
18
  * `node bin/orchestrator.mjs --root <home>`, has no verb before it); for `import`, which writes the home it names
@@ -36,6 +37,9 @@ export function handOff(root, argv) {
36
37
  try { named = realpathSync(record.entry); } catch { throw new Error(`${root} is served by orchestrator ${record.version ?? 'unknown'} (${record.entry ?? 'its record names none'}), which is not on this machine; this one is ${version}. Nothing was run`); }
37
38
  const supercode = record.supercode?.entry;
38
39
  if (!supercode || !existsSync(supercode)) throw new Error(`${root} is served by supercode ${record.supercode?.version ?? 'unknown'} (${supercode ?? 'its record names none'}), which is not on this machine. Nothing was run`);
40
+ // A stale home's record must not hand a locked command to an older npm entry that cannot enforce the lock.
41
+ enforceSourceLock(named, 'the home record orchestrator');
42
+ enforceSourceLock(supercode, 'the home record supercode');
39
43
  if (named === own) { process.env.SUPERCODE_BIN = supercode; return null; }
40
44
  return new Promise((done) => {
41
45
  const child = spawn(process.execPath, [named, ...argv], { stdio: 'inherit', env: { ...process.env, SUPERCODE_BIN: supercode } });
package/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import './source-lock.mjs';
1
2
  export {
2
3
  LoadError, sessionReset, homeChannel, CHAT_TYPES, END_REASONS, FIRE_STATUSES, OBLIGATION_STATES,
3
4
  renderSurfaceKey, parseSurfaceKey, surfaceKeyString, parseTarget, renderTarget, resolveRoute, routeSpecificity,
package/orchestration.mjs CHANGED
@@ -27,6 +27,7 @@ import { dirname, join, resolve } from 'node:path';
27
27
  import { fileURLToPath } from 'node:url';
28
28
  import { SupercodeHarnessClient } from '@volter/supercode-harness-sdk';
29
29
  import { emptyRuntime, persistedView } from './ir.mjs';
30
+ import { lockedNative } from './source-lock.mjs';
30
31
 
31
32
  const here = dirname(fileURLToPath(import.meta.url));
32
33
 
@@ -36,6 +37,8 @@ const here = dirname(fileURLToPath(import.meta.url));
36
37
  * checkout's debug build, else `supercode` on PATH.
37
38
  */
38
39
  export function supercodeCommand() {
40
+ const pinned = lockedNative();
41
+ if (pinned) return pinned;
39
42
  if (process.env.SUPERCODE_BIN) return process.env.SUPERCODE_BIN;
40
43
  const built = resolve(here, '../../target/debug/supercode');
41
44
  return existsSync(built) ? built : 'supercode';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.5.195",
3
+ "version": "0.5.197",
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,9 +28,10 @@
28
28
  "check-types": "node scripts/generate-types.mjs --check"
29
29
  },
30
30
  "dependencies": {
31
+ "@volter/supercode-teams": "^0.3.329",
31
32
  "@volter/supercode-terminal": "^0.3.8",
32
33
  "@volter/supercode-harness-sdk": "^0.3.101",
33
- "@volter/teams": "0.2.90",
34
+ "@volter/teams": "0.2.91",
34
35
  "@volter/ztrack": "^2.4.23",
35
36
  "yaml": "^2.9.0"
36
37
  },
@@ -0,0 +1,34 @@
1
+ // The orchestrator and its native codec share the CLI/Teams source lock; no second declaration.
2
+ import { existsSync, realpathSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+ import { enforceSourceLock, sourceRoot, SourceLockError } from '@volter/supercode-teams/source-lock';
6
+
7
+ const lock = enforceSourceLock(import.meta.url, 'the orchestrator');
8
+ if (lock) {
9
+ enforceSourceLock(import.meta.resolve('@volter/supercode-harness-sdk'), 'the orchestrator harness SDK');
10
+ enforceSourceLock(import.meta.resolve('@volter/supercode-teams/source-lock'), 'the orchestrator Teams package');
11
+ }
12
+
13
+ /** The locked tree's release native, proved against the same lock before any codec door opens. */
14
+ export function lockedNative() {
15
+ const lock = enforceSourceLock(import.meta.url, 'the orchestrator');
16
+ if (!lock) return null;
17
+ const root = sourceRoot(import.meta.url);
18
+ const binary = resolve(root, 'target/release', process.platform === 'win32' ? 'supercode.exe' : 'supercode');
19
+ if (!existsSync(binary)) throw new SourceLockError(`supercode source lock: the orchestrator needs the pinned tree's release native (${binary}); build it there with cargo build --release -p supercode-cli`);
20
+ if (process.env.SUPERCODE_BIN && (!existsSync(process.env.SUPERCODE_BIN) || realpathSync(process.env.SUPERCODE_BIN) !== realpathSync(binary))) {
21
+ // A host normally passes its source-linked Node front door as SUPERCODE_BIN.
22
+ enforceSourceLock(process.env.SUPERCODE_BIN, 'the orchestrator SUPERCODE_BIN');
23
+ if (realpathSync(process.env.SUPERCODE_BIN) !== realpathSync(resolve(root, 'packaging/npm/bin/supercode.js'))) {
24
+ throw new SourceLockError(`supercode source lock: SUPERCODE_BIN must name the pinned release native or its front door (${binary})`);
25
+ }
26
+ }
27
+ const result = spawnSync(binary, ['source', 'show', '--json'], { encoding: 'utf8', timeout: 5000 });
28
+ if (result.error || result.status !== 0) throw new SourceLockError(`supercode source lock: the orchestrator native ${binary} cannot be verified: ${result.error?.message || result.stderr}`);
29
+ const receipt = JSON.parse(result.stdout);
30
+ if (receipt.verdict !== 'matches' || receipt.native.version !== lock.supercode || receipt.native.commit !== lock.commit || receipt.native.dirty) {
31
+ throw new SourceLockError(`supercode source lock: the orchestrator native ${binary} does not match ${lock.path}: ${receipt.verdict}`);
32
+ }
33
+ return binary;
34
+ }