@pleri/olam-cli 0.1.56 → 0.1.58

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.
Files changed (46) hide show
  1. package/dist/__tests__/services.test.d.ts +8 -0
  2. package/dist/__tests__/services.test.d.ts.map +1 -0
  3. package/dist/__tests__/services.test.js +185 -0
  4. package/dist/__tests__/services.test.js.map +1 -0
  5. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts +6 -0
  6. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts.map +1 -0
  7. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js +26 -0
  8. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js.map +1 -0
  9. package/dist/commands/__tests__/upgrade.all-three.test.js +1 -13
  10. package/dist/commands/__tests__/upgrade.all-three.test.js.map +1 -1
  11. package/dist/commands/__tests__/upgrade.compose-path.test.js +1 -13
  12. package/dist/commands/__tests__/upgrade.compose-path.test.js.map +1 -1
  13. package/dist/commands/__tests__/upgrade.olam-tag.test.js +1 -14
  14. package/dist/commands/__tests__/upgrade.olam-tag.test.js.map +1 -1
  15. package/dist/commands/__tests__/upgrade.recreate.test.js +1 -13
  16. package/dist/commands/__tests__/upgrade.recreate.test.js.map +1 -1
  17. package/dist/commands/__tests__/upgrade.rollback.test.js +1 -21
  18. package/dist/commands/__tests__/upgrade.rollback.test.js.map +1 -1
  19. package/dist/commands/__tests__/upgrade.smoke.test.js +1 -21
  20. package/dist/commands/__tests__/upgrade.smoke.test.js.map +1 -1
  21. package/dist/commands/__tests__/upgrade.swap.test.js +1 -22
  22. package/dist/commands/__tests__/upgrade.swap.test.js.map +1 -1
  23. package/dist/commands/auth.d.ts.map +1 -1
  24. package/dist/commands/auth.js +15 -38
  25. package/dist/commands/auth.js.map +1 -1
  26. package/dist/commands/bootstrap.d.ts +2 -0
  27. package/dist/commands/bootstrap.d.ts.map +1 -1
  28. package/dist/commands/bootstrap.js +3 -3
  29. package/dist/commands/bootstrap.js.map +1 -1
  30. package/dist/commands/create.d.ts.map +1 -1
  31. package/dist/commands/create.js +1 -9
  32. package/dist/commands/create.js.map +1 -1
  33. package/dist/commands/services.d.ts +39 -0
  34. package/dist/commands/services.d.ts.map +1 -0
  35. package/dist/commands/services.js +220 -0
  36. package/dist/commands/services.js.map +1 -0
  37. package/dist/commands/upgrade.d.ts +11 -0
  38. package/dist/commands/upgrade.d.ts.map +1 -1
  39. package/dist/commands/upgrade.js +70 -6
  40. package/dist/commands/upgrade.js.map +1 -1
  41. package/dist/image-digests.json +4 -3
  42. package/dist/index.js +953 -1023
  43. package/dist/index.js.map +1 -1
  44. package/dist/mcp-server.js +258 -370
  45. package/host-cp/src/server.mjs +9 -1
  46. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -460,8 +460,8 @@ var init_parseUtil = __esm({
460
460
  init_errors();
461
461
  init_en();
462
462
  makeIssue = (params) => {
463
- const { data, path: path45, errorMaps, issueData } = params;
464
- const fullPath = [...path45, ...issueData.path || []];
463
+ const { data, path: path44, errorMaps, issueData } = params;
464
+ const fullPath = [...path44, ...issueData.path || []];
465
465
  const fullIssue = {
466
466
  ...issueData,
467
467
  path: fullPath
@@ -769,11 +769,11 @@ var init_types = __esm({
769
769
  init_parseUtil();
770
770
  init_util();
771
771
  ParseInputLazyPath = class {
772
- constructor(parent, value, path45, key) {
772
+ constructor(parent, value, path44, key) {
773
773
  this._cachedPath = [];
774
774
  this.parent = parent;
775
775
  this.data = value;
776
- this._path = path45;
776
+ this._path = path44;
777
777
  this._key = key;
778
778
  }
779
779
  get path() {
@@ -4254,7 +4254,7 @@ import YAML from "yaml";
4254
4254
  function bootstrapStepCmd(entry) {
4255
4255
  return typeof entry === "string" ? entry : entry.cmd;
4256
4256
  }
4257
- function refineForbiddenKeys(value, path45, ctx, rejectSource) {
4257
+ function refineForbiddenKeys(value, path44, ctx, rejectSource) {
4258
4258
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
4259
4259
  return;
4260
4260
  }
@@ -4262,12 +4262,12 @@ function refineForbiddenKeys(value, path45, ctx, rejectSource) {
4262
4262
  if (FORBIDDEN_KEYS.has(key)) {
4263
4263
  ctx.addIssue({
4264
4264
  code: external_exports.ZodIssueCode.custom,
4265
- path: [...path45, key],
4265
+ path: [...path44, key],
4266
4266
  message: `forbidden key "${key}" (prototype-pollution surface)`
4267
4267
  });
4268
4268
  continue;
4269
4269
  }
4270
- if (rejectSource && path45.length === 0 && key === "source") {
4270
+ if (rejectSource && path44.length === 0 && key === "source") {
4271
4271
  ctx.addIssue({
4272
4272
  code: external_exports.ZodIssueCode.custom,
4273
4273
  path: ["source"],
@@ -4275,21 +4275,21 @@ function refineForbiddenKeys(value, path45, ctx, rejectSource) {
4275
4275
  });
4276
4276
  continue;
4277
4277
  }
4278
- refineForbiddenKeys(value[key], [...path45, key], ctx, false);
4278
+ refineForbiddenKeys(value[key], [...path44, key], ctx, false);
4279
4279
  }
4280
4280
  }
4281
- function rejectForbiddenKeys(value, path45, rejectSource) {
4281
+ function rejectForbiddenKeys(value, path44, rejectSource) {
4282
4282
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
4283
4283
  return;
4284
4284
  }
4285
4285
  for (const key of Object.keys(value)) {
4286
4286
  if (FORBIDDEN_KEYS.has(key)) {
4287
- throw new Error(`[manifest] ${path45}: forbidden key "${key}" (prototype-pollution surface)`);
4287
+ throw new Error(`[manifest] ${path44}: forbidden key "${key}" (prototype-pollution surface)`);
4288
4288
  }
4289
4289
  if (rejectSource && key === "source") {
4290
- throw new Error(`[manifest] ${path45}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
4290
+ throw new Error(`[manifest] ${path44}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
4291
4291
  }
4292
- rejectForbiddenKeys(value[key], `${path45}.${key}`, false);
4292
+ rejectForbiddenKeys(value[key], `${path44}.${key}`, false);
4293
4293
  }
4294
4294
  }
4295
4295
  function unknownTopLevelKeys(parsed) {
@@ -5280,8 +5280,8 @@ var init_client = __esm({
5280
5280
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
5281
5281
  }
5282
5282
  }
5283
- async request(method, path45, body, attempt = 0) {
5284
- const url = `${this.baseUrl}${path45}`;
5283
+ async request(method, path44, body, attempt = 0) {
5284
+ const url = `${this.baseUrl}${path44}`;
5285
5285
  const controller = new AbortController();
5286
5286
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
5287
5287
  const headers = {};
@@ -5299,7 +5299,7 @@ var init_client = __esm({
5299
5299
  } catch (err) {
5300
5300
  if (attempt < RETRY_COUNT && isTransient(err)) {
5301
5301
  await sleep(RETRY_BACKOFF_MS * (attempt + 1));
5302
- return this.request(method, path45, body, attempt + 1);
5302
+ return this.request(method, path44, body, attempt + 1);
5303
5303
  }
5304
5304
  throw err;
5305
5305
  } finally {
@@ -6778,8 +6778,8 @@ var init_provider3 = __esm({
6778
6778
  // -----------------------------------------------------------------------
6779
6779
  // Internal fetch helper
6780
6780
  // -----------------------------------------------------------------------
6781
- async request(path45, method, body) {
6782
- const url = `${this.config.workerUrl}${path45}`;
6781
+ async request(path44, method, body) {
6782
+ const url = `${this.config.workerUrl}${path44}`;
6783
6783
  const bearer = await this.config.mintToken();
6784
6784
  const headers = {
6785
6785
  Authorization: `Bearer ${bearer}`
@@ -7569,192 +7569,87 @@ var init_hooks_config = __esm({
7569
7569
  }
7570
7570
  });
7571
7571
 
7572
- // ../core/dist/world/merge-settings.js
7573
- import * as fs12 from "node:fs";
7574
- import * as path13 from "node:path";
7575
- import * as crypto2 from "node:crypto";
7576
- function mergeHomeSettingsJson(filePath, options) {
7577
- let settings;
7578
- try {
7579
- settings = readSettings(filePath);
7580
- } catch (err) {
7581
- throw new Error(`merge-settings: failed to parse existing settings.json: ${err?.message ?? err}`);
7582
- }
7583
- let changed = false;
7584
- if (options.ensureHook) {
7585
- const { stage, sentinel, entry } = options.ensureHook;
7586
- if (!settings.hooks || typeof settings.hooks !== "object") {
7587
- settings = { ...settings, hooks: {} };
7588
- changed = true;
7589
- }
7590
- const hooks = settings.hooks;
7591
- if (!Array.isArray(hooks[stage])) {
7592
- settings = {
7593
- ...settings,
7594
- hooks: { ...hooks, [stage]: [] }
7595
- };
7596
- changed = true;
7597
- }
7598
- const stageArr = settings.hooks[stage];
7599
- if (isHookSentinelPresent(stageArr, sentinel)) {
7600
- if (!changed) {
7601
- return { status: "already-present", message: `hook already present at ${filePath}` };
7602
- }
7603
- } else {
7604
- settings = {
7605
- ...settings,
7606
- hooks: {
7607
- ...settings.hooks,
7608
- [stage]: [...stageArr, entry]
7609
- }
7610
- };
7611
- changed = true;
7612
- }
7613
- }
7614
- if (options.env) {
7615
- const existingEnv = settings.env && typeof settings.env === "object" ? settings.env : {};
7616
- const mergedEnv = { ...existingEnv, ...options.env };
7617
- const sameKeys = Object.keys(mergedEnv).length === Object.keys(existingEnv).length && Object.keys(mergedEnv).every((k) => existingEnv[k] === mergedEnv[k]);
7618
- if (!sameKeys) {
7619
- settings = { ...settings, env: mergedEnv };
7620
- changed = true;
7621
- }
7622
- }
7623
- if (!changed) {
7624
- return { status: "no-op", message: `no change needed at ${filePath}` };
7625
- }
7626
- try {
7627
- atomicWriteJson(filePath, settings);
7628
- } catch (err) {
7629
- throw new Error(`merge-settings: failed to write settings.json: ${err?.message ?? err}`);
7630
- }
7631
- return { status: "installed", message: `settings.json updated at ${filePath}` };
7632
- }
7633
- function readSettings(filePath) {
7634
- if (!fs12.existsSync(filePath)) {
7635
- return {};
7636
- }
7637
- const raw = fs12.readFileSync(filePath, "utf-8");
7638
- if (!raw.trim())
7639
- return {};
7640
- return JSON.parse(raw);
7641
- }
7642
- function isHookSentinelPresent(matchers, sentinel) {
7643
- for (const matcher of matchers) {
7644
- if (typeof matcher?.command === "string" && matcher.command.includes(sentinel)) {
7645
- return true;
7646
- }
7647
- if (Array.isArray(matcher?.hooks)) {
7648
- for (const h of matcher.hooks) {
7649
- if (typeof h?.command === "string" && h.command.includes(sentinel)) {
7650
- return true;
7651
- }
7652
- }
7653
- }
7654
- }
7655
- return false;
7656
- }
7657
- function atomicWriteJson(filePath, data) {
7658
- const dir = path13.dirname(filePath);
7659
- fs12.mkdirSync(dir, { recursive: true });
7660
- const rand = crypto2.randomBytes(6).toString("hex");
7661
- const tmp = `${filePath}.tmp.${process.pid}.${rand}`;
7662
- const json = JSON.stringify(data, null, 2) + "\n";
7663
- fs12.writeFileSync(tmp, json, { mode: 420 });
7664
- fs12.renameSync(tmp, filePath);
7665
- }
7666
- var init_merge_settings = __esm({
7667
- "../core/dist/world/merge-settings.js"() {
7668
- "use strict";
7669
- }
7670
- });
7671
-
7672
7572
  // ../core/dist/world/env-setup.js
7673
- import * as crypto3 from "node:crypto";
7674
- import * as fs13 from "node:fs";
7573
+ import * as crypto2 from "node:crypto";
7574
+ import * as fs12 from "node:fs";
7675
7575
  import * as os8 from "node:os";
7676
- import * as path14 from "node:path";
7576
+ import * as path13 from "node:path";
7677
7577
  import { globSync } from "node:fs";
7678
7578
  function copyClaudeConfig(workspacePath, homeDir, configCtx) {
7679
- const sourceClaudeDir = path14.join(homeDir ?? os8.homedir(), ".claude");
7680
- const destClaudeDir = path14.join(workspacePath, ".claude-host-config");
7579
+ const sourceClaudeDir = path13.join(homeDir ?? os8.homedir(), ".claude");
7580
+ const destClaudeDir = path13.join(workspacePath, ".claude-host-config");
7681
7581
  void configCtx;
7682
- if (!fs13.existsSync(sourceClaudeDir))
7582
+ if (!fs12.existsSync(sourceClaudeDir))
7683
7583
  return;
7684
- fs13.mkdirSync(destClaudeDir, { recursive: true });
7685
- const settingsPath = path14.join(sourceClaudeDir, "settings.json");
7584
+ fs12.mkdirSync(destClaudeDir, { recursive: true });
7585
+ const settingsPath = path13.join(sourceClaudeDir, "settings.json");
7686
7586
  let settings = {};
7687
- if (fs13.existsSync(settingsPath)) {
7587
+ if (fs12.existsSync(settingsPath)) {
7688
7588
  try {
7689
- settings = JSON.parse(fs13.readFileSync(settingsPath, "utf-8"));
7589
+ settings = JSON.parse(fs12.readFileSync(settingsPath, "utf-8"));
7690
7590
  delete settings["hooks"];
7691
7591
  } catch {
7692
7592
  }
7693
7593
  }
7694
7594
  const hooksConfig = generateHooksConfig(DEFAULT_HOOK_SERVER_URL);
7695
7595
  settings["hooks"] = hooksConfig["hooks"];
7696
- fs13.writeFileSync(path14.join(destClaudeDir, "settings.json"), JSON.stringify(settings, null, 2));
7697
- const claudeMdPath = path14.join(sourceClaudeDir, "CLAUDE.md");
7698
- if (fs13.existsSync(claudeMdPath)) {
7699
- fs13.copyFileSync(claudeMdPath, path14.join(destClaudeDir, "CLAUDE.md"));
7596
+ fs12.writeFileSync(path13.join(destClaudeDir, "settings.json"), JSON.stringify(settings, null, 2));
7597
+ const claudeMdPath = path13.join(sourceClaudeDir, "CLAUDE.md");
7598
+ if (fs12.existsSync(claudeMdPath)) {
7599
+ fs12.copyFileSync(claudeMdPath, path13.join(destClaudeDir, "CLAUDE.md"));
7700
7600
  }
7701
- const rulesDir = path14.join(sourceClaudeDir, "rules");
7702
- if (fs13.existsSync(rulesDir)) {
7703
- copyDirRecursive(rulesDir, path14.join(destClaudeDir, "rules"));
7601
+ const rulesDir = path13.join(sourceClaudeDir, "rules");
7602
+ if (fs12.existsSync(rulesDir)) {
7603
+ copyDirRecursive(rulesDir, path13.join(destClaudeDir, "rules"));
7704
7604
  }
7705
- const agentsDir = path14.join(sourceClaudeDir, "agents");
7706
- if (fs13.existsSync(agentsDir)) {
7707
- copyDirRecursive(agentsDir, path14.join(destClaudeDir, "agents"));
7605
+ const agentsDir = path13.join(sourceClaudeDir, "agents");
7606
+ if (fs12.existsSync(agentsDir)) {
7607
+ copyDirRecursive(agentsDir, path13.join(destClaudeDir, "agents"));
7708
7608
  }
7709
- const pluginsDir = path14.join(sourceClaudeDir, "plugins");
7710
- if (fs13.existsSync(pluginsDir)) {
7711
- copyDirRecursive(pluginsDir, path14.join(destClaudeDir, "plugins"), 0, SKIP_FILES);
7609
+ const pluginsDir = path13.join(sourceClaudeDir, "plugins");
7610
+ if (fs12.existsSync(pluginsDir)) {
7611
+ copyDirRecursive(pluginsDir, path13.join(destClaudeDir, "plugins"), 0, SKIP_FILES);
7712
7612
  }
7713
- const skillsDir = path14.join(sourceClaudeDir, "skills");
7714
- if (fs13.existsSync(skillsDir)) {
7715
- copyDirRecursive(skillsDir, path14.join(destClaudeDir, "skills"));
7613
+ const skillsDir = path13.join(sourceClaudeDir, "skills");
7614
+ if (fs12.existsSync(skillsDir)) {
7615
+ copyDirRecursive(skillsDir, path13.join(destClaudeDir, "skills"));
7716
7616
  }
7717
- const scriptsDir = path14.join(sourceClaudeDir, "scripts");
7718
- if (fs13.existsSync(scriptsDir)) {
7719
- copyDirRecursive(scriptsDir, path14.join(destClaudeDir, "scripts"));
7617
+ const scriptsDir = path13.join(sourceClaudeDir, "scripts");
7618
+ if (fs12.existsSync(scriptsDir)) {
7619
+ copyDirRecursive(scriptsDir, path13.join(destClaudeDir, "scripts"));
7720
7620
  }
7721
7621
  applyProjectClaudeOverlay(workspacePath, destClaudeDir);
7722
7622
  writeStrippedMcpServersSnapshot(homeDir ?? os8.homedir(), workspacePath, destClaudeDir);
7723
- if (configCtx != null && configCtx.worlds_default?.agent_teams_enabled !== false) {
7724
- mergeHomeSettingsJson(path14.join(destClaudeDir, "settings.json"), {
7725
- env: { CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1" }
7726
- });
7727
- }
7728
7623
  }
7729
7624
  function applyProjectClaudeOverlay(workspacePath, destClaudeDir) {
7730
- const projectClaudeDir = path14.join(workspacePath, ".claude");
7731
- if (!fs13.existsSync(projectClaudeDir))
7625
+ const projectClaudeDir = path13.join(workspacePath, ".claude");
7626
+ if (!fs12.existsSync(projectClaudeDir))
7732
7627
  return;
7733
- const projectSettingsPath = path14.join(projectClaudeDir, "settings.json");
7734
- const destSettingsPath = path14.join(destClaudeDir, "settings.json");
7735
- if (fs13.existsSync(projectSettingsPath)) {
7628
+ const projectSettingsPath = path13.join(projectClaudeDir, "settings.json");
7629
+ const destSettingsPath = path13.join(destClaudeDir, "settings.json");
7630
+ if (fs12.existsSync(projectSettingsPath)) {
7736
7631
  try {
7737
- const projectSettings = JSON.parse(fs13.readFileSync(projectSettingsPath, "utf-8"));
7632
+ const projectSettings = JSON.parse(fs12.readFileSync(projectSettingsPath, "utf-8"));
7738
7633
  delete projectSettings["hooks"];
7739
- const existing = fs13.existsSync(destSettingsPath) ? JSON.parse(fs13.readFileSync(destSettingsPath, "utf-8")) : {};
7634
+ const existing = fs12.existsSync(destSettingsPath) ? JSON.parse(fs12.readFileSync(destSettingsPath, "utf-8")) : {};
7740
7635
  const merged = { ...existing, ...projectSettings, hooks: existing["hooks"] };
7741
- fs13.writeFileSync(destSettingsPath, JSON.stringify(merged, null, 2));
7636
+ fs12.writeFileSync(destSettingsPath, JSON.stringify(merged, null, 2));
7742
7637
  } catch {
7743
7638
  }
7744
7639
  }
7745
- const projectClaudeMd = path14.join(projectClaudeDir, "CLAUDE.md");
7746
- if (fs13.existsSync(projectClaudeMd)) {
7747
- fs13.copyFileSync(projectClaudeMd, path14.join(destClaudeDir, "CLAUDE.md"));
7640
+ const projectClaudeMd = path13.join(projectClaudeDir, "CLAUDE.md");
7641
+ if (fs12.existsSync(projectClaudeMd)) {
7642
+ fs12.copyFileSync(projectClaudeMd, path13.join(destClaudeDir, "CLAUDE.md"));
7748
7643
  }
7749
- const projectAgentsMd = path14.join(projectClaudeDir, "AGENTS.md");
7750
- if (fs13.existsSync(projectAgentsMd)) {
7751
- fs13.copyFileSync(projectAgentsMd, path14.join(destClaudeDir, "AGENTS.md"));
7644
+ const projectAgentsMd = path13.join(projectClaudeDir, "AGENTS.md");
7645
+ if (fs12.existsSync(projectAgentsMd)) {
7646
+ fs12.copyFileSync(projectAgentsMd, path13.join(destClaudeDir, "AGENTS.md"));
7752
7647
  }
7753
7648
  for (const subdir of ["rules", "agents", "plugins", "skills", "scripts"]) {
7754
- const projectSubdir = path14.join(projectClaudeDir, subdir);
7755
- if (fs13.existsSync(projectSubdir)) {
7649
+ const projectSubdir = path13.join(projectClaudeDir, subdir);
7650
+ if (fs12.existsSync(projectSubdir)) {
7756
7651
  const skip = subdir === "plugins" ? SKIP_FILES : /* @__PURE__ */ new Set();
7757
- copyDirRecursive(projectSubdir, path14.join(destClaudeDir, subdir), 0, skip);
7652
+ copyDirRecursive(projectSubdir, path13.join(destClaudeDir, subdir), 0, skip);
7758
7653
  }
7759
7654
  }
7760
7655
  }
@@ -7784,8 +7679,8 @@ function stripMcpServers(mcpServers) {
7784
7679
  return out;
7785
7680
  }
7786
7681
  function writeStrippedMcpServersSnapshot(homeDir, workspacePath, destClaudeDir) {
7787
- const hostMcpServers = readMcpServersFromFile(path14.join(homeDir, ".claude.json"));
7788
- const projectMcpServers = readMcpServersFromFile(path14.join(workspacePath, ".mcp.json"));
7682
+ const hostMcpServers = readMcpServersFromFile(path13.join(homeDir, ".claude.json"));
7683
+ const projectMcpServers = readMcpServersFromFile(path13.join(workspacePath, ".mcp.json"));
7789
7684
  if (Object.keys(hostMcpServers).length === 0 && Object.keys(projectMcpServers).length === 0) {
7790
7685
  return;
7791
7686
  }
@@ -7794,11 +7689,11 @@ function writeStrippedMcpServersSnapshot(homeDir, workspacePath, destClaudeDir)
7794
7689
  ...stripMcpServers(projectMcpServers)
7795
7690
  };
7796
7691
  const output = { mcpServers: stripped };
7797
- fs13.writeFileSync(path14.join(destClaudeDir, ".claude.json"), JSON.stringify(output, null, 2), { mode: 384 });
7692
+ fs12.writeFileSync(path13.join(destClaudeDir, ".claude.json"), JSON.stringify(output, null, 2), { mode: 384 });
7798
7693
  }
7799
7694
  function writeWorldEntitlementsJson(workspacePath, configCtx) {
7800
- const olamDir = path14.join(workspacePath, ".olam");
7801
- fs13.mkdirSync(olamDir, { recursive: true });
7695
+ const olamDir = path13.join(workspacePath, ".olam");
7696
+ fs12.mkdirSync(olamDir, { recursive: true });
7802
7697
  const resolvedRepos = configCtx.repos.map((repo) => {
7803
7698
  const repoEntitlement = repo;
7804
7699
  return {
@@ -7812,14 +7707,14 @@ function writeWorldEntitlementsJson(workspacePath, configCtx) {
7812
7707
  worlds_default: configCtx.worlds_default,
7813
7708
  repos: resolvedRepos
7814
7709
  };
7815
- const filePath = path14.join(olamDir, "world-entitlements.json");
7816
- fs13.writeFileSync(filePath, JSON.stringify(resolved, null, 2), { mode: 420 });
7710
+ const filePath = path13.join(olamDir, "world-entitlements.json");
7711
+ fs12.writeFileSync(filePath, JSON.stringify(resolved, null, 2), { mode: 420 });
7817
7712
  }
7818
7713
  function readMcpServersFromFile(filePath) {
7819
- if (!fs13.existsSync(filePath))
7714
+ if (!fs12.existsSync(filePath))
7820
7715
  return {};
7821
7716
  try {
7822
- const raw = fs13.readFileSync(filePath, "utf-8");
7717
+ const raw = fs12.readFileSync(filePath, "utf-8");
7823
7718
  if (!raw.trim())
7824
7719
  return {};
7825
7720
  const parsed = JSON.parse(raw);
@@ -7834,8 +7729,8 @@ function readMcpServersFromFile(filePath) {
7834
7729
  function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new Set()) {
7835
7730
  if (depth > 10)
7836
7731
  return;
7837
- fs13.mkdirSync(dest, { recursive: true });
7838
- for (const entry of fs13.readdirSync(src, { withFileTypes: true })) {
7732
+ fs12.mkdirSync(dest, { recursive: true });
7733
+ for (const entry of fs12.readdirSync(src, { withFileTypes: true })) {
7839
7734
  const { name } = entry;
7840
7735
  if (skipFiles.has(name))
7841
7736
  continue;
@@ -7845,12 +7740,12 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
7845
7740
  continue;
7846
7741
  if (entry.isDirectory() && SKIP_DIRS.has(name))
7847
7742
  continue;
7848
- const srcPath = path14.join(src, name);
7849
- const destPath = path14.join(dest, name);
7743
+ const srcPath = path13.join(src, name);
7744
+ const destPath = path13.join(dest, name);
7850
7745
  if (entry.isSymbolicLink()) {
7851
7746
  let stat;
7852
7747
  try {
7853
- stat = fs13.statSync(srcPath);
7748
+ stat = fs12.statSync(srcPath);
7854
7749
  } catch {
7855
7750
  continue;
7856
7751
  }
@@ -7859,12 +7754,12 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
7859
7754
  continue;
7860
7755
  copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
7861
7756
  } else if (stat.isFile()) {
7862
- fs13.copyFileSync(srcPath, destPath);
7757
+ fs12.copyFileSync(srcPath, destPath);
7863
7758
  }
7864
7759
  } else if (entry.isDirectory()) {
7865
7760
  copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
7866
7761
  } else {
7867
- fs13.copyFileSync(srcPath, destPath);
7762
+ fs12.copyFileSync(srcPath, destPath);
7868
7763
  }
7869
7764
  }
7870
7765
  }
@@ -8002,9 +7897,9 @@ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, conf
8002
7897
  }
8003
7898
  }
8004
7899
  for (const repo of repos) {
8005
- const worktreePath = path14.join(workspacePath, repo.name);
7900
+ const worktreePath = path13.join(workspacePath, repo.name);
8006
7901
  const sourcePath = repo.path;
8007
- if (!sourcePath || !fs13.existsSync(worktreePath))
7902
+ if (!sourcePath || !fs12.existsSync(worktreePath))
8008
7903
  continue;
8009
7904
  const envSetup = repo.env_setup;
8010
7905
  if (!envSetup)
@@ -8023,23 +7918,23 @@ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, conf
8023
7918
  }
8024
7919
  }
8025
7920
  function copyMatchingFiles(sourcePath, destPath, pattern) {
8026
- const fullPattern = path14.join(sourcePath, pattern);
7921
+ const fullPattern = path13.join(sourcePath, pattern);
8027
7922
  if (!pattern.includes("*")) {
8028
- const sourceFile = path14.join(sourcePath, pattern);
8029
- const destFile = path14.join(destPath, pattern);
8030
- if (fs13.existsSync(sourceFile)) {
8031
- fs13.mkdirSync(path14.dirname(destFile), { recursive: true });
8032
- fs13.copyFileSync(sourceFile, destFile);
7923
+ const sourceFile = path13.join(sourcePath, pattern);
7924
+ const destFile = path13.join(destPath, pattern);
7925
+ if (fs12.existsSync(sourceFile)) {
7926
+ fs12.mkdirSync(path13.dirname(destFile), { recursive: true });
7927
+ fs12.copyFileSync(sourceFile, destFile);
8033
7928
  }
8034
7929
  return;
8035
7930
  }
8036
7931
  try {
8037
7932
  const matches2 = globSync(fullPattern);
8038
7933
  for (const match2 of matches2) {
8039
- const relative2 = path14.relative(sourcePath, match2);
8040
- const dest = path14.join(destPath, relative2);
8041
- fs13.mkdirSync(path14.dirname(dest), { recursive: true });
8042
- fs13.copyFileSync(match2, dest);
7934
+ const relative2 = path13.relative(sourcePath, match2);
7935
+ const dest = path13.join(destPath, relative2);
7936
+ fs12.mkdirSync(path13.dirname(dest), { recursive: true });
7937
+ fs12.copyFileSync(match2, dest);
8043
7938
  }
8044
7939
  } catch {
8045
7940
  }
@@ -8047,14 +7942,14 @@ function copyMatchingFiles(sourcePath, destPath, pattern) {
8047
7942
  function generateEnvFromExample(repoPath, overrides) {
8048
7943
  const exampleFiles = [".env.example", ".env.sample", ".env.local.example"];
8049
7944
  for (const exampleName of exampleFiles) {
8050
- const examplePath = path14.join(repoPath, exampleName);
8051
- if (!fs13.existsSync(examplePath))
7945
+ const examplePath = path13.join(repoPath, exampleName);
7946
+ if (!fs12.existsSync(examplePath))
8052
7947
  continue;
8053
7948
  const targetName = exampleName.replace(".example", "").replace(".sample", "");
8054
- const targetPath = path14.join(repoPath, targetName);
8055
- if (fs13.existsSync(targetPath))
7949
+ const targetPath = path13.join(repoPath, targetName);
7950
+ if (fs12.existsSync(targetPath))
8056
7951
  continue;
8057
- const template = fs13.readFileSync(examplePath, "utf-8");
7952
+ const template = fs12.readFileSync(examplePath, "utf-8");
8058
7953
  const generated = template.split("\n").map((line) => {
8059
7954
  const match2 = /^([A-Z_][A-Z0-9_]*)=(.*)$/.exec(line);
8060
7955
  if (match2) {
@@ -8065,13 +7960,13 @@ function generateEnvFromExample(repoPath, overrides) {
8065
7960
  }
8066
7961
  return line;
8067
7962
  }).join("\n");
8068
- fs13.writeFileSync(targetPath, generated);
7963
+ fs12.writeFileSync(targetPath, generated);
8069
7964
  }
8070
7965
  }
8071
7966
  function applyEnvOverrides(repoPath, overrides) {
8072
- const envPath = path14.join(repoPath, ".env");
8073
- if (fs13.existsSync(envPath)) {
8074
- const existing = fs13.readFileSync(envPath, "utf-8");
7967
+ const envPath = path13.join(repoPath, ".env");
7968
+ if (fs12.existsSync(envPath)) {
7969
+ const existing = fs12.readFileSync(envPath, "utf-8");
8075
7970
  const existingKeys = new Set(existing.split("\n").map((l) => l.split("=")[0]?.trim()).filter(Boolean));
8076
7971
  const additions = [];
8077
7972
  for (const [key, value] of Object.entries(overrides)) {
@@ -8080,7 +7975,7 @@ function applyEnvOverrides(repoPath, overrides) {
8080
7975
  }
8081
7976
  }
8082
7977
  if (additions.length > 0) {
8083
- fs13.appendFileSync(envPath, "\n# Olam injected\n" + additions.join("\n") + "\n");
7978
+ fs12.appendFileSync(envPath, "\n# Olam injected\n" + additions.join("\n") + "\n");
8084
7979
  }
8085
7980
  }
8086
7981
  }
@@ -8089,7 +7984,6 @@ var init_env_setup = __esm({
8089
7984
  "../core/dist/world/env-setup.js"() {
8090
7985
  "use strict";
8091
7986
  init_hooks_config();
8092
- init_merge_settings();
8093
7987
  MCP_SERVER_ALLOWLIST = /* @__PURE__ */ new Set([
8094
7988
  "command",
8095
7989
  "args",
@@ -8153,9 +8047,9 @@ var init_env_setup = __esm({
8153
8047
 
8154
8048
  // ../core/dist/world/baseline-diff.js
8155
8049
  import { execFileSync as execFileSync3 } from "node:child_process";
8156
- import * as fs14 from "node:fs";
8050
+ import * as fs13 from "node:fs";
8157
8051
  import * as os9 from "node:os";
8158
- import * as path15 from "node:path";
8052
+ import * as path14 from "node:path";
8159
8053
  function expandHome(p, homedir22) {
8160
8054
  return p.replace(/^~(?=$|\/|\\)/, homedir22());
8161
8055
  }
@@ -8181,9 +8075,9 @@ ${stderr}`;
8181
8075
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
8182
8076
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
8183
8077
  const homedir22 = deps.homedir ?? (() => os9.homedir());
8184
- const baselineDir = path15.join(workspacePath, ".olam", "baseline");
8078
+ const baselineDir = path14.join(workspacePath, ".olam", "baseline");
8185
8079
  try {
8186
- fs14.mkdirSync(baselineDir, { recursive: true });
8080
+ fs13.mkdirSync(baselineDir, { recursive: true });
8187
8081
  } catch (err) {
8188
8082
  const msg = err instanceof Error ? err.message : String(err);
8189
8083
  console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
@@ -8195,9 +8089,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
8195
8089
  if (!repo.path)
8196
8090
  continue;
8197
8091
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
8198
- const outPath = path15.join(baselineDir, filename);
8092
+ const outPath = path14.join(baselineDir, filename);
8199
8093
  const repoPath = expandHome(repo.path, homedir22);
8200
- if (!fs14.existsSync(repoPath)) {
8094
+ if (!fs13.existsSync(repoPath)) {
8201
8095
  writeBaselineFile(outPath, `# repo: ${repo.name}
8202
8096
  # (skipped: path ${repoPath} does not exist)
8203
8097
  `);
@@ -8264,7 +8158,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
8264
8158
  }
8265
8159
  function writeBaselineFile(outPath, content) {
8266
8160
  try {
8267
- fs14.writeFileSync(outPath, content);
8161
+ fs13.writeFileSync(outPath, content);
8268
8162
  } catch (err) {
8269
8163
  const msg = err instanceof Error ? err.message : String(err);
8270
8164
  console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
@@ -8272,8 +8166,8 @@ function writeBaselineFile(outPath, content) {
8272
8166
  }
8273
8167
  function stripWorktreeEdits(repos, workspacePath) {
8274
8168
  for (const repo of repos) {
8275
- const worktreePath = path15.join(workspacePath, repo.name);
8276
- if (!fs14.existsSync(worktreePath))
8169
+ const worktreePath = path14.join(workspacePath, repo.name);
8170
+ if (!fs13.existsSync(worktreePath))
8277
8171
  continue;
8278
8172
  try {
8279
8173
  execFileSync3("git", ["checkout", "--", "."], {
@@ -8310,12 +8204,12 @@ var init_baseline_diff = __esm({
8310
8204
  });
8311
8205
 
8312
8206
  // ../core/dist/world/context-injection.js
8313
- import * as fs15 from "node:fs";
8314
- import * as path16 from "node:path";
8207
+ import * as fs14 from "node:fs";
8208
+ import * as path15 from "node:path";
8315
8209
  function injectWorldContext(opts) {
8316
8210
  const { world, task, linearTicketId, claudeMdExtra, taskContext, services, pleriPlaneUrl } = opts;
8317
- const claudeDir = path16.join(world.workspacePath, ".claude");
8318
- fs15.mkdirSync(claudeDir, { recursive: true });
8211
+ const claudeDir = path15.join(world.workspacePath, ".claude");
8212
+ fs14.mkdirSync(claudeDir, { recursive: true });
8319
8213
  const sections = [];
8320
8214
  sections.push(`# Olam World: ${world.name}`);
8321
8215
  sections.push("");
@@ -8476,7 +8370,7 @@ function injectWorldContext(opts) {
8476
8370
  sections.push("");
8477
8371
  }
8478
8372
  const content = sections.join("\n");
8479
- fs15.writeFileSync(path16.join(claudeDir, "CLAUDE.md"), content);
8373
+ fs14.writeFileSync(path15.join(claudeDir, "CLAUDE.md"), content);
8480
8374
  }
8481
8375
  function formatTaskSource(ctx) {
8482
8376
  if (ctx.source === "linear" && ctx.ticketId) {
@@ -8490,9 +8384,9 @@ function formatTaskSource(ctx) {
8490
8384
  function hasPlanFile(world) {
8491
8385
  if (world.repos.length === 0)
8492
8386
  return false;
8493
- const plansDir = path16.join(world.workspacePath, world.repos[0], "docs", "plans");
8387
+ const plansDir = path15.join(world.workspacePath, world.repos[0], "docs", "plans");
8494
8388
  try {
8495
- return fs15.existsSync(plansDir) && fs15.readdirSync(plansDir).length > 0;
8389
+ return fs14.existsSync(plansDir) && fs14.readdirSync(plansDir).length > 0;
8496
8390
  } catch {
8497
8391
  return false;
8498
8392
  }
@@ -8737,7 +8631,7 @@ var init_stack_install = __esm({
8737
8631
 
8738
8632
  // ../core/dist/world/stack-image.js
8739
8633
  import { execSync as execSync2 } from "node:child_process";
8740
- import * as crypto4 from "node:crypto";
8634
+ import * as crypto3 from "node:crypto";
8741
8635
  function computeFingerprint(runtimes) {
8742
8636
  const parts = [];
8743
8637
  for (const [runtime, versions] of runtimes) {
@@ -8787,14 +8681,14 @@ function getBaseImageDigest() {
8787
8681
  cachedBaseDigest = digest.replace("sha256:", "").slice(0, 16);
8788
8682
  return cachedBaseDigest;
8789
8683
  } catch {
8790
- cachedBaseDigest = crypto4.createHash("sha256").update("unknown").digest("hex").slice(0, 16);
8684
+ cachedBaseDigest = crypto3.createHash("sha256").update("unknown").digest("hex").slice(0, 16);
8791
8685
  return cachedBaseDigest;
8792
8686
  }
8793
8687
  }
8794
8688
  function sanitizeTag(raw) {
8795
8689
  let tag = raw.toLowerCase().replace(/[^a-z0-9._-]/g, "-");
8796
8690
  if (tag.length > MAX_TAG_LENGTH) {
8797
- const hash = crypto4.createHash("sha256").update(raw).digest("hex").slice(0, 12);
8691
+ const hash = crypto3.createHash("sha256").update(raw).digest("hex").slice(0, 12);
8798
8692
  tag = tag.slice(0, MAX_TAG_LENGTH - 13) + "_" + hash;
8799
8693
  }
8800
8694
  return tag;
@@ -9196,14 +9090,14 @@ var init_secrets_fetcher = __esm({
9196
9090
  });
9197
9091
 
9198
9092
  // ../core/dist/world/olam-yaml.js
9199
- import * as path17 from "node:path";
9093
+ import * as path16 from "node:path";
9200
9094
  import YAML2 from "yaml";
9201
9095
  function enrichReposWithManifests(repos, workspacePath) {
9202
9096
  return repos.map((repo) => {
9203
9097
  if (repo.manifest !== void 0 && repo.manifest !== null) {
9204
9098
  return repo;
9205
9099
  }
9206
- const repoDir = path17.join(workspacePath, repo.name);
9100
+ const repoDir = path16.join(workspacePath, repo.name);
9207
9101
  let manifest = null;
9208
9102
  try {
9209
9103
  manifest = loadRepoManifest(repoDir);
@@ -9224,8 +9118,8 @@ var init_olam_yaml = __esm({
9224
9118
  });
9225
9119
 
9226
9120
  // ../core/dist/policies/loader.js
9227
- import * as fs16 from "node:fs";
9228
- import * as path18 from "node:path";
9121
+ import * as fs15 from "node:fs";
9122
+ import * as path17 from "node:path";
9229
9123
  import { parse as parseYaml3 } from "yaml";
9230
9124
  function parseFrontmatter(content) {
9231
9125
  const match2 = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
@@ -9245,20 +9139,20 @@ function toStringArray(v) {
9245
9139
  return v.filter((x) => typeof x === "string");
9246
9140
  }
9247
9141
  function loadPolicies(workspaceRoot) {
9248
- const policiesDir = path18.join(workspaceRoot, ".olam", "policies");
9249
- if (!fs16.existsSync(policiesDir))
9142
+ const policiesDir = path17.join(workspaceRoot, ".olam", "policies");
9143
+ if (!fs15.existsSync(policiesDir))
9250
9144
  return [];
9251
9145
  let files;
9252
9146
  try {
9253
- files = fs16.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
9147
+ files = fs15.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
9254
9148
  } catch {
9255
9149
  return [];
9256
9150
  }
9257
9151
  const policies = [];
9258
9152
  for (const file of files) {
9259
- const filePath = path18.join(policiesDir, file);
9153
+ const filePath = path17.join(policiesDir, file);
9260
9154
  try {
9261
- const content = fs16.readFileSync(filePath, "utf8");
9155
+ const content = fs15.readFileSync(filePath, "utf8");
9262
9156
  const parsed = parseFrontmatter(content);
9263
9157
  if (!parsed) {
9264
9158
  console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
@@ -9333,7 +9227,7 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
9333
9227
  const probeTimeoutMs = options.probeTimeoutMs ?? 3e4;
9334
9228
  const probeIntervalMs = options.probeIntervalMs ?? 1e3;
9335
9229
  const clock = options.clock ?? Date.now;
9336
- const sleep3 = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
9230
+ const sleep4 = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
9337
9231
  for (const repo of repos) {
9338
9232
  if (isPortBound(exec, containerName, repo.hostPort)) {
9339
9233
  throw new PortInUseError(repo.hostPort, repo.name, repo.manifestPath);
@@ -9358,7 +9252,7 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
9358
9252
  probeTimeoutMs,
9359
9253
  probeIntervalMs,
9360
9254
  clock,
9361
- sleep: sleep3
9255
+ sleep: sleep4
9362
9256
  })));
9363
9257
  return {
9364
9258
  sessionName,
@@ -9422,7 +9316,6 @@ var manager_exports = {};
9422
9316
  __export(manager_exports, {
9423
9317
  AuthPreflightError: () => AuthPreflightError,
9424
9318
  BotIdentityError: () => BotIdentityError,
9425
- RepoSelectionRequiredError: () => RepoSelectionRequiredError,
9426
9319
  WorkspaceNotFoundError: () => WorkspaceNotFoundError,
9427
9320
  WorldManager: () => WorldManager,
9428
9321
  buildManifestRuntimeForTest: () => buildManifestRuntime,
@@ -9431,11 +9324,11 @@ __export(manager_exports, {
9431
9324
  planManifestPipeline: () => planManifestPipeline,
9432
9325
  runManifestRuntime: () => runManifestRuntime
9433
9326
  });
9434
- import * as crypto5 from "node:crypto";
9327
+ import * as crypto4 from "node:crypto";
9435
9328
  import { execSync as execSync4 } from "node:child_process";
9436
- import * as fs17 from "node:fs";
9329
+ import * as fs16 from "node:fs";
9437
9330
  import * as os10 from "node:os";
9438
- import * as path19 from "node:path";
9331
+ import * as path18 from "node:path";
9439
9332
  import YAML3 from "yaml";
9440
9333
  function getTokenScopes(ghToken, _exec = execSync4) {
9441
9334
  try {
@@ -9774,7 +9667,7 @@ function buildManifestRuntime(worldId, repos) {
9774
9667
  }
9775
9668
  return { worldId, repos: runtimeRepos };
9776
9669
  }
9777
- var BotIdentityError, ADJECTIVES, NOUNS, AuthPreflightError, WorkspaceNotFoundError, RepoSelectionRequiredError, WorldManager;
9670
+ var BotIdentityError, ADJECTIVES, NOUNS, AuthPreflightError, WorkspaceNotFoundError, WorldManager;
9778
9671
  var init_manager = __esm({
9779
9672
  "../core/dist/world/manager.js"() {
9780
9673
  "use strict";
@@ -9823,15 +9716,6 @@ var init_manager = __esm({
9823
9716
  this.name = "WorkspaceNotFoundError";
9824
9717
  }
9825
9718
  };
9826
- RepoSelectionRequiredError = class extends Error {
9827
- availableRepos;
9828
- constructor(availableRepos) {
9829
- const list = availableRepos.length > 0 ? availableRepos.join(", ") : "(none configured)";
9830
- super(`--repos or --workspace is required. Available repos: ${list}. Pick the subset you actually want \u2014 implicit "all repos" was removed to prevent accidental multi-repo bootstraps.`);
9831
- this.availableRepos = availableRepos;
9832
- this.name = "RepoSelectionRequiredError";
9833
- }
9834
- };
9835
9719
  WorldManager = class {
9836
9720
  config;
9837
9721
  provider;
@@ -9859,7 +9743,7 @@ var init_manager = __esm({
9859
9743
  }
9860
9744
  }
9861
9745
  const worldId = generateWorldId();
9862
- const workspacePath = path19.join(os10.homedir(), ".olam", "worlds", worldId);
9746
+ const workspacePath = path18.join(os10.homedir(), ".olam", "worlds", worldId);
9863
9747
  const portOffset = this.registry.getNextPortOffset();
9864
9748
  const branch = opts.branchName ?? `olam/${worldId}`;
9865
9749
  const repos = this.resolveReposWithWorkspace(opts);
@@ -9916,37 +9800,37 @@ var init_manager = __esm({
9916
9800
  if (!repo.path)
9917
9801
  continue;
9918
9802
  const sourceRoot = repo.path.replace(/^~/, os10.homedir());
9919
- const worktreeRoot = path19.join(workspacePath, repo.name);
9920
- if (!fs17.existsSync(sourceRoot) || !fs17.existsSync(worktreeRoot))
9803
+ const worktreeRoot = path18.join(workspacePath, repo.name);
9804
+ if (!fs16.existsSync(sourceRoot) || !fs16.existsSync(worktreeRoot))
9921
9805
  continue;
9922
9806
  let copied = 0;
9923
9807
  for (const pattern of RUNTIME_FILE_PATTERNS) {
9924
9808
  const matches2 = [];
9925
9809
  if (pattern.includes("*")) {
9926
- const [dir, glob] = [path19.dirname(pattern), path19.basename(pattern)];
9927
- const sourceDir = path19.join(sourceRoot, dir);
9928
- if (fs17.existsSync(sourceDir)) {
9810
+ const [dir, glob] = [path18.dirname(pattern), path18.basename(pattern)];
9811
+ const sourceDir = path18.join(sourceRoot, dir);
9812
+ if (fs16.existsSync(sourceDir)) {
9929
9813
  const ext2 = glob.replace(/^\*+/, "");
9930
9814
  try {
9931
- for (const entry of fs17.readdirSync(sourceDir)) {
9815
+ for (const entry of fs16.readdirSync(sourceDir)) {
9932
9816
  if (ext2 === "" || entry.endsWith(ext2))
9933
- matches2.push(path19.join(dir, entry));
9817
+ matches2.push(path18.join(dir, entry));
9934
9818
  }
9935
9819
  } catch {
9936
9820
  }
9937
9821
  }
9938
- } else if (fs17.existsSync(path19.join(sourceRoot, pattern))) {
9822
+ } else if (fs16.existsSync(path18.join(sourceRoot, pattern))) {
9939
9823
  matches2.push(pattern);
9940
9824
  }
9941
9825
  for (const rel of matches2) {
9942
- const src = path19.join(sourceRoot, rel);
9943
- const dst = path19.join(worktreeRoot, rel);
9826
+ const src = path18.join(sourceRoot, rel);
9827
+ const dst = path18.join(worktreeRoot, rel);
9944
9828
  try {
9945
- const st = fs17.statSync(src);
9829
+ const st = fs16.statSync(src);
9946
9830
  if (!st.isFile())
9947
9831
  continue;
9948
- fs17.mkdirSync(path19.dirname(dst), { recursive: true });
9949
- fs17.copyFileSync(src, dst);
9832
+ fs16.mkdirSync(path18.dirname(dst), { recursive: true });
9833
+ fs16.copyFileSync(src, dst);
9950
9834
  copied++;
9951
9835
  } catch {
9952
9836
  }
@@ -10046,7 +9930,7 @@ var init_manager = __esm({
10046
9930
  try {
10047
9931
  const hostExec = makeHostExecFn();
10048
9932
  for (const repo of repos) {
10049
- const repoDir = path19.join(workspacePath, repo.name);
9933
+ const repoDir = path18.join(workspacePath, repo.name);
10050
9934
  if (repo.stack && Object.keys(repo.stack).length > 0) {
10051
9935
  preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
10052
9936
  } else {
@@ -10103,10 +9987,10 @@ var init_manager = __esm({
10103
9987
  const worldEnv = {};
10104
9988
  if (opts.task)
10105
9989
  worldEnv.OLAM_TASK = opts.task;
10106
- const r2CredsPath = path19.join(os10.homedir(), ".olam", "r2-credentials.json");
10107
- if (fs17.existsSync(r2CredsPath)) {
9990
+ const r2CredsPath = path18.join(os10.homedir(), ".olam", "r2-credentials.json");
9991
+ if (fs16.existsSync(r2CredsPath)) {
10108
9992
  try {
10109
- const r2Raw = fs17.readFileSync(r2CredsPath, "utf-8").trim();
9993
+ const r2Raw = fs16.readFileSync(r2CredsPath, "utf-8").trim();
10110
9994
  if (r2Raw.length > 0) {
10111
9995
  const r2 = JSON.parse(r2Raw);
10112
9996
  if (typeof r2.account_id === "string")
@@ -10123,10 +10007,10 @@ var init_manager = __esm({
10123
10007
  } catch {
10124
10008
  }
10125
10009
  }
10126
- const keysYamlPath = path19.join(os10.homedir(), ".olam", "keys.yaml");
10127
- if (fs17.existsSync(keysYamlPath)) {
10010
+ const keysYamlPath = path18.join(os10.homedir(), ".olam", "keys.yaml");
10011
+ if (fs16.existsSync(keysYamlPath)) {
10128
10012
  try {
10129
- const keysRaw = fs17.readFileSync(keysYamlPath, "utf-8").trim();
10013
+ const keysRaw = fs16.readFileSync(keysYamlPath, "utf-8").trim();
10130
10014
  if (keysRaw.length > 0) {
10131
10015
  const parsed = YAML3.parse(keysRaw);
10132
10016
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
@@ -10173,10 +10057,10 @@ var init_manager = __esm({
10173
10057
  worldEnv[k] = v;
10174
10058
  }
10175
10059
  for (const { repoName, relativePath, content } of fileWrites) {
10176
- const absPath = path19.join(workspacePath, repoName, relativePath);
10060
+ const absPath = path18.join(workspacePath, repoName, relativePath);
10177
10061
  try {
10178
- fs17.mkdirSync(path19.dirname(absPath), { recursive: true });
10179
- fs17.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
10062
+ fs16.mkdirSync(path18.dirname(absPath), { recursive: true });
10063
+ fs16.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
10180
10064
  mode: 384
10181
10065
  });
10182
10066
  console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
@@ -10328,7 +10212,7 @@ var init_manager = __esm({
10328
10212
  let taskWithPolicies = opts.task;
10329
10213
  try {
10330
10214
  const allPolicies = repos.flatMap((repo) => {
10331
- const repoWorktree = path19.join(workspacePath, repo.name);
10215
+ const repoWorktree = path18.join(workspacePath, repo.name);
10332
10216
  return loadPolicies(repoWorktree);
10333
10217
  });
10334
10218
  const seen = /* @__PURE__ */ new Set();
@@ -10344,8 +10228,8 @@ var init_manager = __esm({
10344
10228
  ${opts.task}`;
10345
10229
  execSync4(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
10346
10230
  for (const repo of repos) {
10347
- const policiesDir = path19.join(workspacePath, repo.name, ".olam", "policies");
10348
- if (fs17.existsSync(policiesDir)) {
10231
+ const policiesDir = path18.join(workspacePath, repo.name, ".olam", "policies");
10232
+ if (fs16.existsSync(policiesDir)) {
10349
10233
  execSync4(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
10350
10234
  }
10351
10235
  }
@@ -10424,8 +10308,8 @@ ${opts.task}`;
10424
10308
  } catch {
10425
10309
  }
10426
10310
  try {
10427
- fs17.rmSync(world.workspacePath, { recursive: true, force: true });
10428
- if (fs17.existsSync(world.workspacePath)) {
10311
+ fs16.rmSync(world.workspacePath, { recursive: true, force: true });
10312
+ if (fs16.existsSync(world.workspacePath)) {
10429
10313
  console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
10430
10314
  }
10431
10315
  } catch (err) {
@@ -10480,10 +10364,7 @@ ${opts.task}`;
10480
10364
  * Resolution precedence (matches the CF worker exactly):
10481
10365
  * 1. inline `opts.repos` names → look up in `config.repos`
10482
10366
  * 2. named `opts.workspace` → load catalog YAML, map via workspaceToRepoConfigs
10483
- * 3. neitherthrow `RepoSelectionRequiredError`. The historical
10484
- * "include every repo in config.yaml" fallback silently fanned a
10485
- * single-repo audit into 7-repo bootstraps and steered
10486
- * `image_selectors` to a wider tag than intended.
10367
+ * 3. fallbackevery repo declared in the project's config.yaml
10487
10368
  */
10488
10369
  resolveReposWithWorkspace(opts) {
10489
10370
  if (opts.repos && opts.repos.length > 0) {
@@ -10495,7 +10376,7 @@ ${opts.task}`;
10495
10376
  throw new WorkspaceNotFoundError(opts.workspace);
10496
10377
  return workspaceToRepoConfigs(ws);
10497
10378
  }
10498
- throw new RepoSelectionRequiredError(this.config.repos.map((r) => r.name));
10379
+ return this.resolveRepos(void 0);
10499
10380
  }
10500
10381
  resolveRepos(repoNames) {
10501
10382
  if (!repoNames || repoNames.length === 0) {
@@ -10513,14 +10394,14 @@ ${opts.task}`;
10513
10394
  return names.map((name) => this.config.repos.find((r) => r.name === name)).filter((r) => r !== void 0);
10514
10395
  }
10515
10396
  transportPlanFile(planFilePath, workspacePath, repoNames) {
10516
- const planContent = fs17.readFileSync(planFilePath, "utf-8");
10517
- const planFileName = path19.basename(planFilePath);
10397
+ const planContent = fs16.readFileSync(planFilePath, "utf-8");
10398
+ const planFileName = path18.basename(planFilePath);
10518
10399
  const targetRepo = repoNames[0];
10519
10400
  if (!targetRepo)
10520
10401
  return;
10521
- const plansDir = path19.join(workspacePath, targetRepo, "docs", "plans");
10522
- fs17.mkdirSync(plansDir, { recursive: true });
10523
- fs17.writeFileSync(path19.join(plansDir, planFileName), planContent);
10402
+ const plansDir = path18.join(workspacePath, targetRepo, "docs", "plans");
10403
+ fs16.mkdirSync(plansDir, { recursive: true });
10404
+ fs16.writeFileSync(path18.join(plansDir, planFileName), planContent);
10524
10405
  }
10525
10406
  resolveServices(repos) {
10526
10407
  const services = [];
@@ -10613,9 +10494,9 @@ var init_tracker = __esm({
10613
10494
  });
10614
10495
 
10615
10496
  // ../core/dist/world-paths.js
10616
- import * as path20 from "node:path";
10497
+ import * as path19 from "node:path";
10617
10498
  function getWorldDbPath(workspacePath) {
10618
- return path20.join(workspacePath, WORLD_DB_FILENAME);
10499
+ return path19.join(workspacePath, WORLD_DB_FILENAME);
10619
10500
  }
10620
10501
  var WORLD_DB_FILENAME;
10621
10502
  var init_world_paths = __esm({
@@ -11233,8 +11114,8 @@ var init_session_aggregator = __esm({
11233
11114
 
11234
11115
  // ../core/dist/dashboard/server.js
11235
11116
  import * as http from "node:http";
11236
- import * as fs18 from "node:fs";
11237
- import * as path21 from "node:path";
11117
+ import * as fs17 from "node:fs";
11118
+ import * as path20 from "node:path";
11238
11119
  import { fileURLToPath as fileURLToPath2 } from "node:url";
11239
11120
  function jsonResponse(res, data, status = 200) {
11240
11121
  res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
@@ -11245,7 +11126,7 @@ function notFound(res) {
11245
11126
  }
11246
11127
  function openThoughtStore(workspacePath) {
11247
11128
  const dbPath = getWorldDbPath(workspacePath);
11248
- if (!fs18.existsSync(dbPath))
11129
+ if (!fs17.existsSync(dbPath))
11249
11130
  return null;
11250
11131
  return new ThoughtLocalStore(dbPath);
11251
11132
  }
@@ -11416,13 +11297,13 @@ function findSessionInWorld(registry, sessionId) {
11416
11297
  }
11417
11298
  function createDashboardServer(opts) {
11418
11299
  const { port, registry } = opts;
11419
- const thisDir = path21.dirname(fileURLToPath2(import.meta.url));
11420
- const defaultPublicDir = path21.resolve(thisDir, "../../../control-plane/public");
11300
+ const thisDir = path20.dirname(fileURLToPath2(import.meta.url));
11301
+ const defaultPublicDir = path20.resolve(thisDir, "../../../control-plane/public");
11421
11302
  const publicDir = opts.publicDir ?? defaultPublicDir;
11422
- let hasPublicDir = fs18.existsSync(publicDir);
11303
+ let hasPublicDir = fs17.existsSync(publicDir);
11423
11304
  const server = http.createServer((req, res) => {
11424
11305
  if (!hasPublicDir) {
11425
- hasPublicDir = fs18.existsSync(publicDir);
11306
+ hasPublicDir = fs17.existsSync(publicDir);
11426
11307
  }
11427
11308
  const host = req.headers.host ?? `localhost:${port}`;
11428
11309
  const url = new URL(req.url ?? "/", `http://${host}`);
@@ -11696,22 +11577,22 @@ function createDashboardServer(opts) {
11696
11577
  res.end(`<html><body style="font-family:system-ui;padding:2rem"><h1>Olam Dashboard</h1><p>The React app has not been built yet.</p><p>Run <code>npm run build:app</code> in <code>packages/control-plane</code> to build it.</p><p>API routes are available at <code>/api/*</code>.</p></body></html>`);
11697
11578
  return;
11698
11579
  }
11699
- let filePath = path21.join(publicDir, pathname === "/" ? "index.html" : pathname);
11580
+ let filePath = path20.join(publicDir, pathname === "/" ? "index.html" : pathname);
11700
11581
  if (!filePath.startsWith(publicDir)) {
11701
11582
  notFound(res);
11702
11583
  return;
11703
11584
  }
11704
- if (fs18.existsSync(filePath) && fs18.statSync(filePath).isFile()) {
11705
- const ext2 = path21.extname(filePath);
11585
+ if (fs17.existsSync(filePath) && fs17.statSync(filePath).isFile()) {
11586
+ const ext2 = path20.extname(filePath);
11706
11587
  const contentType = MIME[ext2] ?? "application/octet-stream";
11707
11588
  res.writeHead(200, { "Content-Type": contentType });
11708
- fs18.createReadStream(filePath).pipe(res);
11589
+ fs17.createReadStream(filePath).pipe(res);
11709
11590
  return;
11710
11591
  }
11711
- filePath = path21.join(publicDir, "index.html");
11712
- if (fs18.existsSync(filePath)) {
11592
+ filePath = path20.join(publicDir, "index.html");
11593
+ if (fs17.existsSync(filePath)) {
11713
11594
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
11714
- fs18.createReadStream(filePath).pipe(res);
11595
+ fs17.createReadStream(filePath).pipe(res);
11715
11596
  return;
11716
11597
  }
11717
11598
  notFound(res);
@@ -11742,16 +11623,16 @@ var init_server = __esm({
11742
11623
  });
11743
11624
 
11744
11625
  // ../core/dist/dashboard/state.js
11745
- import * as fs19 from "node:fs";
11626
+ import * as fs18 from "node:fs";
11746
11627
  import * as os11 from "node:os";
11747
- import * as path22 from "node:path";
11628
+ import * as path21 from "node:path";
11748
11629
  function saveDashboardState(state) {
11749
- fs19.mkdirSync(path22.dirname(STATE_PATH), { recursive: true });
11750
- fs19.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
11630
+ fs18.mkdirSync(path21.dirname(STATE_PATH), { recursive: true });
11631
+ fs18.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
11751
11632
  }
11752
11633
  function loadDashboardState() {
11753
11634
  try {
11754
- const raw = fs19.readFileSync(STATE_PATH, "utf-8");
11635
+ const raw = fs18.readFileSync(STATE_PATH, "utf-8");
11755
11636
  return JSON.parse(raw);
11756
11637
  } catch {
11757
11638
  return null;
@@ -11759,7 +11640,7 @@ function loadDashboardState() {
11759
11640
  }
11760
11641
  function clearDashboardState() {
11761
11642
  try {
11762
- fs19.unlinkSync(STATE_PATH);
11643
+ fs18.unlinkSync(STATE_PATH);
11763
11644
  } catch {
11764
11645
  }
11765
11646
  }
@@ -11779,7 +11660,7 @@ var STATE_PATH;
11779
11660
  var init_state2 = __esm({
11780
11661
  "../core/dist/dashboard/state.js"() {
11781
11662
  "use strict";
11782
- STATE_PATH = path22.join(os11.homedir(), ".olam", "dashboard.json");
11663
+ STATE_PATH = path21.join(os11.homedir(), ".olam", "dashboard.json");
11783
11664
  }
11784
11665
  });
11785
11666
 
@@ -12173,51 +12054,51 @@ __export(host_cp_exports, {
12173
12054
  writePid: () => writePid,
12174
12055
  writeToken: () => writeToken
12175
12056
  });
12176
- import * as crypto6 from "node:crypto";
12177
- import * as fs20 from "node:fs";
12057
+ import * as crypto5 from "node:crypto";
12058
+ import * as fs19 from "node:fs";
12178
12059
  import * as os12 from "node:os";
12179
- import * as path23 from "node:path";
12060
+ import * as path22 from "node:path";
12180
12061
  import { spawnSync as spawnSync4 } from "node:child_process";
12181
12062
  import Dockerode2 from "dockerode";
12182
12063
  function findComposeFile() {
12183
12064
  const candidates = [
12184
12065
  // Bundled path: dist/index.js lives at <pkg>/dist/; host-cp/ is a sibling of dist/
12185
- path23.resolve(path23.dirname(new URL(import.meta.url).pathname), "../host-cp/compose.yaml"),
12066
+ path22.resolve(path22.dirname(new URL(import.meta.url).pathname), "../host-cp/compose.yaml"),
12186
12067
  // Source-mode: cwd is monorepo root
12187
- path23.resolve(process.cwd(), "packages/host-cp/compose.yaml"),
12068
+ path22.resolve(process.cwd(), "packages/host-cp/compose.yaml"),
12188
12069
  // Source-mode: cwd is one level inside the monorepo
12189
- path23.resolve(process.cwd(), "../packages/host-cp/compose.yaml")
12070
+ path22.resolve(process.cwd(), "../packages/host-cp/compose.yaml")
12190
12071
  ];
12191
12072
  for (const c of candidates) {
12192
- if (fs20.existsSync(c)) return c;
12073
+ if (fs19.existsSync(c)) return c;
12193
12074
  }
12194
- return path23.resolve(process.cwd(), "packages/host-cp/compose.yaml");
12075
+ return path22.resolve(process.cwd(), "packages/host-cp/compose.yaml");
12195
12076
  }
12196
12077
  function olamHome() {
12197
- return process.env.OLAM_HOME ?? path23.join(os12.homedir(), ".olam");
12078
+ return process.env.OLAM_HOME ?? path22.join(os12.homedir(), ".olam");
12198
12079
  }
12199
12080
  function tokenPath() {
12200
- return path23.join(olamHome(), "host-cp.token");
12081
+ return path22.join(olamHome(), "host-cp.token");
12201
12082
  }
12202
12083
  function pidPath() {
12203
- return path23.join(olamHome(), "host-cp.pid");
12084
+ return path22.join(olamHome(), "host-cp.pid");
12204
12085
  }
12205
12086
  function authSecretPath() {
12206
- return path23.join(olamHome(), "auth-secret");
12087
+ return path22.join(olamHome(), "auth-secret");
12207
12088
  }
12208
12089
  function readAuthSecret2() {
12209
12090
  const filePath = authSecretPath();
12210
- if (!fs20.existsSync(filePath)) return null;
12211
- const raw = fs20.readFileSync(filePath, "utf-8").trim();
12091
+ if (!fs19.existsSync(filePath)) return null;
12092
+ const raw = fs19.readFileSync(filePath, "utf-8").trim();
12212
12093
  return raw.length > 0 ? raw : null;
12213
12094
  }
12214
12095
  function r2CredentialsPath() {
12215
- return path23.join(olamHome(), "r2-credentials.json");
12096
+ return path22.join(olamHome(), "r2-credentials.json");
12216
12097
  }
12217
12098
  function readR2Credentials() {
12218
12099
  const filePath = r2CredentialsPath();
12219
- if (!fs20.existsSync(filePath)) return null;
12220
- const raw = fs20.readFileSync(filePath, "utf-8").trim();
12100
+ if (!fs19.existsSync(filePath)) return null;
12101
+ const raw = fs19.readFileSync(filePath, "utf-8").trim();
12221
12102
  if (raw.length === 0) return null;
12222
12103
  try {
12223
12104
  const parsed = JSON.parse(raw);
@@ -12238,39 +12119,39 @@ function readR2Credentials() {
12238
12119
  }
12239
12120
  }
12240
12121
  function writeToken() {
12241
- const token = crypto6.randomBytes(32).toString("hex");
12122
+ const token = crypto5.randomBytes(32).toString("hex");
12242
12123
  const filePath = tokenPath();
12243
- fs20.mkdirSync(path23.dirname(filePath), { recursive: true });
12244
- fs20.writeFileSync(filePath, token, { mode: 384 });
12124
+ fs19.mkdirSync(path22.dirname(filePath), { recursive: true });
12125
+ fs19.writeFileSync(filePath, token, { mode: 384 });
12245
12126
  return token;
12246
12127
  }
12247
12128
  function readToken() {
12248
12129
  const filePath = tokenPath();
12249
- if (!fs20.existsSync(filePath)) return null;
12250
- return fs20.readFileSync(filePath, "utf-8").trim();
12130
+ if (!fs19.existsSync(filePath)) return null;
12131
+ return fs19.readFileSync(filePath, "utf-8").trim();
12251
12132
  }
12252
12133
  function removeToken() {
12253
12134
  const filePath = tokenPath();
12254
- if (!fs20.existsSync(filePath)) return false;
12255
- fs20.unlinkSync(filePath);
12135
+ if (!fs19.existsSync(filePath)) return false;
12136
+ fs19.unlinkSync(filePath);
12256
12137
  return true;
12257
12138
  }
12258
12139
  function writePid(pid) {
12259
12140
  const filePath = pidPath();
12260
- fs20.mkdirSync(path23.dirname(filePath), { recursive: true });
12261
- fs20.writeFileSync(filePath, String(pid), { mode: 420 });
12141
+ fs19.mkdirSync(path22.dirname(filePath), { recursive: true });
12142
+ fs19.writeFileSync(filePath, String(pid), { mode: 420 });
12262
12143
  }
12263
12144
  function readPid() {
12264
12145
  const filePath = pidPath();
12265
- if (!fs20.existsSync(filePath)) return null;
12266
- const raw = fs20.readFileSync(filePath, "utf-8").trim();
12146
+ if (!fs19.existsSync(filePath)) return null;
12147
+ const raw = fs19.readFileSync(filePath, "utf-8").trim();
12267
12148
  const n = parseInt(raw, 10);
12268
12149
  return Number.isFinite(n) ? n : null;
12269
12150
  }
12270
12151
  function removePid() {
12271
12152
  const filePath = pidPath();
12272
- if (!fs20.existsSync(filePath)) return false;
12273
- fs20.unlinkSync(filePath);
12153
+ if (!fs19.existsSync(filePath)) return false;
12154
+ fs19.unlinkSync(filePath);
12274
12155
  return true;
12275
12156
  }
12276
12157
  async function findHostCpContainer() {
@@ -12429,7 +12310,7 @@ async function handleStart(opts) {
12429
12310
  }
12430
12311
  const token = writeToken();
12431
12312
  const composeFile = findComposeFile();
12432
- if (!fs20.existsSync(composeFile)) {
12313
+ if (!fs19.existsSync(composeFile)) {
12433
12314
  printError(`compose.yaml not found at ${composeFile}. Run from the olam project root.`);
12434
12315
  removeToken();
12435
12316
  process.exitCode = 1;
@@ -12511,7 +12392,7 @@ async function stopHostCp() {
12511
12392
  }
12512
12393
  async function handleStop() {
12513
12394
  const composeFile = findComposeFile();
12514
- if (!fs20.existsSync(composeFile)) {
12395
+ if (!fs19.existsSync(composeFile)) {
12515
12396
  printWarning(`compose.yaml not found at ${composeFile}. Cleaning up token + PID anyway.`);
12516
12397
  removeToken();
12517
12398
  removePid();
@@ -12539,13 +12420,13 @@ async function buildStatusReport() {
12539
12420
  const container = await findHostCpContainer();
12540
12421
  const health = await probeHealth();
12541
12422
  const tokenFile = tokenPath();
12542
- const tokenPresent = fs20.existsSync(tokenFile);
12423
+ const tokenPresent = fs19.existsSync(tokenFile);
12543
12424
  let tokenModeOk = false;
12544
12425
  if (tokenPresent) {
12545
- const mode = fs20.statSync(tokenFile).mode & 511;
12426
+ const mode = fs19.statSync(tokenFile).mode & 511;
12546
12427
  tokenModeOk = mode === 384;
12547
12428
  }
12548
- const pidPresent = fs20.existsSync(pidPath());
12429
+ const pidPresent = fs19.existsSync(pidPath());
12549
12430
  let stack;
12550
12431
  if (!container) {
12551
12432
  stack = "not_started";
@@ -12633,13 +12514,13 @@ async function discoverWorldPort(worldId) {
12633
12514
  }
12634
12515
  async function readHostCpToken2() {
12635
12516
  const tp = tokenPath();
12636
- if (!fs20.existsSync(tp)) return null;
12637
- return fs20.readFileSync(tp, "utf-8").trim();
12517
+ if (!fs19.existsSync(tp)) return null;
12518
+ return fs19.readFileSync(tp, "utf-8").trim();
12638
12519
  }
12639
- async function callHostCpProxy(method, worldId, path45, body) {
12520
+ async function callHostCpProxy(method, worldId, path44, body) {
12640
12521
  const token = await readHostCpToken2();
12641
12522
  if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
12642
- const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path45}`;
12523
+ const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path44}`;
12643
12524
  try {
12644
12525
  const headers = {
12645
12526
  Authorization: `Bearer ${token}`
@@ -12764,17 +12645,17 @@ __export(install_root_exports, {
12764
12645
  isDevMode: () => isDevMode,
12765
12646
  resolveBuildScript: () => resolveBuildScript
12766
12647
  });
12767
- import { existsSync as existsSync19 } from "node:fs";
12768
- import { dirname as dirname14, join as join24, resolve as resolve6 } from "node:path";
12648
+ import { existsSync as existsSync18 } from "node:fs";
12649
+ import { dirname as dirname13, join as join24, resolve as resolve6 } from "node:path";
12769
12650
  import { fileURLToPath as fileURLToPath3 } from "node:url";
12770
12651
  function installRoot(metaUrl = import.meta.url) {
12771
12652
  const here = fileURLToPath3(metaUrl);
12772
- return resolve6(dirname14(here), "..");
12653
+ return resolve6(dirname13(here), "..");
12773
12654
  }
12774
12655
  function isDevMode(env = process.env, installRootDir = installRoot()) {
12775
12656
  if (env.OLAM_DEV !== "1") return false;
12776
12657
  const repoRoot = resolve6(installRootDir, "..", "..");
12777
- return existsSync19(join24(repoRoot, "packages")) && existsSync19(join24(repoRoot, "package.json"));
12658
+ return existsSync18(join24(repoRoot, "packages")) && existsSync18(join24(repoRoot, "package.json"));
12778
12659
  }
12779
12660
  function resolveBuildScript(input) {
12780
12661
  const { scriptRelPath, env = process.env, installRootDir = installRoot() } = input;
@@ -12953,20 +12834,20 @@ var init_registry_allowlist = __esm({
12953
12834
  });
12954
12835
 
12955
12836
  // ../core/dist/world/world-yaml.js
12956
- import * as fs22 from "node:fs";
12957
- import * as path25 from "node:path";
12837
+ import * as fs21 from "node:fs";
12838
+ import * as path24 from "node:path";
12958
12839
  import { parse as parseYaml4, stringify as stringifyYaml4 } from "yaml";
12959
12840
  function writeWorldYaml(worldPath, data) {
12960
- const olamDir = path25.join(worldPath, ".olam");
12961
- fs22.mkdirSync(olamDir, { recursive: true });
12962
- fs22.writeFileSync(path25.join(olamDir, "world.yaml"), stringifyYaml4(data), "utf-8");
12841
+ const olamDir = path24.join(worldPath, ".olam");
12842
+ fs21.mkdirSync(olamDir, { recursive: true });
12843
+ fs21.writeFileSync(path24.join(olamDir, "world.yaml"), stringifyYaml4(data), "utf-8");
12963
12844
  }
12964
12845
  function readWorldYaml(worldPath) {
12965
- const yamlPath = path25.join(worldPath, ".olam", "world.yaml");
12966
- if (!fs22.existsSync(yamlPath))
12846
+ const yamlPath = path24.join(worldPath, ".olam", "world.yaml");
12847
+ if (!fs21.existsSync(yamlPath))
12967
12848
  return null;
12968
12849
  try {
12969
- const raw = fs22.readFileSync(yamlPath, "utf-8");
12850
+ const raw = fs21.readFileSync(yamlPath, "utf-8");
12970
12851
  const parsed = parseYaml4(raw);
12971
12852
  return WorldYamlSchema.parse(parsed);
12972
12853
  } catch {
@@ -13097,16 +12978,16 @@ __export(machine_schema_exports, {
13097
12978
  readMachineConfig: () => readMachineConfig,
13098
12979
  writeMachineConfig: () => writeMachineConfig
13099
12980
  });
13100
- import * as fs36 from "node:fs";
13101
- import * as path40 from "node:path";
12981
+ import * as fs35 from "node:fs";
12982
+ import * as path39 from "node:path";
13102
12983
  import * as os21 from "node:os";
13103
12984
  import { parse as parseYaml5, stringify as stringifyYaml5 } from "yaml";
13104
12985
  function readMachineConfig(configPath) {
13105
12986
  const p = configPath ?? DEFAULT_CONFIG_PATH;
13106
- if (!fs36.existsSync(p))
12987
+ if (!fs35.existsSync(p))
13107
12988
  return null;
13108
12989
  try {
13109
- const raw = fs36.readFileSync(p, "utf-8");
12990
+ const raw = fs35.readFileSync(p, "utf-8");
13110
12991
  const parsed = parseYaml5(raw);
13111
12992
  return MachineConfigSchema.parse(parsed);
13112
12993
  } catch {
@@ -13115,8 +12996,8 @@ function readMachineConfig(configPath) {
13115
12996
  }
13116
12997
  function writeMachineConfig(config, configPath) {
13117
12998
  const p = configPath ?? DEFAULT_CONFIG_PATH;
13118
- fs36.mkdirSync(path40.dirname(p), { recursive: true });
13119
- fs36.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
12999
+ fs35.mkdirSync(path39.dirname(p), { recursive: true });
13000
+ fs35.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
13120
13001
  }
13121
13002
  function initMachineConfig(opts = {}) {
13122
13003
  const configPath = opts.configPath ?? DEFAULT_CONFIG_PATH;
@@ -13139,16 +13020,16 @@ var init_machine_schema = __esm({
13139
13020
  channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
13140
13021
  auto_update: external_exports.boolean().default(true),
13141
13022
  telemetry: external_exports.boolean().default(true),
13142
- worlds_dir: external_exports.string().default(() => path40.join(os21.homedir(), ".olam", "worlds"))
13023
+ worlds_dir: external_exports.string().default(() => path39.join(os21.homedir(), ".olam", "worlds"))
13143
13024
  });
13144
- DEFAULT_CONFIG_PATH = path40.join(os21.homedir(), ".olam", "config.yaml");
13025
+ DEFAULT_CONFIG_PATH = path39.join(os21.homedir(), ".olam", "config.yaml");
13145
13026
  }
13146
13027
  });
13147
13028
 
13148
13029
  // src/index.ts
13149
13030
  import { Command } from "commander";
13150
- import * as fs40 from "node:fs";
13151
- import * as path44 from "node:path";
13031
+ import * as fs39 from "node:fs";
13032
+ import * as path43 from "node:path";
13152
13033
  import { fileURLToPath as fileURLToPath4 } from "node:url";
13153
13034
 
13154
13035
  // src/commands/init.ts
@@ -13525,9 +13406,9 @@ var UnknownArchetypeError = class extends Error {
13525
13406
  };
13526
13407
  var ArchetypeCycleError = class extends Error {
13527
13408
  path;
13528
- constructor(path45) {
13529
- super(`Archetype inheritance cycle detected: ${path45.join(" \u2192 ")} \u2192 ${path45[0] ?? "?"}`);
13530
- this.path = path45;
13409
+ constructor(path44) {
13410
+ super(`Archetype inheritance cycle detected: ${path44.join(" \u2192 ")} \u2192 ${path44[0] ?? "?"}`);
13411
+ this.path = path44;
13531
13412
  this.name = "ArchetypeCycleError";
13532
13413
  }
13533
13414
  };
@@ -13721,7 +13602,7 @@ function registerInstall(program2) {
13721
13602
  // src/commands/auth.ts
13722
13603
  init_auth();
13723
13604
  init_output();
13724
- import pc8 from "picocolors";
13605
+ import pc9 from "picocolors";
13725
13606
  import * as readline from "node:readline/promises";
13726
13607
  import { spawn as spawn3 } from "node:child_process";
13727
13608
 
@@ -13730,174 +13611,17 @@ import * as fs8 from "node:fs";
13730
13611
  import * as os5 from "node:os";
13731
13612
  import * as path9 from "node:path";
13732
13613
  import pc5 from "picocolors";
13733
-
13734
- // ../auth-logic/dist/effective-state.js
13735
- function effectiveState(account, now = Date.now()) {
13736
- const persisted = account.state ?? (account.rateLimited ? "cooldown" : "active");
13737
- if (persisted === "disabled")
13738
- return "disabled";
13739
- if (account.expiresAt != null && account.expiresAt <= now)
13740
- return "expired";
13741
- if (persisted === "cooldown" || persisted === "usage-capped") {
13742
- const reset = account.rateLimitResetsAt ? new Date(account.rateLimitResetsAt).getTime() : 0;
13743
- if (reset > 0 && reset <= now)
13744
- return "active";
13745
- return persisted;
13746
- }
13747
- return "active";
13748
- }
13749
-
13750
- // ../auth-logic/dist/pick-credential.js
13751
- function pickCredential(accounts, now = Date.now()) {
13752
- const active = accounts.filter((a) => effectiveState(a, now) === "active");
13753
- if (active.length === 0)
13754
- return null;
13755
- return [...active].sort((a, b) => {
13756
- const aCount = a.usage?.requestCount5h ?? 0;
13757
- const bCount = b.usage?.requestCount5h ?? 0;
13758
- if (aCount !== bCount)
13759
- return aCount - bCount;
13760
- const aLast = a.lastUsed ? new Date(a.lastUsed).getTime() : 0;
13761
- const bLast = b.lastUsed ? new Date(b.lastUsed).getTime() : 0;
13762
- return aLast - bLast;
13763
- })[0] ?? null;
13764
- }
13765
-
13766
- // ../auth-logic/dist/next-cooldown-reset.js
13767
- function nextCooldownReset(accounts, now = Date.now()) {
13768
- const upcoming = accounts.filter((a) => effectiveState(a, now) === "cooldown").map((a) => a.rateLimitResetsAt ? new Date(a.rateLimitResetsAt).getTime() : 0).filter((ts) => ts > now).sort((a, b) => a - b);
13769
- return upcoming.length > 0 ? new Date(upcoming[0]).toISOString() : null;
13770
- }
13771
-
13772
- // src/commands/auth-status.ts
13773
13614
  init_auth();
13774
13615
  init_output();
13775
13616
  init_exit_codes();
13776
13617
  var LOCAL_DATA_DIR = path9.join(os5.homedir(), ".olam", "auth-data");
13777
- function localHHMM(isoStr) {
13778
- const d = new Date(isoStr);
13779
- return d.toLocaleTimeString(void 0, {
13780
- hour: "2-digit",
13781
- minute: "2-digit",
13782
- hour12: false
13783
- });
13784
- }
13785
- function daysAgoStr(expiresAt, now) {
13786
- const diffDays = Math.floor((now - expiresAt) / (1e3 * 60 * 60 * 24));
13787
- if (diffDays <= 0) return "expired today";
13788
- return `expired ${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
13789
- }
13790
- function trunc(s, maxLen) {
13791
- return s.length > maxLen ? s.slice(0, maxLen) : s;
13792
- }
13793
- var STATE_PRIORITY = {
13794
- active: 0,
13795
- cooldown: 1,
13796
- "usage-capped": 2,
13797
- disabled: 3,
13798
- expired: 4
13799
- };
13800
- function formatAuthStatus(accounts, now = Date.now()) {
13801
- const picked = pickCredential(accounts, now);
13802
- const rows = accounts.map((account) => {
13803
- const state = effectiveState(account, now);
13804
- const isPicked = picked != null && account.id === picked.id;
13805
- const req5h = account.usage?.requestCount5h ?? 0;
13806
- const last429 = account.usage?.last429At ? localHHMM(account.usage.last429At) : "never";
13807
- let reason;
13808
- if (isPicked) {
13809
- reason = "\u2190 selected";
13810
- } else if (state === "active") {
13811
- reason = `req5h=${req5h} (higher than candidate)`;
13812
- } else if (state === "cooldown") {
13813
- const resetTime = account.rateLimitResetsAt ? localHHMM(account.rateLimitResetsAt) : "?";
13814
- reason = `cooldown until ${resetTime}`;
13815
- } else if (state === "expired") {
13816
- reason = daysAgoStr(account.expiresAt ?? 0, now);
13817
- } else {
13818
- reason = "disabled";
13819
- }
13820
- return { id: account.id, label: account.accountLabel ?? account.id, state, reason, req5h, last429, isPicked };
13821
- });
13822
- rows.sort((a, b) => {
13823
- if (a.isPicked !== b.isPicked) return a.isPicked ? -1 : 1;
13824
- return STATE_PRIORITY[a.state] - STATE_PRIORITY[b.state];
13825
- });
13826
- const COL = { id: 17, label: 17, state: 11, reason: 28, req5h: 7 };
13827
- const lines = [];
13828
- const hdr = "id".padEnd(COL.id) + "label".padEnd(COL.label) + "state".padEnd(COL.state) + "reason".padEnd(COL.reason) + "req5h".padEnd(COL.req5h) + "last429";
13829
- lines.push(pc5.dim(hdr));
13830
- lines.push(pc5.dim("-".repeat(hdr.length)));
13831
- for (const row of rows) {
13832
- const id = trunc(row.id, 16).padEnd(COL.id);
13833
- const label = trunc(row.label, 16).padEnd(COL.label);
13834
- const stateRaw = row.state.padEnd(COL.state);
13835
- const stateColored = row.state === "active" ? pc5.green(stateRaw) : row.state === "cooldown" ? pc5.yellow(stateRaw) : row.state === "expired" ? pc5.red(stateRaw) : pc5.dim(stateRaw);
13836
- const reason = row.reason.padEnd(COL.reason);
13837
- const req5h = String(row.req5h).padEnd(COL.req5h);
13838
- if (row.isPicked) {
13839
- lines.push(
13840
- pc5.bold(id) + pc5.bold(label) + stateColored + pc5.green(reason) + pc5.dim(req5h) + pc5.dim(row.last429)
13841
- );
13842
- } else {
13843
- lines.push(id + label + stateColored + reason + pc5.dim(req5h) + pc5.dim(row.last429));
13844
- }
13845
- }
13846
- if (picked == null) {
13847
- const resetIso = nextCooldownReset(accounts, now);
13848
- lines.push("");
13849
- lines.push(
13850
- resetIso ? pc5.yellow(`Next reset: ${localHHMM(resetIso)}`) : pc5.dim("No reset scheduled")
13851
- );
13852
- return { output: lines.join("\n"), exitCode: EXIT_AUTH_NEEDS_ATTENTION };
13853
- }
13854
- return { output: lines.join("\n"), exitCode: 0 };
13855
- }
13856
- function toSafeAccount(a) {
13857
- return {
13858
- id: a.id,
13859
- accountLabel: a.accountLabel,
13860
- // expiresAt not exposed in summary — state is pre-computed server-side
13861
- rateLimited: a.rateLimited,
13862
- rateLimitResetsAt: a.rateLimitResetsAt,
13863
- lastUsed: a.lastUsed,
13864
- state: a.state,
13865
- usage: a.usage ? { requestCount5h: a.usage.requestCount5h, last429At: a.usage.last429At } : void 0
13866
- };
13867
- }
13868
- async function runAuthStatus(getStatus) {
13869
- const fetchStatus = getStatus ?? (() => new AuthClient().status());
13870
- let status;
13871
- try {
13872
- status = await fetchStatus();
13873
- } catch {
13874
- printError("Failed to contact auth service. Run `olam auth up` first.");
13875
- process.exitCode = 1;
13876
- return;
13877
- }
13878
- if (!status.reachable) {
13879
- printError("Auth container is not reachable. Run `olam auth up` first.");
13880
- process.exitCode = 1;
13881
- return;
13882
- }
13883
- if (status.accounts.length === 0) {
13884
- console.log(pc5.dim("No credentials found. Run: olam auth login"));
13885
- return;
13886
- }
13887
- const accounts = status.accounts.map(toSafeAccount);
13888
- const result = formatAuthStatus(accounts);
13889
- console.log(result.output);
13890
- if (result.exitCode !== 0) {
13891
- process.exitCode = result.exitCode;
13892
- }
13893
- }
13894
13618
 
13895
13619
  // src/commands/auth-upgrade.ts
13896
13620
  init_output();
13897
13621
  init_host_cp();
13898
13622
  init_auth();
13899
- import * as fs21 from "node:fs";
13900
- import * as path24 from "node:path";
13623
+ import * as fs20 from "node:fs";
13624
+ import * as path23 from "node:path";
13901
13625
  import { spawnSync as spawnSync7 } from "node:child_process";
13902
13626
  import ora2 from "ora";
13903
13627
  import pc7 from "picocolors";
@@ -13908,20 +13632,20 @@ init_exit_codes();
13908
13632
  init_protocol_version();
13909
13633
  init_output();
13910
13634
  import { spawn as spawn2, spawnSync as spawnSync6 } from "node:child_process";
13911
- import { existsSync as existsSync20, readFileSync as readFileSync16 } from "node:fs";
13635
+ import { existsSync as existsSync19, readFileSync as readFileSync15 } from "node:fs";
13912
13636
  import { join as join25 } from "node:path";
13913
13637
  import ora from "ora";
13914
13638
  import pc6 from "picocolors";
13915
13639
  function loadImageDigests(installRootDir = installRoot()) {
13916
13640
  const digestsPath = join25(installRootDir, "dist", "image-digests.json");
13917
- if (!existsSync20(digestsPath)) {
13641
+ if (!existsSync19(digestsPath)) {
13918
13642
  throw new Error(
13919
13643
  `image-digests.json missing at ${digestsPath}. Re-run \`npm install -g @pleri/olam-cli@<version>\` to refresh the tarball.`
13920
13644
  );
13921
13645
  }
13922
13646
  let parsed;
13923
13647
  try {
13924
- parsed = JSON.parse(readFileSync16(digestsPath, "utf8"));
13648
+ parsed = JSON.parse(readFileSync15(digestsPath, "utf8"));
13925
13649
  } catch (err) {
13926
13650
  throw new Error(`image-digests.json is not valid JSON: ${err.message}`);
13927
13651
  }
@@ -14179,9 +13903,9 @@ async function runBootstrap2(opts, deps = {}) {
14179
13903
  printSuccess("Smoke world created");
14180
13904
  }
14181
13905
  printHeader("Stack ready");
14182
- printInfo("host-cp", `running (${digests["host-cp"].slice(0, 19)}\u2026)`);
14183
- printInfo("auth", `running (${digests.auth.slice(0, 19)}\u2026)`);
14184
- printInfo("devbox", `pulled (${digests.devbox.slice(0, 19)}\u2026)`);
13906
+ printInfo("olam-host-cp", `running (${digests["host-cp"].slice(0, 19)}\u2026)`);
13907
+ printInfo("olam-auth", `running (${digests.auth.slice(0, 19)}\u2026)`);
13908
+ printInfo("olam-devbox", `pulled (${digests.devbox.slice(0, 19)}\u2026)`);
14185
13909
  printInfo("next", '`olam create --task "your task"` to spawn a world');
14186
13910
  return { exitCode: 0, summary: "stack ready" };
14187
13911
  }
@@ -14221,8 +13945,8 @@ function parseAuthUpgradeOpts(raw) {
14221
13945
  };
14222
13946
  }
14223
13947
  function validateAuthRepoRoot(cwd) {
14224
- const marker = path24.join(cwd, "packages/auth-service/Dockerfile");
14225
- if (!fs21.existsSync(marker)) {
13948
+ const marker = path23.join(cwd, "packages/auth-service/Dockerfile");
13949
+ if (!fs20.existsSync(marker)) {
14226
13950
  return {
14227
13951
  ok: false,
14228
13952
  error: `Not an olam repo root (expected ${marker}).
@@ -14589,6 +14313,185 @@ function registerAuthUpgrade(auth) {
14589
14313
  });
14590
14314
  }
14591
14315
 
14316
+ // src/commands/services.ts
14317
+ init_auth();
14318
+ init_output();
14319
+ import { execFileSync as execFileSync4, spawnSync as spawnSync8 } from "node:child_process";
14320
+ import pc8 from "picocolors";
14321
+ var MCP_AUTH_PORT = 9998;
14322
+ var MCP_AUTH_VOLUME = "olam-mcp-auth-data";
14323
+ var MCP_AUTH_CONTAINER = "olam-mcp-auth";
14324
+ var MCP_AUTH_LOCAL_TAG = "olam-mcp-auth:local";
14325
+ var MCP_AUTH_PUBLISHED_TAG = "ghcr.io/pleri/olam-mcp-auth:latest";
14326
+ var MCP_AUTH_HEALTH_URL = `http://127.0.0.1:${MCP_AUTH_PORT}/health`;
14327
+ var MCP_AUTH_HEALTH_TIMEOUT_MS = 15e3;
14328
+ var McpAuthContainerController = class {
14329
+ imageTag = MCP_AUTH_LOCAL_TAG;
14330
+ status() {
14331
+ const r = spawnSync8(
14332
+ "docker",
14333
+ ["inspect", "--format", "{{.State.Status}}|{{.Id}}", MCP_AUTH_CONTAINER],
14334
+ { encoding: "utf-8" }
14335
+ );
14336
+ if (r.status === 0) {
14337
+ const [stateRaw, id] = r.stdout.trim().split("|");
14338
+ return {
14339
+ state: stateRaw === "running" ? "running" : "stopped",
14340
+ port: MCP_AUTH_PORT,
14341
+ containerId: id
14342
+ };
14343
+ }
14344
+ return { state: "missing", port: MCP_AUTH_PORT };
14345
+ }
14346
+ imageExists(tag = this.imageTag) {
14347
+ return spawnSync8("docker", ["image", "inspect", tag], { encoding: "utf-8" }).status === 0;
14348
+ }
14349
+ start() {
14350
+ const current = this.status();
14351
+ if (current.state === "running") return;
14352
+ if (current.state === "stopped") {
14353
+ execFileSync4("docker", ["start", MCP_AUTH_CONTAINER], { stdio: "pipe" });
14354
+ return;
14355
+ }
14356
+ if (!this.imageExists()) {
14357
+ if (this.imageTag !== MCP_AUTH_PUBLISHED_TAG && this.imageExists(MCP_AUTH_PUBLISHED_TAG)) {
14358
+ this.imageTag = MCP_AUTH_PUBLISHED_TAG;
14359
+ } else {
14360
+ throw new Error(
14361
+ `mcp-auth image '${this.imageTag}' not found locally. Run \`olam bootstrap\` to pull the published image.`
14362
+ );
14363
+ }
14364
+ }
14365
+ execFileSync4(
14366
+ "docker",
14367
+ [
14368
+ "run",
14369
+ "--detach",
14370
+ "--name",
14371
+ MCP_AUTH_CONTAINER,
14372
+ "--restart",
14373
+ "unless-stopped",
14374
+ "--publish",
14375
+ `${MCP_AUTH_PORT}:${MCP_AUTH_PORT}`,
14376
+ "--volume",
14377
+ `${MCP_AUTH_VOLUME}:/mcp-auth-data`,
14378
+ this.imageTag
14379
+ ],
14380
+ { stdio: "pipe" }
14381
+ );
14382
+ }
14383
+ stop() {
14384
+ const current = this.status();
14385
+ if (current.state !== "running") return;
14386
+ execFileSync4("docker", ["stop", MCP_AUTH_CONTAINER], { stdio: "pipe" });
14387
+ }
14388
+ remove() {
14389
+ spawnSync8("docker", ["rm", "-f", MCP_AUTH_CONTAINER], { stdio: "pipe" });
14390
+ }
14391
+ async waitForReady(timeoutMs = MCP_AUTH_HEALTH_TIMEOUT_MS) {
14392
+ const deadline = Date.now() + timeoutMs;
14393
+ while (Date.now() < deadline) {
14394
+ try {
14395
+ const res = await fetch(MCP_AUTH_HEALTH_URL, { signal: AbortSignal.timeout(1500) });
14396
+ if (res.ok) return true;
14397
+ } catch {
14398
+ }
14399
+ await sleep3(500);
14400
+ }
14401
+ return false;
14402
+ }
14403
+ };
14404
+ function sleep3(ms) {
14405
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
14406
+ }
14407
+ async function servicesUp() {
14408
+ const auth = new AuthContainerController();
14409
+ const mcpAuth = new McpAuthContainerController();
14410
+ const authStatus = auth.status();
14411
+ if (authStatus.state === "running") {
14412
+ printSuccess(`olam-auth already running on :${authStatus.port}`);
14413
+ } else {
14414
+ try {
14415
+ auth.start();
14416
+ } catch (err) {
14417
+ printError(`olam-auth failed to start: ${err instanceof Error ? err.message : String(err)}`);
14418
+ return { exitCode: 1 };
14419
+ }
14420
+ const ready = await auth.waitForReady(15e3);
14421
+ if (!ready) {
14422
+ printWarning("olam-auth started but /health did not respond within 15s.");
14423
+ return { exitCode: 1 };
14424
+ }
14425
+ printSuccess("olam-auth started");
14426
+ }
14427
+ const mcpStatus = mcpAuth.status();
14428
+ if (mcpStatus.state === "running") {
14429
+ printSuccess(`olam-mcp-auth already running on :${mcpStatus.port}`);
14430
+ } else {
14431
+ try {
14432
+ mcpAuth.start();
14433
+ } catch (err) {
14434
+ printError(`olam-mcp-auth failed to start: ${err instanceof Error ? err.message : String(err)}`);
14435
+ return { exitCode: 1 };
14436
+ }
14437
+ const ready = await mcpAuth.waitForReady();
14438
+ if (!ready) {
14439
+ printWarning("olam-mcp-auth started but /health did not respond within 15s.");
14440
+ return { exitCode: 1 };
14441
+ }
14442
+ printSuccess("olam-mcp-auth started");
14443
+ }
14444
+ printHeader("Services up");
14445
+ printInfo("olam-auth", ":9999");
14446
+ printInfo("olam-mcp-auth", ":9998");
14447
+ return { exitCode: 0 };
14448
+ }
14449
+ function servicesDown() {
14450
+ const auth = new AuthContainerController();
14451
+ const mcpAuth = new McpAuthContainerController();
14452
+ let exitCode = 0;
14453
+ try {
14454
+ auth.stop();
14455
+ printSuccess("olam-auth stopped.");
14456
+ } catch (err) {
14457
+ printError(`olam-auth: ${err instanceof Error ? err.message : String(err)}`);
14458
+ exitCode = 1;
14459
+ }
14460
+ try {
14461
+ mcpAuth.stop();
14462
+ printSuccess("olam-mcp-auth stopped.");
14463
+ } catch (err) {
14464
+ printError(`olam-mcp-auth: ${err instanceof Error ? err.message : String(err)}`);
14465
+ exitCode = 1;
14466
+ }
14467
+ return { exitCode };
14468
+ }
14469
+ function servicesStatus() {
14470
+ const auth = new AuthContainerController();
14471
+ const mcpAuth = new McpAuthContainerController();
14472
+ printHeader("Services status");
14473
+ const authState = auth.status();
14474
+ const authStateStr = authState.state === "running" ? pc8.green("running") : authState.state === "stopped" ? pc8.yellow("stopped") : pc8.red("missing");
14475
+ printInfo("olam-auth", `${authStateStr} :${authState.port}`);
14476
+ const mcpState = mcpAuth.status();
14477
+ const mcpStateStr = mcpState.state === "running" ? pc8.green("running") : mcpState.state === "stopped" ? pc8.yellow("stopped") : pc8.red("missing");
14478
+ printInfo("olam-mcp-auth", `${mcpStateStr} :${mcpState.port}`);
14479
+ }
14480
+ function registerServices(program2) {
14481
+ const services = program2.command("services").description("Manage Olam service containers (olam-auth, olam-mcp-auth)");
14482
+ services.command("up").description("Start all service containers (idempotent)").action(async () => {
14483
+ const result = await servicesUp();
14484
+ if (result.exitCode !== 0) process.exitCode = result.exitCode;
14485
+ });
14486
+ services.command("down").description("Stop all service containers").action(() => {
14487
+ const result = servicesDown();
14488
+ if (result.exitCode !== 0) process.exitCode = result.exitCode;
14489
+ });
14490
+ services.command("status").description("Show state of all service containers").action(() => {
14491
+ servicesStatus();
14492
+ });
14493
+ }
14494
+
14592
14495
  // src/commands/auth.ts
14593
14496
  function openBrowser(url) {
14594
14497
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
@@ -14609,44 +14512,19 @@ async function promptLine(question) {
14609
14512
  }
14610
14513
  function registerAuth(program2) {
14611
14514
  const auth = program2.command("auth").description("Manage the local Claude auth container");
14612
- auth.command("up").description("Start the auth container (idempotent)").action(async () => {
14613
- const controller = new AuthContainerController();
14614
- const initial = controller.status();
14615
- if (initial.state === "running") {
14616
- printSuccess(`Auth container already running on :${initial.port}`);
14617
- return;
14618
- }
14619
- try {
14620
- controller.start();
14621
- } catch (err) {
14622
- printError(err instanceof Error ? err.message : "failed to start");
14623
- process.exitCode = 1;
14624
- return;
14625
- }
14626
- const ready = await controller.waitForReady(15e3);
14627
- if (!ready) {
14628
- printWarning("Container started but /health did not respond within 15s.");
14629
- process.exitCode = 1;
14630
- return;
14631
- }
14632
- printHeader("Auth container up");
14633
- printInfo("Port", String(initial.port));
14634
- printInfo("Volume", "olam-auth-data");
14635
- console.log(`
14636
- ${pc8.dim("Next: olam auth login")}`);
14515
+ auth.command("up").description("[deprecated] Start the auth container \u2014 use `olam services up` instead").action(async () => {
14516
+ printWarning("`olam auth up` is deprecated. Use `olam services up` instead.");
14517
+ const result = await servicesUp();
14518
+ if (result.exitCode !== 0) process.exitCode = result.exitCode;
14637
14519
  });
14638
- auth.command("down").description("Stop the auth container (tokens persist in the volume)").action(() => {
14639
- const controller = new AuthContainerController();
14640
- try {
14641
- controller.stop();
14642
- printSuccess("Auth container stopped.");
14643
- } catch (err) {
14644
- printError(err instanceof Error ? err.message : "failed to stop");
14645
- process.exitCode = 1;
14646
- }
14520
+ auth.command("down").description("[deprecated] Stop the auth container \u2014 use `olam services down` instead").action(() => {
14521
+ printWarning("`olam auth down` is deprecated. Use `olam services down` instead.");
14522
+ const result = servicesDown();
14523
+ if (result.exitCode !== 0) process.exitCode = result.exitCode;
14647
14524
  });
14648
- auth.command("status").description("Show credential states from auth-service (same source as `auth list`)").action(async () => {
14649
- await runAuthStatus();
14525
+ auth.command("status").description("[deprecated] Show container state \u2014 use `olam services status` instead").action(() => {
14526
+ printWarning("`olam auth status` is deprecated. Use `olam services status` instead.");
14527
+ servicesStatus();
14650
14528
  });
14651
14529
  auth.command("list").description("List all stored credentials with state, usage, and rate-limit status").action(async () => {
14652
14530
  const client = new AuthClient();
@@ -14658,15 +14536,15 @@ ${pc8.dim("Next: olam auth login")}`);
14658
14536
  }
14659
14537
  printHeader(`Credentials (${status.accounts.length})`);
14660
14538
  if (status.accounts.length === 0) {
14661
- console.log(` ${pc8.dim("No credentials \u2014 run: olam auth login --label primary")}`);
14539
+ console.log(` ${pc9.dim("No credentials \u2014 run: olam auth login --label primary")}`);
14662
14540
  return;
14663
14541
  }
14664
14542
  const stateColor = (s) => {
14665
- if (s === "active") return pc8.green("active");
14666
- if (s === "cooldown") return pc8.yellow("cooldown");
14667
- if (s === "expired") return pc8.red("expired");
14668
- if (s === "disabled") return pc8.dim("disabled");
14669
- return pc8.dim(s ?? "unknown");
14543
+ if (s === "active") return pc9.green("active");
14544
+ if (s === "cooldown") return pc9.yellow("cooldown");
14545
+ if (s === "expired") return pc9.red("expired");
14546
+ if (s === "disabled") return pc9.dim("disabled");
14547
+ return pc9.dim(s ?? "unknown");
14670
14548
  };
14671
14549
  for (const a of status.accounts) {
14672
14550
  const label = a.accountLabel ?? a.id;
@@ -14674,7 +14552,7 @@ ${pc8.dim("Next: olam auth login")}`);
14674
14552
  const last429 = a.usage?.last429At ? `last429=${a.usage.last429At}` : "last429=never";
14675
14553
  const reset = a.rateLimitResetsAt ? `resets=${a.rateLimitResetsAt}` : "";
14676
14554
  console.log(
14677
- ` ${pc8.bold(label.padEnd(18))} ${stateColor(a.state).padEnd(18)} ${pc8.dim(`req5h=${reqs}`)} ${pc8.dim(`exp=${a.expiresIn}`)} ${pc8.dim(last429)} ${pc8.yellow(reset)}`
14555
+ ` ${pc9.bold(label.padEnd(18))} ${stateColor(a.state).padEnd(18)} ${pc9.dim(`req5h=${reqs}`)} ${pc9.dim(`exp=${a.expiresIn}`)} ${pc9.dim(last429)} ${pc9.yellow(reset)}`
14678
14556
  );
14679
14557
  }
14680
14558
  });
@@ -14712,7 +14590,7 @@ ${pc8.dim("Next: olam auth login")}`);
14712
14590
  const preflight = await runAuthPreflight({ autoStart: true });
14713
14591
  if (preflight.verdict !== "ok" && preflight.verdict !== "no-accounts") {
14714
14592
  printError(preflight.message);
14715
- console.log(` ${pc8.dim(preflight.remedy)}`);
14593
+ console.log(` ${pc9.dim(preflight.remedy)}`);
14716
14594
  process.exitCode = 1;
14717
14595
  return;
14718
14596
  }
@@ -14745,14 +14623,14 @@ ${pc8.dim("Next: olam auth login")}`);
14745
14623
  }
14746
14624
  printHeader("Claude OAuth \u2014 PKCE flow");
14747
14625
  console.log(`
14748
- ${pc8.bold("1.")} Opening Claude in your default browser\u2026`);
14749
- console.log(` ${pc8.dim(pending.loginUrl)}`);
14626
+ ${pc9.bold("1.")} Opening Claude in your default browser\u2026`);
14627
+ console.log(` ${pc9.dim(pending.loginUrl)}`);
14750
14628
  openBrowser(pending.loginUrl);
14751
14629
  console.log(`
14752
- ${pc8.bold("2.")} After approving, paste the authorization code from the redirect page.`);
14753
- console.log(` ${pc8.dim("(Format: <code>#<state> or just <code>.)")}
14630
+ ${pc9.bold("2.")} After approving, paste the authorization code from the redirect page.`);
14631
+ console.log(` ${pc9.dim("(Format: <code>#<state> or just <code>.)")}
14754
14632
  `);
14755
- const raw = await promptLine(`${pc8.dim("code:")} `);
14633
+ const raw = await promptLine(`${pc9.dim("code:")} `);
14756
14634
  if (!raw) {
14757
14635
  printError("No code provided.");
14758
14636
  process.exitCode = 1;
@@ -14763,7 +14641,7 @@ ${pc8.dim("Next: olam auth login")}`);
14763
14641
  const result = await client.completeLogin(statePart, codePart);
14764
14642
  printSuccess(`Account stored: ${result.account} (${result.expiresIn})`);
14765
14643
  console.log(`
14766
- ${pc8.dim("Next: olam create --name my-world")}`);
14644
+ ${pc9.dim("Next: olam create --name my-world")}`);
14767
14645
  } catch (err) {
14768
14646
  printError(err instanceof Error ? err.message : "token exchange failed");
14769
14647
  process.exitCode = 1;
@@ -14794,15 +14672,15 @@ ${pc8.dim("Next: olam create --name my-world")}`);
14794
14672
 
14795
14673
  // src/commands/create.ts
14796
14674
  init_manager();
14797
- import { spawnSync as spawnSync8 } from "node:child_process";
14798
- import { existsSync as existsSync23 } from "node:fs";
14799
- import { dirname as dirname15, resolve as resolve7 } from "node:path";
14675
+ import { spawnSync as spawnSync9 } from "node:child_process";
14676
+ import { existsSync as existsSync22 } from "node:fs";
14677
+ import { dirname as dirname14, resolve as resolve7 } from "node:path";
14800
14678
  import ora3 from "ora";
14801
- import pc9 from "picocolors";
14679
+ import pc10 from "picocolors";
14802
14680
 
14803
14681
  // ../core/dist/world/devbox-freshness.js
14804
14682
  import { execSync as execSync6 } from "node:child_process";
14805
- import { existsSync as existsSync22, statSync as statSync5 } from "node:fs";
14683
+ import { existsSync as existsSync21, statSync as statSync5 } from "node:fs";
14806
14684
  import { join as join27 } from "node:path";
14807
14685
  var DEFAULT_DEVBOX_IMAGE = "olam-devbox:latest";
14808
14686
  var DEVBOX_BAKED_SOURCES = [
@@ -14871,9 +14749,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
14871
14749
  "These source files have changed since the image was built; the",
14872
14750
  "changes will NOT take effect in fresh worlds until you rebuild:"
14873
14751
  ];
14874
- for (const { path: path45, mtimeMs } of result.newerSources) {
14752
+ for (const { path: path44, mtimeMs } of result.newerSources) {
14875
14753
  const when = new Date(mtimeMs).toISOString();
14876
- lines.push(` \u2022 ${path45} (modified ${when})`);
14754
+ lines.push(` \u2022 ${path44} (modified ${when})`);
14877
14755
  }
14878
14756
  lines.push("");
14879
14757
  lines.push("Rebuild with:");
@@ -14892,7 +14770,7 @@ function defaultDockerInspect(image) {
14892
14770
  }
14893
14771
  function defaultStatMtime(absPath) {
14894
14772
  try {
14895
- if (!existsSync22(absPath))
14773
+ if (!existsSync21(absPath))
14896
14774
  return null;
14897
14775
  return statSync5(absPath).mtimeMs;
14898
14776
  } catch {
@@ -15032,15 +14910,15 @@ init_host_cp();
15032
14910
  var HOST_CP_URL = "http://127.0.0.1:19000";
15033
14911
  async function readHostCpTokenForCreate() {
15034
14912
  try {
15035
- const { default: fs41 } = await import("node:fs");
14913
+ const { default: fs40 } = await import("node:fs");
15036
14914
  const { default: os24 } = await import("node:os");
15037
- const { default: path45 } = await import("node:path");
15038
- const tp = path45.join(
15039
- process.env.OLAM_HOME ?? path45.join(os24.homedir(), ".olam"),
14915
+ const { default: path44 } = await import("node:path");
14916
+ const tp = path44.join(
14917
+ process.env.OLAM_HOME ?? path44.join(os24.homedir(), ".olam"),
15040
14918
  "host-cp.token"
15041
14919
  );
15042
- if (!fs41.existsSync(tp)) return null;
15043
- return fs41.readFileSync(tp, "utf-8").trim();
14920
+ if (!fs40.existsSync(tp)) return null;
14921
+ return fs40.readFileSync(tp, "utf-8").trim();
15044
14922
  } catch {
15045
14923
  return null;
15046
14924
  }
@@ -15065,7 +14943,7 @@ function registerCreate(program2) {
15065
14943
  if (decision.stderrLine) {
15066
14944
  process.stderr.write(decision.stderrLine + "\n");
15067
14945
  }
15068
- spawnSync8("docker", ["pull", overrideRef], { stdio: "pipe" });
14946
+ spawnSync9("docker", ["pull", overrideRef], { stdio: "pipe" });
15069
14947
  const { inspectImageProtocolVersions: inspectImageProtocolVersions2, checkProtocolOverlap: checkProtocolOverlap2 } = await Promise.resolve().then(() => (init_protocol_version(), protocol_version_exports));
15070
14948
  const inspect = inspectImageProtocolVersions2(overrideRef);
15071
14949
  if (inspect.inspectFailed) {
@@ -15114,9 +14992,9 @@ function registerCreate(program2) {
15114
14992
  const reason = inferred.repos.length === 0 ? "no repo names extracted from prompt" : `inference confidence ${inferred.confidence.toFixed(2)} below ${PICKER_CONFIDENCE_THRESHOLD}`;
15115
14993
  printError(`Picker needed: ${reason}`);
15116
14994
  if (catalogRepos.length > 0) {
15117
- console.log(pc9.dim(` available repos: ${catalogRepos.join(", ")}`));
14995
+ console.log(pc10.dim(` available repos: ${catalogRepos.join(", ")}`));
15118
14996
  }
15119
- console.log(pc9.dim(" rerun with explicit --workspace <name> or --repos <a> <b> <c>"));
14997
+ console.log(pc10.dim(" rerun with explicit --workspace <name> or --repos <a> <b> <c>"));
15120
14998
  process.exitCode = 1;
15121
14999
  return;
15122
15000
  }
@@ -15134,7 +15012,7 @@ function registerCreate(program2) {
15134
15012
  inferenceSpinner.fail(`Multiple workspaces match (${decision.result})`);
15135
15013
  const cands = decision.result === "exact-N" ? decision.candidates.map((w) => w.name) : decision.candidates.map((c) => c.workspace.name);
15136
15014
  printError(`Picker needed: ${cands.join(", ")}`);
15137
- console.log(pc9.dim(" rerun with explicit --workspace <name>"));
15015
+ console.log(pc10.dim(" rerun with explicit --workspace <name>"));
15138
15016
  process.exitCode = 1;
15139
15017
  return;
15140
15018
  } else {
@@ -15182,7 +15060,7 @@ function registerCreate(program2) {
15182
15060
  throw err;
15183
15061
  }
15184
15062
  const spinner2 = ora3("Rebuilding olam-devbox:latest\u2026").start();
15185
- const rebuild = spawnSync8(
15063
+ const rebuild = spawnSync9(
15186
15064
  "bash",
15187
15065
  [buildScript],
15188
15066
  { cwd: repoRoot, stdio: "inherit" }
@@ -15248,10 +15126,10 @@ function registerCreate(program2) {
15248
15126
  }
15249
15127
  if (world.credentialsInjected?.claude) {
15250
15128
  console.log(`
15251
- ${pc9.green("Credentials injected. World is ready for dispatch.")}`);
15129
+ ${pc10.green("Credentials injected. World is ready for dispatch.")}`);
15252
15130
  } else if (world.dashboardUrl) {
15253
15131
  console.log(`
15254
- ${pc9.yellow("Authenticate at")} ${world.dashboardUrl}`);
15132
+ ${pc10.yellow("Authenticate at")} ${world.dashboardUrl}`);
15255
15133
  }
15256
15134
  if (opts.hostCp !== false) {
15257
15135
  const probeResult = await probeHostCp().catch(() => null);
@@ -15263,14 +15141,14 @@ ${pc9.yellow("Authenticate at")} ${world.dashboardUrl}`);
15263
15141
  process.stderr.write(
15264
15142
  [
15265
15143
  "",
15266
- pc9.red("Host CP probe failed."),
15144
+ pc10.red("Host CP probe failed."),
15267
15145
  ` tried: http://127.0.0.1:19000/api/bootstrap \u2192 ${diag.bootstrapStatus}`,
15268
15146
  ` tried: docker container "olam-host-cp" \u2192 ${diag.containerStatus}`,
15269
15147
  "",
15270
- pc9.yellow("World was created but the SPA inbox will not show it until you:"),
15271
- ` ${pc9.cyan("olam host-cp start")} (start the host CP)`,
15272
- ` ${pc9.cyan(`olam host-cp register --world ${world.id}`)} (register manually)`,
15273
- ` OR pass ${pc9.dim("--no-host-cp")} on next create to suppress this check.`,
15148
+ pc10.yellow("World was created but the SPA inbox will not show it until you:"),
15149
+ ` ${pc10.cyan("olam host-cp start")} (start the host CP)`,
15150
+ ` ${pc10.cyan(`olam host-cp register --world ${world.id}`)} (register manually)`,
15151
+ ` OR pass ${pc10.dim("--no-host-cp")} on next create to suppress this check.`,
15274
15152
  ""
15275
15153
  ].join("\n")
15276
15154
  );
@@ -15302,13 +15180,13 @@ ${pc9.yellow("Authenticate at")} ${world.dashboardUrl}`);
15302
15180
  process.stderr.write(
15303
15181
  [
15304
15182
  "",
15305
- pc9.red("Host CP registry POST failed."),
15183
+ pc10.red("Host CP registry POST failed."),
15306
15184
  ` url: ${hostCpUrl}/api/admin/registry`,
15307
15185
  ` status: ${reg.status}`,
15308
15186
  ` error: ${reg.error}`,
15309
15187
  "",
15310
- pc9.yellow("World was created but not registered. Run manually:"),
15311
- ` ${pc9.cyan(`olam host-cp register --world ${world.id}`)}`,
15188
+ pc10.yellow("World was created but not registered. Run manually:"),
15189
+ ` ${pc10.cyan(`olam host-cp register --world ${world.id}`)}`,
15312
15190
  ""
15313
15191
  ].join("\n")
15314
15192
  );
@@ -15363,7 +15241,7 @@ ${pc9.yellow("Authenticate at")} ${world.dashboardUrl}`);
15363
15241
  }
15364
15242
  const worldUrl = `${hostCpUrl}/world/${encodeURIComponent(world.id)}`;
15365
15243
  console.log(`
15366
- ${pc9.cyan("Host CP UI:")} ${worldUrl}`);
15244
+ ${pc10.cyan("Host CP UI:")} ${worldUrl}`);
15367
15245
  if (opts.open !== false && reg.ok) {
15368
15246
  const openResult = openUrl(worldUrl);
15369
15247
  if (openResult.opened) {
@@ -15377,14 +15255,7 @@ ${pc9.cyan("Host CP UI:")} ${worldUrl}`);
15377
15255
  spinner.fail("Failed to create world");
15378
15256
  if (err instanceof AuthPreflightError) {
15379
15257
  printError(err.message);
15380
- if (err.remedy) console.log(` ${pc9.dim(err.remedy)}`);
15381
- } else if (err instanceof RepoSelectionRequiredError) {
15382
- printError(err.message);
15383
- if (err.availableRepos.length > 0) {
15384
- const example = err.availableRepos[0];
15385
- console.log(` ${pc9.dim(`Example: olam create --name <name> --repos ${example} --task "<task>"`)}`);
15386
- console.log(` ${pc9.dim('Or: olam create --name <name> --workspace <workspace> --task "<task>"')}`);
15387
- }
15258
+ if (err.remedy) console.log(` ${pc10.dim(err.remedy)}`);
15388
15259
  } else {
15389
15260
  printError(err instanceof Error ? err.message : String(err));
15390
15261
  }
@@ -15395,10 +15266,10 @@ ${pc9.cyan("Host CP UI:")} ${worldUrl}`);
15395
15266
  function resolveRepoRoot(start) {
15396
15267
  let cur = start;
15397
15268
  while (true) {
15398
- if (existsSync23(resolve7(cur, "packages")) && existsSync23(resolve7(cur, "package.json"))) {
15269
+ if (existsSync22(resolve7(cur, "packages")) && existsSync22(resolve7(cur, "package.json"))) {
15399
15270
  return cur;
15400
15271
  }
15401
- const parent = dirname15(cur);
15272
+ const parent = dirname14(cur);
15402
15273
  if (parent === cur) return start;
15403
15274
  cur = parent;
15404
15275
  }
@@ -15409,12 +15280,12 @@ function defaultNameFromPrompt(prompt) {
15409
15280
  }
15410
15281
  async function readHostCpToken3() {
15411
15282
  try {
15412
- const { default: fs41 } = await import("node:fs");
15283
+ const { default: fs40 } = await import("node:fs");
15413
15284
  const { default: os24 } = await import("node:os");
15414
- const { default: path45 } = await import("node:path");
15415
- const tp = path45.join(os24.homedir(), ".olam", "host-cp.token");
15416
- if (!fs41.existsSync(tp)) return null;
15417
- const raw = fs41.readFileSync(tp, "utf-8").trim();
15285
+ const { default: path44 } = await import("node:path");
15286
+ const tp = path44.join(os24.homedir(), ".olam", "host-cp.token");
15287
+ if (!fs40.existsSync(tp)) return null;
15288
+ const raw = fs40.readFileSync(tp, "utf-8").trim();
15418
15289
  return raw.length > 0 ? raw : null;
15419
15290
  } catch {
15420
15291
  return null;
@@ -15459,7 +15330,7 @@ async function fetchHostCpExactMatches(projects) {
15459
15330
  init_context();
15460
15331
  init_output();
15461
15332
  import ora4 from "ora";
15462
- import pc10 from "picocolors";
15333
+ import pc11 from "picocolors";
15463
15334
 
15464
15335
  // ../core/dist/orchestrator/dispatch.js
15465
15336
  var DEEP_MODE_SUFFIX = "\n\nUltrathink and use sub-agents (the Agent tool) to parallelize independent work. Break complex tasks into focused sub-tasks.";
@@ -15546,7 +15417,7 @@ OLAM_EOF`
15546
15417
  const containerName = `olam-${worldId}-devbox`;
15547
15418
  console.log(
15548
15419
  `
15549
- ${pc10.dim(`Watch live: docker exec -it ${containerName} tmux attach -t claude-main -r`)}`
15420
+ ${pc11.dim(`Watch live: docker exec -it ${containerName} tmux attach -t claude-main -r`)}`
15550
15421
  );
15551
15422
  } catch (err) {
15552
15423
  spinner.fail("Dispatch failed");
@@ -15559,7 +15430,7 @@ ${pc10.dim(`Watch live: docker exec -it ${containerName} tmux attach -t claude-m
15559
15430
  // src/commands/observe.ts
15560
15431
  init_context();
15561
15432
  init_output();
15562
- import pc11 from "picocolors";
15433
+ import pc12 from "picocolors";
15563
15434
  function registerObserve(program2) {
15564
15435
  program2.command("observe").description("Stream thoughts from a world (coming soon)").argument("<world>", "World ID").action(async (worldId) => {
15565
15436
  const { ctx, error } = await loadContext();
@@ -15579,15 +15450,15 @@ function registerObserve(program2) {
15579
15450
  checkVersionPin2(worldId, world.workspacePath);
15580
15451
  }
15581
15452
  console.log(
15582
- pc11.yellow("Observation is coming in a future release.")
15453
+ pc12.yellow("Observation is coming in a future release.")
15583
15454
  );
15584
15455
  console.log(
15585
- pc11.dim("This will stream the world's reasoning in real-time.")
15456
+ pc12.dim("This will stream the world's reasoning in real-time.")
15586
15457
  );
15587
15458
  const containerName = `olam-${worldId}-devbox`;
15588
15459
  console.log(
15589
15460
  `
15590
- ${pc11.dim(`For now: docker exec -it ${containerName} tmux attach -t claude-main -r`)}`
15461
+ ${pc12.dim(`For now: docker exec -it ${containerName} tmux attach -t claude-main -r`)}`
15591
15462
  );
15592
15463
  });
15593
15464
  }
@@ -15595,7 +15466,7 @@ ${pc11.dim(`For now: docker exec -it ${containerName} tmux attach -t claude-main
15595
15466
  // src/commands/list.ts
15596
15467
  init_context();
15597
15468
  init_output();
15598
- import pc12 from "picocolors";
15469
+ import pc13 from "picocolors";
15599
15470
  function registerList(program2) {
15600
15471
  program2.command("list").alias("ls").description("List active worlds").action(async () => {
15601
15472
  const { ctx, error } = await loadContext();
@@ -15606,18 +15477,18 @@ function registerList(program2) {
15606
15477
  }
15607
15478
  const worlds = ctx.worldManager.listWorlds();
15608
15479
  if (worlds.length === 0) {
15609
- console.log(pc12.dim("No worlds. Create one with `olam create --name my-world`."));
15480
+ console.log(pc13.dim("No worlds. Create one with `olam create --name my-world`."));
15610
15481
  return;
15611
15482
  }
15612
- console.log(`${pc12.bold(String(worlds.length))} world(s)
15483
+ console.log(`${pc13.bold(String(worlds.length))} world(s)
15613
15484
  `);
15614
15485
  for (const w of worlds) {
15615
- const statusColor = w.status === "running" ? pc12.green(w.status) : w.status === "error" ? pc12.red(w.status) : pc12.yellow(w.status);
15486
+ const statusColor = w.status === "running" ? pc13.green(w.status) : w.status === "error" ? pc13.red(w.status) : pc13.yellow(w.status);
15616
15487
  const age = formatAge(w.createdAt);
15617
15488
  const cost = `$${w.totalCostUsd.toFixed(2)}`;
15618
- console.log(` ${pc12.bold(w.name)} ${pc12.dim(`(${w.id})`)}`);
15489
+ console.log(` ${pc13.bold(w.name)} ${pc13.dim(`(${w.id})`)}`);
15619
15490
  console.log(
15620
- ` ${statusColor} ${pc12.dim("|")} ${w.repos.join(", ")} ${pc12.dim("|")} ${cost} ${pc12.dim("|")} ${age}`
15491
+ ` ${statusColor} ${pc13.dim("|")} ${w.repos.join(", ")} ${pc13.dim("|")} ${cost} ${pc13.dim("|")} ${age}`
15621
15492
  );
15622
15493
  console.log();
15623
15494
  }
@@ -15626,9 +15497,9 @@ function registerList(program2) {
15626
15497
 
15627
15498
  // src/commands/status.ts
15628
15499
  init_output();
15629
- import * as fs23 from "node:fs";
15500
+ import * as fs22 from "node:fs";
15630
15501
  import * as os13 from "node:os";
15631
- import * as path26 from "node:path";
15502
+ import * as path25 from "node:path";
15632
15503
  var CLI_VERSION2 = process.env["OLAM_CLI_VERSION"] ?? "0.0.0";
15633
15504
  var HOST_CP_PORT2 = 19e3;
15634
15505
  async function getMachineStatus(_probe, _loadCtx, _readToken) {
@@ -15658,14 +15529,14 @@ async function getMachineStatus(_probe, _loadCtx, _readToken) {
15658
15529
  }
15659
15530
  } catch {
15660
15531
  }
15661
- const manifestPath2 = path26.join(os13.homedir(), ".olam", "cache", "manifest.json");
15532
+ const manifestPath2 = path25.join(os13.homedir(), ".olam", "cache", "manifest.json");
15662
15533
  let updateAvailable = null;
15663
15534
  let lastUpdateCheck = null;
15664
- if (fs23.existsSync(manifestPath2)) {
15665
- const mtime = fs23.statSync(manifestPath2).mtime;
15535
+ if (fs22.existsSync(manifestPath2)) {
15536
+ const mtime = fs22.statSync(manifestPath2).mtime;
15666
15537
  lastUpdateCheck = mtime.toISOString();
15667
15538
  try {
15668
- const manifest = JSON.parse(fs23.readFileSync(manifestPath2, "utf-8"));
15539
+ const manifest = JSON.parse(fs22.readFileSync(manifestPath2, "utf-8"));
15669
15540
  const latest = manifest["version"];
15670
15541
  updateAvailable = latest !== void 0 && latest !== CLI_VERSION2;
15671
15542
  } catch {
@@ -15788,10 +15659,10 @@ function registerDestroy(program2) {
15788
15659
  // src/commands/clean.ts
15789
15660
  init_context();
15790
15661
  init_output();
15791
- import fs24 from "node:fs";
15662
+ import fs23 from "node:fs";
15792
15663
  import os14 from "node:os";
15793
- import path27 from "node:path";
15794
- import { execFileSync as execFileSync4 } from "node:child_process";
15664
+ import path26 from "node:path";
15665
+ import { execFileSync as execFileSync5 } from "node:child_process";
15795
15666
  function registerClean(program2) {
15796
15667
  program2.command("clean").description("Reap orphan world filesystem state under ~/.olam/worlds/").option("--apply", "Actually delete the orphans (default is dry-run)", false).option(
15797
15668
  "--include-dirty",
@@ -15814,8 +15685,8 @@ async function runClean(opts) {
15814
15685
  printError(error?.message ?? "Olam is not configured. Run `olam init` first.");
15815
15686
  return 1;
15816
15687
  }
15817
- const worldsDir = path27.join(os14.homedir(), ".olam", "worlds");
15818
- if (!fs24.existsSync(worldsDir)) {
15688
+ const worldsDir = path26.join(os14.homedir(), ".olam", "worlds");
15689
+ if (!fs23.existsSync(worldsDir)) {
15819
15690
  if (opts.json) {
15820
15691
  process.stdout.write(`${JSON.stringify({ worldsDir, entries: [] })}
15821
15692
  `);
@@ -15830,8 +15701,8 @@ async function runClean(opts) {
15830
15701
  }
15831
15702
  const worktreeMap = collectWorktrees(worldsDir);
15832
15703
  const entries = [];
15833
- for (const id of fs24.readdirSync(worldsDir).sort()) {
15834
- const fullPath = path27.join(worldsDir, id);
15704
+ for (const id of fs23.readdirSync(worldsDir).sort()) {
15705
+ const fullPath = path26.join(worldsDir, id);
15835
15706
  const stat = safeStat(fullPath);
15836
15707
  if (!stat || !stat.isDirectory()) continue;
15837
15708
  entries.push(classifyWorld({ id, fullPath, liveIds, worktreeMap }));
@@ -15897,7 +15768,7 @@ function classifyWorld(args) {
15897
15768
  if (liveIds.has(id)) {
15898
15769
  return { id, path: fullPath, bytes, category: "active", note: "in registry" };
15899
15770
  }
15900
- const worktreeChild = path27.join(fullPath, "olam");
15771
+ const worktreeChild = path26.join(fullPath, "olam");
15901
15772
  const worktreeInfo = worktreeMap.get(worktreeChild);
15902
15773
  if (worktreeInfo) {
15903
15774
  if (worktreeInfo.dirty > 0 || worktreeInfo.unpushed > 0) {
@@ -15934,7 +15805,7 @@ function reapEntry(entry) {
15934
15805
  try {
15935
15806
  const gitDir = resolveGitDirForWorktree(entry.worktreePath);
15936
15807
  if (gitDir) {
15937
- execFileSync4("git", ["worktree", "remove", "--force", entry.worktreePath], {
15808
+ execFileSync5("git", ["worktree", "remove", "--force", entry.worktreePath], {
15938
15809
  cwd: gitDir,
15939
15810
  stdio: "pipe"
15940
15811
  });
@@ -15943,20 +15814,20 @@ function reapEntry(entry) {
15943
15814
  }
15944
15815
  }
15945
15816
  try {
15946
- fs24.rmSync(entry.path, { recursive: true, force: true });
15817
+ fs23.rmSync(entry.path, { recursive: true, force: true });
15947
15818
  } catch (err) {
15948
15819
  process.stderr.write(` ! rm ${entry.path}: ${err instanceof Error ? err.message : String(err)}
15949
15820
  `);
15950
15821
  return false;
15951
15822
  }
15952
- return !fs24.existsSync(entry.path);
15823
+ return !fs23.existsSync(entry.path);
15953
15824
  }
15954
15825
  function collectWorktrees(worldsDir) {
15955
15826
  const out = /* @__PURE__ */ new Map();
15956
- for (const id of fs24.readdirSync(worldsDir)) {
15957
- const child = path27.join(worldsDir, id, "olam");
15958
- const gitMarker = path27.join(child, ".git");
15959
- if (!fs24.existsSync(gitMarker)) continue;
15827
+ for (const id of fs23.readdirSync(worldsDir)) {
15828
+ const child = path26.join(worldsDir, id, "olam");
15829
+ const gitMarker = path26.join(child, ".git");
15830
+ if (!fs23.existsSync(gitMarker)) continue;
15960
15831
  const gitDir = resolveGitDirForWorktree(child);
15961
15832
  if (!gitDir) continue;
15962
15833
  const branch = readBranch(child);
@@ -15967,21 +15838,21 @@ function collectWorktrees(worldsDir) {
15967
15838
  return out;
15968
15839
  }
15969
15840
  function resolveGitDirForWorktree(worktreePath) {
15970
- const gitMarker = path27.join(worktreePath, ".git");
15841
+ const gitMarker = path26.join(worktreePath, ".git");
15971
15842
  try {
15972
- const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], {
15843
+ const top = execFileSync5("git", ["rev-parse", "--show-toplevel"], {
15973
15844
  cwd: worktreePath,
15974
15845
  encoding: "utf-8",
15975
15846
  stdio: "pipe"
15976
15847
  }).trim();
15977
15848
  if (!top) return null;
15978
- const common = execFileSync4("git", ["rev-parse", "--git-common-dir"], {
15849
+ const common = execFileSync5("git", ["rev-parse", "--git-common-dir"], {
15979
15850
  cwd: worktreePath,
15980
15851
  encoding: "utf-8",
15981
15852
  stdio: "pipe"
15982
15853
  }).trim();
15983
15854
  if (!common) return top;
15984
- return path27.dirname(path27.resolve(worktreePath, common));
15855
+ return path26.dirname(path26.resolve(worktreePath, common));
15985
15856
  } catch {
15986
15857
  return null;
15987
15858
  }
@@ -15989,7 +15860,7 @@ function resolveGitDirForWorktree(worktreePath) {
15989
15860
  }
15990
15861
  function readBranch(worktreePath) {
15991
15862
  try {
15992
- return execFileSync4("git", ["branch", "--show-current"], {
15863
+ return execFileSync5("git", ["branch", "--show-current"], {
15993
15864
  cwd: worktreePath,
15994
15865
  encoding: "utf-8",
15995
15866
  stdio: "pipe"
@@ -16000,7 +15871,7 @@ function readBranch(worktreePath) {
16000
15871
  }
16001
15872
  function countDirty(worktreePath) {
16002
15873
  try {
16003
- const out = execFileSync4("git", ["status", "--porcelain"], {
15874
+ const out = execFileSync5("git", ["status", "--porcelain"], {
16004
15875
  cwd: worktreePath,
16005
15876
  encoding: "utf-8",
16006
15877
  stdio: "pipe"
@@ -16012,7 +15883,7 @@ function countDirty(worktreePath) {
16012
15883
  }
16013
15884
  function countUnpushed(worktreePath) {
16014
15885
  try {
16015
- const out = execFileSync4("git", ["log", "@{u}..HEAD", "--oneline"], {
15886
+ const out = execFileSync5("git", ["log", "@{u}..HEAD", "--oneline"], {
16016
15887
  cwd: worktreePath,
16017
15888
  encoding: "utf-8",
16018
15889
  stdio: "pipe"
@@ -16024,7 +15895,7 @@ function countUnpushed(worktreePath) {
16024
15895
  }
16025
15896
  function safeStat(p) {
16026
15897
  try {
16027
- return fs24.statSync(p);
15898
+ return fs23.statSync(p);
16028
15899
  } catch {
16029
15900
  return null;
16030
15901
  }
@@ -16036,7 +15907,7 @@ function computeBytes(p) {
16036
15907
  const cur = stack.pop();
16037
15908
  let st;
16038
15909
  try {
16039
- st = fs24.lstatSync(cur);
15910
+ st = fs23.lstatSync(cur);
16040
15911
  } catch {
16041
15912
  continue;
16042
15913
  }
@@ -16044,11 +15915,11 @@ function computeBytes(p) {
16044
15915
  if (st.isDirectory()) {
16045
15916
  let entries;
16046
15917
  try {
16047
- entries = fs24.readdirSync(cur);
15918
+ entries = fs23.readdirSync(cur);
16048
15919
  } catch {
16049
15920
  continue;
16050
15921
  }
16051
- for (const name of entries) stack.push(path27.join(cur, name));
15922
+ for (const name of entries) stack.push(path26.join(cur, name));
16052
15923
  } else {
16053
15924
  total += st.size;
16054
15925
  }
@@ -16101,7 +15972,7 @@ async function confirmInteractive() {
16101
15972
  init_context();
16102
15973
  init_output();
16103
15974
  import { execSync as execSync7 } from "node:child_process";
16104
- import pc13 from "picocolors";
15975
+ import pc14 from "picocolors";
16105
15976
  var SAFE_IDENT3 = /^[a-z0-9][a-z0-9-]{0,63}$/;
16106
15977
  function buildStartClaudeCommands(containerName, sessionName, task) {
16107
15978
  if (!SAFE_IDENT3.test(containerName)) {
@@ -16208,7 +16079,7 @@ function registerEnter(program2) {
16208
16079
  }
16209
16080
  console.log("Run these commands in order to enter the world:\n");
16210
16081
  for (const step of steps) {
16211
- console.log(` ${pc13.dim(`# ${step.description}`)}`);
16082
+ console.log(` ${pc14.dim(`# ${step.description}`)}`);
16212
16083
  if (step.stdin !== void 0) {
16213
16084
  const escaped = step.stdin.replace(/'/g, "'\\''");
16214
16085
  console.log(` printf '%s' '${escaped}' | ${step.command}`);
@@ -16242,11 +16113,11 @@ function registerEnter(program2) {
16242
16113
  return;
16243
16114
  }
16244
16115
  console.log("Run this command to enter the world:\n");
16245
- console.log(` ${pc13.bold(result.command)}`);
16116
+ console.log(` ${pc14.bold(result.command)}`);
16246
16117
  const containerName = `olam-${worldId}-devbox`;
16247
16118
  console.log(
16248
16119
  `
16249
- ${pc13.dim(`Observe dispatch: docker exec -it ${containerName} tmux attach -t olam-dispatch -r`)}`
16120
+ ${pc14.dim(`Observe dispatch: docker exec -it ${containerName} tmux attach -t olam-dispatch -r`)}`
16250
16121
  );
16251
16122
  });
16252
16123
  }
@@ -16256,7 +16127,7 @@ init_context();
16256
16127
  init_output();
16257
16128
  init_exit_codes();
16258
16129
  init_world_paths();
16259
- import * as fs25 from "node:fs";
16130
+ import * as fs24 from "node:fs";
16260
16131
  import "node:path";
16261
16132
  import ora6 from "ora";
16262
16133
  function registerCrystallize(program2, options = {}) {
@@ -16288,7 +16159,7 @@ function registerCrystallize(program2, options = {}) {
16288
16159
  return;
16289
16160
  }
16290
16161
  const thoughtDbPath = getWorldDbPath(world.workspacePath);
16291
- if (!fs25.existsSync(thoughtDbPath)) {
16162
+ if (!fs24.existsSync(thoughtDbPath)) {
16292
16163
  printError(`No thoughts captured yet for "${worldId}". Run a dispatch first.`);
16293
16164
  process.exitCode = EXIT_GENERIC_ERROR;
16294
16165
  return;
@@ -16358,7 +16229,7 @@ function registerCrystallize(program2, options = {}) {
16358
16229
 
16359
16230
  // src/commands/pr.ts
16360
16231
  init_registry();
16361
- import pc14 from "picocolors";
16232
+ import pc15 from "picocolors";
16362
16233
 
16363
16234
  // ../core/dist/pr-gate/client.js
16364
16235
  var HOST_CONTROL_PLANE_BASE2 = 19080;
@@ -16439,26 +16310,26 @@ async function findGate(id) {
16439
16310
  return null;
16440
16311
  }
16441
16312
  function formatStateBadge(state) {
16442
- if (state === "approve") return pc14.green("approve");
16443
- if (state === "block") return pc14.red("block");
16444
- if (state === "denied") return pc14.gray("denied");
16445
- return pc14.yellow("pending");
16313
+ if (state === "approve") return pc15.green("approve");
16314
+ if (state === "block") return pc15.red("block");
16315
+ if (state === "denied") return pc15.gray("denied");
16316
+ return pc15.yellow("pending");
16446
16317
  }
16447
16318
  function registerPr(program2) {
16448
16319
  const pr = program2.command("pr").description("Review and decide PR-gate requests from running worlds");
16449
16320
  pr.command("list").description("List all PR-gate requests across every running world").action(async () => {
16450
16321
  const all = await fanoutList();
16451
16322
  if (all.length === 0) {
16452
- console.log(pc14.dim("No gates open."));
16323
+ console.log(pc15.dim("No gates open."));
16453
16324
  return;
16454
16325
  }
16455
16326
  printHeader(`${all.length} gate(s)`);
16456
16327
  for (const { world, gate } of all) {
16457
16328
  const badge = formatStateBadge(gate.state);
16458
16329
  console.log(
16459
- ` ${pc14.bold(gate.id.slice(0, 8))} ${badge.padEnd(20)} ${pc14.dim(world.name)} ${pc14.dim(gate.branch)}`
16330
+ ` ${pc15.bold(gate.id.slice(0, 8))} ${badge.padEnd(20)} ${pc15.dim(world.name)} ${pc15.dim(gate.branch)}`
16460
16331
  );
16461
- console.log(` ${pc14.dim(gate.command.slice(0, 100))}`);
16332
+ console.log(` ${pc15.dim(gate.command.slice(0, 100))}`);
16462
16333
  }
16463
16334
  });
16464
16335
  pr.command("show").description("Show full gate detail (diff, command, commits)").argument("<id>", "Gate id (prefix match ok)").action(async (id) => {
@@ -16481,9 +16352,9 @@ function registerPr(program2) {
16481
16352
  if (gate.reason) printInfo("Reason", gate.reason);
16482
16353
  }
16483
16354
  printHeader("Commits");
16484
- console.log(gate.commitLog || pc14.dim(" (empty)"));
16355
+ console.log(gate.commitLog || pc15.dim(" (empty)"));
16485
16356
  printHeader("Diff stat");
16486
- console.log(gate.diffStat || pc14.dim(" (empty)"));
16357
+ console.log(gate.diffStat || pc15.dim(" (empty)"));
16487
16358
  });
16488
16359
  function decideCommand(verb, decision) {
16489
16360
  pr.command(verb).description(`${verb[0].toUpperCase()}${verb.slice(1)} a pending gate`).argument("<id>", "Gate id").option("--reason <reason>", "Short free-text reason").option("--by <name>", "Deciding identity (defaults to $USER)", process.env["USER"] ?? "human").action(async (id, opts) => {
@@ -16608,7 +16479,7 @@ function registerLanes(program2) {
16608
16479
  // src/commands/policy-check.ts
16609
16480
  init_loader2();
16610
16481
  import { execSync as execSync8 } from "node:child_process";
16611
- import pc15 from "picocolors";
16482
+ import pc16 from "picocolors";
16612
16483
 
16613
16484
  // ../../node_modules/balanced-match/dist/esm/index.js
16614
16485
  var balanced = (a, b, str) => {
@@ -17662,11 +17533,11 @@ var qmarksTestNoExtDot = ([$0]) => {
17662
17533
  return (f) => f.length === len && f !== "." && f !== "..";
17663
17534
  };
17664
17535
  var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
17665
- var path29 = {
17536
+ var path28 = {
17666
17537
  win32: { sep: "\\" },
17667
17538
  posix: { sep: "/" }
17668
17539
  };
17669
- var sep = defaultPlatform === "win32" ? path29.win32.sep : path29.posix.sep;
17540
+ var sep = defaultPlatform === "win32" ? path28.win32.sep : path28.posix.sep;
17670
17541
  minimatch.sep = sep;
17671
17542
  var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
17672
17543
  minimatch.GLOBSTAR = GLOBSTAR;
@@ -18468,7 +18339,7 @@ function registerPolicyCheck(program2) {
18468
18339
  const workspaceRoot = opts.workspace ?? process.cwd();
18469
18340
  const policies = loadPolicies(workspaceRoot);
18470
18341
  if (policies.length === 0) {
18471
- console.log(pc15.dim("policy-check: no policies found in .olam/policies/ \u2014 nothing to enforce"));
18342
+ console.log(pc16.dim("policy-check: no policies found in .olam/policies/ \u2014 nothing to enforce"));
18472
18343
  return;
18473
18344
  }
18474
18345
  const diff = getDiff(opts.base, workspaceRoot);
@@ -18477,11 +18348,11 @@ function registerPolicyCheck(program2) {
18477
18348
  for (const result of results) {
18478
18349
  if (result.passed) continue;
18479
18350
  if (result.severity === "error") {
18480
- console.error(`${pc15.red("policy error")} [${result.policyId}]`);
18351
+ console.error(`${pc16.red("policy error")} [${result.policyId}]`);
18481
18352
  console.error(result.message);
18482
18353
  hasErrorFailure = true;
18483
18354
  } else {
18484
- console.warn(`${pc15.yellow("policy warn")} [${result.policyId}]`);
18355
+ console.warn(`${pc16.yellow("policy warn")} [${result.policyId}]`);
18485
18356
  console.warn(result.message);
18486
18357
  }
18487
18358
  }
@@ -18494,23 +18365,23 @@ function registerPolicyCheck(program2) {
18494
18365
  // src/commands/upgrade.ts
18495
18366
  init_output();
18496
18367
  init_host_cp();
18497
- import * as fs28 from "node:fs";
18498
- import * as path32 from "node:path";
18499
- import { spawnSync as spawnSync10 } from "node:child_process";
18368
+ import * as fs27 from "node:fs";
18369
+ import * as path31 from "node:path";
18370
+ import { spawnSync as spawnSync11 } from "node:child_process";
18500
18371
  import ora7 from "ora";
18501
- import pc16 from "picocolors";
18372
+ import pc17 from "picocolors";
18502
18373
 
18503
18374
  // src/commands/upgrade-lock.ts
18504
- import * as fs26 from "node:fs";
18375
+ import * as fs25 from "node:fs";
18505
18376
  import * as os15 from "node:os";
18506
- import * as path30 from "node:path";
18507
- import { spawnSync as spawnSync9 } from "node:child_process";
18508
- var LOCK_FILE_PATH = path30.join(os15.homedir(), ".olam", ".upgrade.lock");
18377
+ import * as path29 from "node:path";
18378
+ import { spawnSync as spawnSync10 } from "node:child_process";
18379
+ var LOCK_FILE_PATH = path29.join(os15.homedir(), ".olam", ".upgrade.lock");
18509
18380
  var STALE_LOCK_TIMEOUT_MS = 5 * 60 * 1e3;
18510
18381
  function readLockFile(lockPath) {
18511
18382
  try {
18512
- if (!fs26.existsSync(lockPath)) return null;
18513
- const raw = fs26.readFileSync(lockPath, "utf-8").trim();
18383
+ if (!fs25.existsSync(lockPath)) return null;
18384
+ const raw = fs25.readFileSync(lockPath, "utf-8").trim();
18514
18385
  if (raw.length === 0) return null;
18515
18386
  const parsed = JSON.parse(raw);
18516
18387
  if (typeof parsed.pid !== "number" || typeof parsed.startTs !== "number") return null;
@@ -18529,7 +18400,7 @@ function isPidAlive(pid) {
18529
18400
  }
18530
18401
  var PS_UNAVAILABLE = "__ps_unavailable__";
18531
18402
  function getPidCommand(pid) {
18532
- const result = spawnSync9("ps", ["-p", String(pid), "-o", "comm="], {
18403
+ const result = spawnSync10("ps", ["-p", String(pid), "-o", "comm="], {
18533
18404
  encoding: "utf-8",
18534
18405
  stdio: ["ignore", "pipe", "ignore"]
18535
18406
  });
@@ -18555,16 +18426,16 @@ function isStaleLock(content, nowMs = Date.now()) {
18555
18426
  return false;
18556
18427
  }
18557
18428
  function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
18558
- const dir = path30.dirname(lockPath);
18559
- fs26.mkdirSync(dir, { recursive: true });
18429
+ const dir = path29.dirname(lockPath);
18430
+ fs25.mkdirSync(dir, { recursive: true });
18560
18431
  for (let attempt = 0; attempt < 2; attempt++) {
18561
18432
  try {
18562
- const fd = fs26.openSync(lockPath, "wx", 420);
18433
+ const fd = fs25.openSync(lockPath, "wx", 420);
18563
18434
  try {
18564
18435
  const content = { pid: process.pid, startTs: nowMs };
18565
- fs26.writeSync(fd, JSON.stringify(content));
18436
+ fs25.writeSync(fd, JSON.stringify(content));
18566
18437
  } finally {
18567
- fs26.closeSync(fd);
18438
+ fs25.closeSync(fd);
18568
18439
  }
18569
18440
  return { acquired: true, lockPath };
18570
18441
  } catch (err) {
@@ -18573,7 +18444,7 @@ function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
18573
18444
  const existing2 = readLockFile(lockPath);
18574
18445
  if (isStaleLock(existing2, nowMs)) {
18575
18446
  try {
18576
- fs26.unlinkSync(lockPath);
18447
+ fs25.unlinkSync(lockPath);
18577
18448
  } catch (unlinkErr) {
18578
18449
  const ucode = unlinkErr.code;
18579
18450
  if (ucode !== "ENOENT") throw unlinkErr;
@@ -18598,7 +18469,7 @@ function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
18598
18469
  }
18599
18470
  function releaseLock(lockPath = LOCK_FILE_PATH) {
18600
18471
  try {
18601
- fs26.unlinkSync(lockPath);
18472
+ fs25.unlinkSync(lockPath);
18602
18473
  } catch (err) {
18603
18474
  const code = err.code;
18604
18475
  if (code !== "ENOENT") throw err;
@@ -18616,19 +18487,19 @@ function formatRefusalMessage(result, lockPath = LOCK_FILE_PATH) {
18616
18487
  }
18617
18488
 
18618
18489
  // src/commands/upgrade-log.ts
18619
- import * as fs27 from "node:fs";
18490
+ import * as fs26 from "node:fs";
18620
18491
  import * as os16 from "node:os";
18621
- import * as path31 from "node:path";
18492
+ import * as path30 from "node:path";
18622
18493
  function getUpgradeLogPath() {
18623
18494
  const home = process.env["HOME"] ?? os16.homedir();
18624
- return path31.join(home, ".olam", "upgrade.log");
18495
+ return path30.join(home, ".olam", "upgrade.log");
18625
18496
  }
18626
18497
  var UPGRADE_LOG_PATH = getUpgradeLogPath();
18627
18498
  function appendUpgradeLog(row, logPath = getUpgradeLogPath()) {
18628
18499
  try {
18629
- fs27.mkdirSync(path31.dirname(logPath), { recursive: true });
18500
+ fs26.mkdirSync(path30.dirname(logPath), { recursive: true });
18630
18501
  const line = JSON.stringify(row) + "\n";
18631
- fs27.appendFileSync(logPath, line, { mode: 420 });
18502
+ fs26.appendFileSync(logPath, line, { mode: 420 });
18632
18503
  } catch (err) {
18633
18504
  process.stderr.write(
18634
18505
  `[upgrade-log] failed to append: ${err instanceof Error ? err.message : String(err)}
@@ -18637,10 +18508,10 @@ function appendUpgradeLog(row, logPath = getUpgradeLogPath()) {
18637
18508
  }
18638
18509
  }
18639
18510
  function readUpgradeLog(limit = 10, logPath = getUpgradeLogPath()) {
18640
- if (!fs27.existsSync(logPath)) return [];
18511
+ if (!fs26.existsSync(logPath)) return [];
18641
18512
  let raw;
18642
18513
  try {
18643
- raw = fs27.readFileSync(logPath, "utf-8");
18514
+ raw = fs26.readFileSync(logPath, "utf-8");
18644
18515
  } catch (err) {
18645
18516
  process.stderr.write(
18646
18517
  `[upgrade-log] failed to read: ${err instanceof Error ? err.message : String(err)}
@@ -18733,12 +18604,12 @@ init_protocol_version();
18733
18604
  init_install_root();
18734
18605
  var AUTH_HEALTH_URL2 = "http://127.0.0.1:9999/health";
18735
18606
  function isNodeModulesInSync(cwd) {
18736
- const lockPath = path32.join(cwd, "package-lock.json");
18737
- const markerPath = path32.join(cwd, "node_modules", ".package-lock.json");
18738
- if (!fs28.existsSync(lockPath) || !fs28.existsSync(markerPath)) return false;
18607
+ const lockPath = path31.join(cwd, "package-lock.json");
18608
+ const markerPath = path31.join(cwd, "node_modules", ".package-lock.json");
18609
+ if (!fs27.existsSync(lockPath) || !fs27.existsSync(markerPath)) return false;
18739
18610
  try {
18740
- const lockStat = fs28.statSync(lockPath);
18741
- const markerStat = fs28.statSync(markerPath);
18611
+ const lockStat = fs27.statSync(lockPath);
18612
+ const markerStat = fs27.statSync(markerPath);
18742
18613
  return markerStat.mtimeMs >= lockStat.mtimeMs;
18743
18614
  } catch {
18744
18615
  return false;
@@ -18754,8 +18625,8 @@ function shouldSkipInstall(opts, cwd) {
18754
18625
  return { skip: false };
18755
18626
  }
18756
18627
  function validateRepoRoot(cwd) {
18757
- const marker = path32.join(cwd, "packages/host-cp/compose.yaml");
18758
- if (!fs28.existsSync(marker)) {
18628
+ const marker = path31.join(cwd, "packages/host-cp/compose.yaml");
18629
+ if (!fs27.existsSync(marker)) {
18759
18630
  return {
18760
18631
  ok: false,
18761
18632
  error: `Not an olam repo root (expected ${marker}).
@@ -18787,8 +18658,8 @@ function extractBundleHash(indexHtml) {
18787
18658
  }
18788
18659
  function runStep2(label, cmd, args, opts = {}) {
18789
18660
  const start = Date.now();
18790
- process.stdout.write(` ${pc16.dim(label.padEnd(34))}`);
18791
- const result = spawnSync10(cmd, [...args], {
18661
+ process.stdout.write(` ${pc17.dim(label.padEnd(34))}`);
18662
+ const result = spawnSync11(cmd, [...args], {
18792
18663
  encoding: "utf-8",
18793
18664
  stdio: ["ignore", "pipe", "pipe"],
18794
18665
  cwd: opts.cwd ?? process.cwd(),
@@ -18797,7 +18668,7 @@ function runStep2(label, cmd, args, opts = {}) {
18797
18668
  const durationMs = Date.now() - start;
18798
18669
  const ok = result.status === 0 && result.error === void 0;
18799
18670
  const dur = `${(durationMs / 1e3).toFixed(1)}s`;
18800
- process.stdout.write(`${ok ? pc16.green("\u2713") : pc16.red("\u2717")} ${dur}
18671
+ process.stdout.write(`${ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${dur}
18801
18672
  `);
18802
18673
  return {
18803
18674
  ok,
@@ -18807,7 +18678,7 @@ function runStep2(label, cmd, args, opts = {}) {
18807
18678
  };
18808
18679
  }
18809
18680
  function isGitDirty(cwd) {
18810
- const result = spawnSync10("git", ["status", "--porcelain"], {
18681
+ const result = spawnSync11("git", ["status", "--porcelain"], {
18811
18682
  encoding: "utf-8",
18812
18683
  stdio: ["ignore", "pipe", "pipe"],
18813
18684
  cwd
@@ -18815,7 +18686,7 @@ function isGitDirty(cwd) {
18815
18686
  return (result.stdout ?? "").trim().length > 0;
18816
18687
  }
18817
18688
  function hasGitUpstream(cwd) {
18818
- const result = spawnSync10("git", ["rev-parse", "--abbrev-ref", "@{u}"], {
18689
+ const result = spawnSync11("git", ["rev-parse", "--abbrev-ref", "@{u}"], {
18819
18690
  encoding: "utf-8",
18820
18691
  stdio: ["ignore", "pipe", "pipe"],
18821
18692
  cwd
@@ -18823,7 +18694,7 @@ function hasGitUpstream(cwd) {
18823
18694
  return result.status === 0;
18824
18695
  }
18825
18696
  function captureHeadSha(cwd) {
18826
- const result = spawnSync10("git", ["rev-parse", "HEAD"], {
18697
+ const result = spawnSync11("git", ["rev-parse", "HEAD"], {
18827
18698
  encoding: "utf-8",
18828
18699
  stdio: ["ignore", "pipe", "pipe"],
18829
18700
  cwd
@@ -18838,7 +18709,7 @@ function abbreviateSha(sha) {
18838
18709
  }
18839
18710
  function imageExists(tag) {
18840
18711
  try {
18841
- const result = spawnSync10("docker", ["image", "inspect", "--format", "{{.Id}}", tag], {
18712
+ const result = spawnSync11("docker", ["image", "inspect", "--format", "{{.Id}}", tag], {
18842
18713
  encoding: "utf-8",
18843
18714
  stdio: ["ignore", "pipe", "ignore"]
18844
18715
  });
@@ -18854,7 +18725,7 @@ function checkRollbackSetExists(plan) {
18854
18725
  }
18855
18726
  var SMOKE_DOCKER_TIMEOUT_MS = 3e4;
18856
18727
  function smokeImage(image, targetSha) {
18857
- const createResult = spawnSync10("docker", ["create", "--name", `olam-smoke-${Date.now()}`, image], {
18728
+ const createResult = spawnSync11("docker", ["create", "--name", `olam-smoke-${Date.now()}`, image], {
18858
18729
  encoding: "utf-8",
18859
18730
  stdio: ["ignore", "pipe", "pipe"],
18860
18731
  timeout: SMOKE_DOCKER_TIMEOUT_MS
@@ -18868,7 +18739,7 @@ function smokeImage(image, targetSha) {
18868
18739
  };
18869
18740
  }
18870
18741
  const containerId = (createResult.stdout ?? "").trim();
18871
- const inspectResult = spawnSync10(
18742
+ const inspectResult = spawnSync11(
18872
18743
  "docker",
18873
18744
  ["inspect", "--format", '{{index .Config.Labels "olam.build.sha"}}', image],
18874
18745
  {
@@ -18878,7 +18749,7 @@ function smokeImage(image, targetSha) {
18878
18749
  }
18879
18750
  );
18880
18751
  if (containerId.length > 0) {
18881
- spawnSync10("docker", ["rm", "-f", containerId], {
18752
+ spawnSync11("docker", ["rm", "-f", containerId], {
18882
18753
  encoding: "utf-8",
18883
18754
  stdio: ["ignore", "ignore", "ignore"],
18884
18755
  timeout: SMOKE_DOCKER_TIMEOUT_MS
@@ -18918,7 +18789,7 @@ var PRODUCTION_SWAP_PLAN = [
18918
18789
  ];
18919
18790
  function dockerTag(source, dest) {
18920
18791
  try {
18921
- const result = spawnSync10("docker", ["tag", source, dest], {
18792
+ const result = spawnSync11("docker", ["tag", source, dest], {
18922
18793
  encoding: "utf-8",
18923
18794
  stdio: ["ignore", "ignore", "pipe"]
18924
18795
  });
@@ -19082,11 +18953,11 @@ async function waitForAuthHealthLocal(timeoutMs = AUTH_HEALTH_TIMEOUT_MS) {
19082
18953
  async function recreateAuthService() {
19083
18954
  const start = Date.now();
19084
18955
  try {
19085
- spawnSync10("docker", ["stop", "olam-auth"], {
18956
+ spawnSync11("docker", ["stop", "olam-auth"], {
19086
18957
  encoding: "utf-8",
19087
18958
  stdio: ["ignore", "ignore", "ignore"]
19088
18959
  });
19089
- spawnSync10("docker", ["rm", "olam-auth"], {
18960
+ spawnSync11("docker", ["rm", "olam-auth"], {
19090
18961
  encoding: "utf-8",
19091
18962
  stdio: ["ignore", "ignore", "ignore"]
19092
18963
  });
@@ -19111,9 +18982,9 @@ async function recreateAuthService() {
19111
18982
  }
19112
18983
  }
19113
18984
  function readBundleHash(cwd) {
19114
- const indexPath = path32.join(cwd, "packages/control-plane/public/index.html");
19115
- if (!fs28.existsSync(indexPath)) return null;
19116
- return extractBundleHash(fs28.readFileSync(indexPath, "utf-8"));
18985
+ const indexPath = path31.join(cwd, "packages/control-plane/public/index.html");
18986
+ if (!fs27.existsSync(indexPath)) return null;
18987
+ return extractBundleHash(fs27.readFileSync(indexPath, "utf-8"));
19117
18988
  }
19118
18989
  async function runUpgradePullByDigest(deps = {}) {
19119
18990
  const docker2 = deps.docker ?? realDocker;
@@ -19125,19 +18996,27 @@ async function runUpgradePullByDigest(deps = {}) {
19125
18996
  if (info.exitCode !== 0) {
19126
18997
  infoSpinner.fail("docker daemon not reachable");
19127
18998
  process.stderr.write(
19128
- `${pc16.red("error")} docker info exited with ${info.exitCode}.
18999
+ `${pc17.red("error")} docker info exited with ${info.exitCode}.
19129
19000
  Ensure Docker Desktop / Colima / Rancher is running, then retry.
19130
19001
  `
19131
19002
  );
19132
19003
  return { exitCode: EXIT_GENERIC_ERROR, summary: "docker daemon not reachable" };
19133
19004
  }
19134
19005
  infoSpinner.succeed("docker daemon reachable");
19135
- const imageRefs = [
19006
+ const hasMcpAuthDigest = typeof digests["mcp-auth"] === "string" && digests["mcp-auth"].length > 0;
19007
+ const baseRefs = [
19136
19008
  { name: "host-cp", ref: `${registry}/olam-host-cp@${digests["host-cp"]}` },
19137
19009
  { name: "auth", ref: `${registry}/olam-auth@${digests.auth}` },
19138
19010
  { name: "devbox", ref: `${registry}/olam-devbox@${digests.devbox}` }
19139
19011
  ];
19140
- const pullSpinner = ora7("Pulling images (3 parallel)").start();
19012
+ if (hasMcpAuthDigest) {
19013
+ baseRefs.push({
19014
+ name: "mcp-auth",
19015
+ ref: `${registry}/olam-mcp-auth@${digests["mcp-auth"]}`
19016
+ });
19017
+ }
19018
+ const imageRefs = baseRefs;
19019
+ const pullSpinner = ora7(`Pulling images (${imageRefs.length} parallel)`).start();
19141
19020
  const pullStart = Date.now();
19142
19021
  const pullResults = await Promise.all(
19143
19022
  imageRefs.map(async ({ name, ref }) => ({
@@ -19152,7 +19031,7 @@ async function runUpgradePullByDigest(deps = {}) {
19152
19031
  pullSpinner.fail(`Pull failed for ${failed.map((r) => r.name).join(", ")}`);
19153
19032
  for (const f of failed) {
19154
19033
  process.stderr.write(
19155
- ` ${pc16.red(f.name)} (${f.ref}):
19034
+ ` ${pc17.red(f.name)} (${f.ref}):
19156
19035
  exit=${f.result.exitCode}
19157
19036
  stderr: ${f.result.stderr.split("\n")[0] ?? "(empty)"}
19158
19037
  `
@@ -19166,14 +19045,14 @@ async function runUpgradePullByDigest(deps = {}) {
19166
19045
  summary: `pull failed: ${failed.map((r) => r.name).join(", ")}`
19167
19046
  };
19168
19047
  }
19169
- pullSpinner.succeed(`Pulled 3 images in ${pullElapsed}s`);
19048
+ pullSpinner.succeed(`Pulled ${imageRefs.length} images in ${pullElapsed}s`);
19170
19049
  const handshakeSpinner = ora7("Verifying olam.protocol.versions handshake").start();
19171
19050
  for (const { name, ref } of imageRefs) {
19172
19051
  const inspect = await docker2.inspectLabel(ref, "olam.protocol.versions");
19173
19052
  if (inspect.exitCode !== 0) {
19174
19053
  handshakeSpinner.fail(`Could not inspect ${name}`);
19175
19054
  process.stderr.write(
19176
- `${pc16.red("error")} docker inspect ${ref} failed: ${inspect.stderr}
19055
+ `${pc17.red("error")} docker inspect ${ref} failed: ${inspect.stderr}
19177
19056
  `
19178
19057
  );
19179
19058
  return { exitCode: EXIT_GENERIC_ERROR, summary: `inspect failed: ${name}` };
@@ -19185,7 +19064,7 @@ async function runUpgradePullByDigest(deps = {}) {
19185
19064
  const decision = checkProtocolOverlap(versions);
19186
19065
  if (!decision.compatible) {
19187
19066
  handshakeSpinner.fail(`Protocol mismatch on ${name}`);
19188
- process.stderr.write(`${pc16.red("error")} ${decision.remedy}
19067
+ process.stderr.write(`${pc17.red("error")} ${decision.remedy}
19189
19068
  `);
19190
19069
  return {
19191
19070
  exitCode: EXIT_PROTOCOL_MISMATCH,
@@ -19193,8 +19072,8 @@ async function runUpgradePullByDigest(deps = {}) {
19193
19072
  };
19194
19073
  }
19195
19074
  }
19196
- handshakeSpinner.succeed("Protocol handshake passed (all 3 images)");
19197
- const tagPlan = [
19075
+ handshakeSpinner.succeed(`Protocol handshake passed (all ${imageRefs.length} images)`);
19076
+ const tagPlanBase = [
19198
19077
  { from: imageRefs[0].ref, to: "olam-host-cp:latest", name: "host-cp (bare)" },
19199
19078
  { from: imageRefs[0].ref, to: `${registry}/olam-host-cp:latest`, name: "host-cp (registry)" },
19200
19079
  { from: imageRefs[1].ref, to: "olam-auth:local", name: "auth (bare)" },
@@ -19202,13 +19081,20 @@ async function runUpgradePullByDigest(deps = {}) {
19202
19081
  { from: imageRefs[2].ref, to: "olam-devbox:latest", name: "devbox (bare)" },
19203
19082
  { from: imageRefs[2].ref, to: `${registry}/olam-devbox:latest`, name: "devbox (registry)" }
19204
19083
  ];
19084
+ if (hasMcpAuthDigest && imageRefs[3]) {
19085
+ tagPlanBase.push(
19086
+ { from: imageRefs[3].ref, to: "olam-mcp-auth:local", name: "mcp-auth (bare)" },
19087
+ { from: imageRefs[3].ref, to: `${registry}/olam-mcp-auth:latest`, name: "mcp-auth (registry)" }
19088
+ );
19089
+ }
19090
+ const tagPlan = tagPlanBase;
19205
19091
  const tagSpinner = ora7("Tagging digests \u2192 canonical local refs").start();
19206
19092
  const tagger = deps.tagImpl ?? dockerTag;
19207
19093
  for (const t of tagPlan) {
19208
19094
  const r = tagger(t.from, t.to);
19209
19095
  if (!r.ok) {
19210
19096
  tagSpinner.fail(`docker tag failed for ${t.name}`);
19211
- process.stderr.write(`${pc16.red("error")} ${r.error ?? "docker tag failed"}
19097
+ process.stderr.write(`${pc17.red("error")} ${r.error ?? "docker tag failed"}
19212
19098
  `);
19213
19099
  return { exitCode: EXIT_GENERIC_ERROR, summary: `tag failed: ${t.name}` };
19214
19100
  }
@@ -19226,7 +19112,7 @@ async function runUpgradePullByDigest(deps = {}) {
19226
19112
  if (!composeResult.ok) {
19227
19113
  composeSpinner.fail("compose recreate failed");
19228
19114
  process.stderr.write(
19229
- `${pc16.red("error")} docker compose up --force-recreate host-cp failed:
19115
+ `${pc17.red("error")} docker compose up --force-recreate host-cp failed:
19230
19116
  ${composeResult.stderr.split("\n").slice(0, 3).join("\n ")}
19231
19117
  `
19232
19118
  );
@@ -19239,25 +19125,68 @@ async function runUpgradePullByDigest(deps = {}) {
19239
19125
  if (!authResult.ok) {
19240
19126
  authSpinner.fail("auth-service recreate failed");
19241
19127
  process.stderr.write(
19242
- `${pc16.red("error")} ${authResult.error ?? "unknown failure"}
19128
+ `${pc17.red("error")} ${authResult.error ?? "unknown failure"}
19243
19129
  `
19244
19130
  );
19245
19131
  return { exitCode: EXIT_GENERIC_ERROR, summary: "auth recreate failed" };
19246
19132
  }
19247
19133
  authSpinner.succeed("auth-service running on new image");
19134
+ if (hasMcpAuthDigest) {
19135
+ const mcpSpinner = ora7("recreate mcp-auth-service").start();
19136
+ const mcpRecreate = deps.recreateMcpAuth ?? defaultRecreateMcpAuthForUpgrade;
19137
+ const mcpResult = await mcpRecreate();
19138
+ if (!mcpResult.ok) {
19139
+ mcpSpinner.fail("mcp-auth-service recreate failed");
19140
+ process.stderr.write(
19141
+ `${pc17.red("error")} ${mcpResult.error ?? "unknown failure"}
19142
+ `
19143
+ );
19144
+ return { exitCode: EXIT_GENERIC_ERROR, summary: "mcp-auth recreate failed" };
19145
+ }
19146
+ mcpSpinner.succeed("mcp-auth-service running on new image");
19147
+ }
19248
19148
  printSuccess("Upgrade complete (pull-by-digest)");
19249
19149
  printInfo("host-cp", `running (${digests["host-cp"].slice(0, 19)}\u2026)`);
19250
19150
  printInfo("auth", `running (${digests.auth.slice(0, 19)}\u2026)`);
19251
19151
  printInfo("devbox", `pulled (${digests.devbox.slice(0, 19)}\u2026)`);
19152
+ if (hasMcpAuthDigest) {
19153
+ printInfo("mcp-auth", `running (${digests["mcp-auth"].slice(0, 19)}\u2026)`);
19154
+ }
19252
19155
  return { exitCode: 0, summary: "stack upgraded" };
19253
19156
  }
19157
+ async function defaultRecreateMcpAuthForUpgrade() {
19158
+ try {
19159
+ const { spawnSync: ss } = await import("node:child_process");
19160
+ ss("docker", ["stop", "olam-mcp-auth"], { stdio: "ignore" });
19161
+ ss("docker", ["rm", "-f", "olam-mcp-auth"], { stdio: "ignore" });
19162
+ const startResult = ss("docker", [
19163
+ "run",
19164
+ "-d",
19165
+ "--name",
19166
+ "olam-mcp-auth",
19167
+ "-p",
19168
+ "9998:9998",
19169
+ "-v",
19170
+ "olam-mcp-auth-data:/mcp-auth-data",
19171
+ "--restart",
19172
+ "unless-stopped",
19173
+ "olam-mcp-auth:local"
19174
+ ], { stdio: "pipe" });
19175
+ if (startResult.status !== 0) {
19176
+ return { ok: false, error: `docker run failed: ${startResult.stderr?.toString() ?? "unknown"}` };
19177
+ }
19178
+ return { ok: true };
19179
+ } catch (err) {
19180
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
19181
+ }
19182
+ }
19254
19183
  async function defaultRecreateAuthForUpgrade() {
19255
19184
  try {
19256
- spawnSync10("docker", ["stop", "olam-auth"], {
19185
+ spawnSync11("docker", ["stop", "olam-auth"], {
19257
19186
  encoding: "utf-8",
19258
19187
  stdio: ["ignore", "ignore", "ignore"]
19259
19188
  });
19260
- spawnSync10("docker", ["rm", "olam-auth"], {
19189
+ spawnSync11("docker", ["rm", "olam-auth"], {
19261
19190
  encoding: "utf-8",
19262
19191
  stdio: ["ignore", "ignore", "ignore"]
19263
19192
  });
@@ -19402,11 +19331,11 @@ manually inspect images with \`docker images olam-*:olam-rollback\`.`
19402
19331
  process.once("SIGINT", releaseOnSignal);
19403
19332
  process.once("SIGTERM", releaseOnSignal);
19404
19333
  try {
19405
- process.stdout.write(` ${pc16.dim("rollback retag (3 ops)".padEnd(34))}`);
19334
+ process.stdout.write(` ${pc17.dim("rollback retag (3 ops)".padEnd(34))}`);
19406
19335
  const swapStart = Date.now();
19407
19336
  const swapResult = performRollbackSwap(PRODUCTION_SWAP_PLAN);
19408
19337
  const swapDur = `${((Date.now() - swapStart) / 1e3).toFixed(1)}s`;
19409
- process.stdout.write(`${swapResult.ok ? pc16.green("\u2713") : pc16.red("\u2717")} ${swapDur}
19338
+ process.stdout.write(`${swapResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${swapDur}
19410
19339
  `);
19411
19340
  if (!swapResult.ok) {
19412
19341
  printError(`Rollback retag failed: ${swapResult.summary}`);
@@ -19416,11 +19345,11 @@ manually inspect images with \`docker images olam-*:olam-rollback\`.`
19416
19345
  printInfo("Rollback", swapResult.summary);
19417
19346
  const composeFile = findComposeFile();
19418
19347
  const authSecret = readAuthSecret2();
19419
- process.stdout.write(` ${pc16.dim("docker compose recreate host-cp".padEnd(34))}`);
19348
+ process.stdout.write(` ${pc17.dim("docker compose recreate host-cp".padEnd(34))}`);
19420
19349
  const composeStart = Date.now();
19421
19350
  const composeResult = runCompose(["up", "-d", "--force-recreate", "--no-deps", "host-cp"], composeFile, buildComposeEnv(authSecret));
19422
19351
  const composeDur = `${((Date.now() - composeStart) / 1e3).toFixed(1)}s`;
19423
- process.stdout.write(`${composeResult.ok ? pc16.green("\u2713") : pc16.red("\u2717")} ${composeDur}
19352
+ process.stdout.write(`${composeResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${composeDur}
19424
19353
  `);
19425
19354
  if (!composeResult.ok) {
19426
19355
  printError(
@@ -19431,10 +19360,10 @@ Canonical tags are at :olam-rollback (good); container restart pending. Manually
19431
19360
  process.exitCode = 1;
19432
19361
  return;
19433
19362
  }
19434
- process.stdout.write(` ${pc16.dim("recreate auth-service".padEnd(34))}`);
19363
+ process.stdout.write(` ${pc17.dim("recreate auth-service".padEnd(34))}`);
19435
19364
  const authResult = await recreateAuthService();
19436
19365
  const authDur = `${(authResult.durationMs / 1e3).toFixed(1)}s`;
19437
- process.stdout.write(`${authResult.ok ? pc16.green("\u2713") : pc16.red("\u2717")} ${authDur}
19366
+ process.stdout.write(`${authResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${authDur}
19438
19367
  `);
19439
19368
  if (!authResult.ok) {
19440
19369
  printError(`Auth-service recreate failed: ${authResult.error ?? "unknown"}`);
@@ -19555,7 +19484,7 @@ ${buildResult.stderr}`);
19555
19484
  return;
19556
19485
  }
19557
19486
  const authSecret = readAuthSecret2();
19558
- const spaDir = path32.join(cwd, "packages/control-plane/app");
19487
+ const spaDir = path31.join(cwd, "packages/control-plane/app");
19559
19488
  const spaResult = runStep2(
19560
19489
  "vite build (SPA)",
19561
19490
  "npx",
@@ -19600,10 +19529,10 @@ ${spaResult.stderr}`);
19600
19529
  throw err;
19601
19530
  }
19602
19531
  if (step.tee) {
19603
- process.stdout.write(` ${pc16.dim(step.label.padEnd(34))}
19532
+ process.stdout.write(` ${pc17.dim(step.label.padEnd(34))}
19604
19533
  `);
19605
19534
  const start = Date.now();
19606
- const result = spawnSync10("bash", [scriptPath], {
19535
+ const result = spawnSync11("bash", [scriptPath], {
19607
19536
  stdio: "inherit",
19608
19537
  cwd,
19609
19538
  env: { ...process.env, ...olamTagEnv }
@@ -19611,7 +19540,7 @@ ${spaResult.stderr}`);
19611
19540
  const durationMs = Date.now() - start;
19612
19541
  const ok = result.status === 0 && result.error === void 0;
19613
19542
  const dur = `${(durationMs / 1e3).toFixed(1)}s`;
19614
- process.stdout.write(` ${pc16.dim(step.label.padEnd(34))}${ok ? pc16.green("\u2713") : pc16.red("\u2717")} ${dur}
19543
+ process.stdout.write(` ${pc17.dim(step.label.padEnd(34))}${ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${dur}
19615
19544
  `);
19616
19545
  timings.push({ label: step.label, durationMs });
19617
19546
  if (!ok) {
@@ -19637,7 +19566,7 @@ ${result.stderr.split("\n").slice(-3).join("\n")}`);
19637
19566
  }
19638
19567
  for (const t of timings) logRow.durations_ms[t.label] = t.durationMs;
19639
19568
  const smokeStart = Date.now();
19640
- process.stdout.write(` ${pc16.dim("smoke (docker create + inspect)".padEnd(34))}`);
19569
+ process.stdout.write(` ${pc17.dim("smoke (docker create + inspect)".padEnd(34))}`);
19641
19570
  const smokeImages = [
19642
19571
  "olam-auth:olam-next",
19643
19572
  "olam-devbox:olam-next",
@@ -19647,7 +19576,7 @@ ${result.stderr.split("\n").slice(-3).join("\n")}`);
19647
19576
  const smokeFailures = smokeResults.filter((r) => !r.ok);
19648
19577
  const smokeDurationMs = Date.now() - smokeStart;
19649
19578
  const smokeDur = `${(smokeDurationMs / 1e3).toFixed(1)}s`;
19650
- process.stdout.write(`${smokeFailures.length === 0 ? pc16.green("\u2713") : pc16.red("\u2717")} ${smokeDur}
19579
+ process.stdout.write(`${smokeFailures.length === 0 ? pc17.green("\u2713") : pc17.red("\u2717")} ${smokeDur}
19651
19580
  `);
19652
19581
  timings.push({ label: "smoke", durationMs: smokeDurationMs });
19653
19582
  if (smokeFailures.length > 0) {
@@ -19674,12 +19603,12 @@ Recovery options:
19674
19603
  process.exitCode = 1;
19675
19604
  return;
19676
19605
  }
19677
- process.stdout.write(` ${pc16.dim("atomic 6-tag swap".padEnd(34))}`);
19606
+ process.stdout.write(` ${pc17.dim("atomic 6-tag swap".padEnd(34))}`);
19678
19607
  const swapStart = Date.now();
19679
19608
  const swapResult = performAtomicSwap(PRODUCTION_SWAP_PLAN);
19680
19609
  const swapDurationMs = Date.now() - swapStart;
19681
19610
  const swapDur = `${(swapDurationMs / 1e3).toFixed(1)}s`;
19682
- process.stdout.write(`${swapResult.ok ? pc16.green("\u2713") : pc16.red("\u2717")} ${swapDur}
19611
+ process.stdout.write(`${swapResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${swapDur}
19683
19612
  `);
19684
19613
  timings.push({ label: "atomic swap", durationMs: swapDurationMs });
19685
19614
  if (!swapResult.ok) {
@@ -19689,7 +19618,7 @@ Recovery options:
19689
19618
  }
19690
19619
  printInfo("Swap", swapResult.summary);
19691
19620
  const composeFile = findComposeFile();
19692
- process.stdout.write(` ${pc16.dim("docker compose recreate".padEnd(34))}`);
19621
+ process.stdout.write(` ${pc17.dim("docker compose recreate".padEnd(34))}`);
19693
19622
  const composeStart = Date.now();
19694
19623
  const composeResult = runCompose(
19695
19624
  ["up", "-d", "--force-recreate"],
@@ -19699,7 +19628,7 @@ Recovery options:
19699
19628
  const composeDurationMs = Date.now() - composeStart;
19700
19629
  const composeOk = composeResult.ok;
19701
19630
  const composeDur = `${(composeDurationMs / 1e3).toFixed(1)}s`;
19702
- process.stdout.write(`${composeOk ? pc16.green("\u2713") : pc16.red("\u2717")} ${composeDur}
19631
+ process.stdout.write(`${composeOk ? pc17.green("\u2713") : pc17.red("\u2717")} ${composeDur}
19703
19632
  `);
19704
19633
  timings.push({ label: "container recreate", durationMs: composeDurationMs });
19705
19634
  if (!composeOk) {
@@ -19715,10 +19644,10 @@ Recovery options:
19715
19644
  process.exitCode = 1;
19716
19645
  return;
19717
19646
  }
19718
- process.stdout.write(` ${pc16.dim("recreate auth-service".padEnd(34))}`);
19647
+ process.stdout.write(` ${pc17.dim("recreate auth-service".padEnd(34))}`);
19719
19648
  const authResult = await recreateAuthService();
19720
19649
  const authDur = `${(authResult.durationMs / 1e3).toFixed(1)}s`;
19721
- process.stdout.write(`${authResult.ok ? pc16.green("\u2713") : pc16.red("\u2717")} ${authDur}
19650
+ process.stdout.write(`${authResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${authDur}
19722
19651
  `);
19723
19652
  timings.push({ label: "auth recreate", durationMs: authResult.durationMs });
19724
19653
  if (!authResult.ok) {
@@ -19733,12 +19662,12 @@ Recovery options:
19733
19662
  process.exitCode = 1;
19734
19663
  return;
19735
19664
  }
19736
- process.stdout.write(` ${pc16.dim("waiting for /health".padEnd(34))}`);
19665
+ process.stdout.write(` ${pc17.dim("waiting for /health".padEnd(34))}`);
19737
19666
  const healthStart = Date.now();
19738
19667
  const healthy = await waitForHealth(1e4);
19739
19668
  const healthDurationMs = Date.now() - healthStart;
19740
19669
  const healthDur = `${(healthDurationMs / 1e3).toFixed(1)}s`;
19741
- process.stdout.write(`${healthy ? pc16.green("\u2713") : pc16.yellow("?")} ${healthDur}
19670
+ process.stdout.write(`${healthy ? pc17.green("\u2713") : pc17.yellow("?")} ${healthDur}
19742
19671
  `);
19743
19672
  timings.push({ label: "/health", durationMs: healthDurationMs });
19744
19673
  if (!healthy) {
@@ -19746,12 +19675,12 @@ Recovery options:
19746
19675
  "Host CP started but /health did not respond within 10s.\n \u2022 Check: docker logs olam-host-cp\n \u2022 If the new SHA is broken: `olam upgrade --rollback` restores the prior set in <30s."
19747
19676
  );
19748
19677
  }
19749
- process.stdout.write(` ${pc16.dim("verify /version/status round-trip".padEnd(34))}`);
19678
+ process.stdout.write(` ${pc17.dim("verify /version/status round-trip".padEnd(34))}`);
19750
19679
  const versionStart = Date.now();
19751
19680
  const versionMatch = await waitForVersionMatch(_targetSha, 9e4);
19752
19681
  const versionDurationMs = Date.now() - versionStart;
19753
19682
  const versionDur = `${(versionDurationMs / 1e3).toFixed(1)}s`;
19754
- process.stdout.write(`${versionMatch.matched ? pc16.green("\u2713") : pc16.yellow("?")} ${versionDur}
19683
+ process.stdout.write(`${versionMatch.matched ? pc17.green("\u2713") : pc17.yellow("?")} ${versionDur}
19755
19684
  `);
19756
19685
  timings.push({ label: "/version/status round-trip", durationMs: versionDurationMs });
19757
19686
  if (!versionMatch.matched) {
@@ -19825,16 +19754,16 @@ init_host_cp();
19825
19754
  init_context();
19826
19755
  init_output();
19827
19756
  import * as http3 from "node:http";
19828
- import pc17 from "picocolors";
19757
+ import pc18 from "picocolors";
19829
19758
  var HOST_CP_PORT3 = 19e3;
19830
19759
  function colorLine(line) {
19831
- if (/\bERROR\b/.test(line)) return pc17.red(line);
19832
- if (/\bWARN\b/.test(line)) return pc17.yellow(line);
19833
- if (/\bINFO\b/.test(line)) return pc17.dim(line);
19760
+ if (/\bERROR\b/.test(line)) return pc18.red(line);
19761
+ if (/\bWARN\b/.test(line)) return pc18.yellow(line);
19762
+ if (/\bINFO\b/.test(line)) return pc18.dim(line);
19834
19763
  return line;
19835
19764
  }
19836
19765
  function formatLine(line, service, showService) {
19837
- const prefix = showService && service ? `${pc17.cyan(`[${service}]`)} ` : "";
19766
+ const prefix = showService && service ? `${pc18.cyan(`[${service}]`)} ` : "";
19838
19767
  return prefix + colorLine(line);
19839
19768
  }
19840
19769
  function parseSseEvent(raw) {
@@ -19951,8 +19880,8 @@ function registerLogs(program2) {
19951
19880
  // src/commands/ps.ts
19952
19881
  init_context();
19953
19882
  init_output();
19954
- import pc18 from "picocolors";
19955
- import { spawnSync as spawnSync11 } from "node:child_process";
19883
+ import pc19 from "picocolors";
19884
+ import { spawnSync as spawnSync12 } from "node:child_process";
19956
19885
  var SAFE_IDENT4 = /^[a-z0-9][a-z0-9-]{0,63}$/;
19957
19886
  function parseDockerTop(stdout) {
19958
19887
  const trimmed = stdout.trim();
@@ -20012,18 +19941,18 @@ function printTable2(rows) {
20012
19941
  const fixedWidth = 5 + 1 + 8 + 1 + 6 + 1 + 6 + 1 + 10 + 1 + 6 + 1;
20013
19942
  const cmdWidth = Math.max(20, cols - fixedWidth);
20014
19943
  const header = [
20015
- pc18.bold(pc18.dim("PID".padEnd(5))),
20016
- pc18.bold(pc18.dim("USER".padEnd(8))),
20017
- pc18.bold(pc18.dim("%CPU".padEnd(6))),
20018
- pc18.bold(pc18.dim("%MEM".padEnd(6))),
20019
- pc18.bold(pc18.dim("STARTED".padEnd(10))),
20020
- pc18.bold(pc18.dim("STATE".padEnd(6))),
20021
- pc18.bold(pc18.dim("COMMAND"))
19944
+ pc19.bold(pc19.dim("PID".padEnd(5))),
19945
+ pc19.bold(pc19.dim("USER".padEnd(8))),
19946
+ pc19.bold(pc19.dim("%CPU".padEnd(6))),
19947
+ pc19.bold(pc19.dim("%MEM".padEnd(6))),
19948
+ pc19.bold(pc19.dim("STARTED".padEnd(10))),
19949
+ pc19.bold(pc19.dim("STATE".padEnd(6))),
19950
+ pc19.bold(pc19.dim("COMMAND"))
20022
19951
  ].join(" ");
20023
19952
  console.log(header);
20024
19953
  for (const row of rows) {
20025
19954
  const cmd = row.command.length > cmdWidth ? row.command.slice(0, cmdWidth - 1) + "\u2026" : row.command;
20026
- const stateFn = row.state.startsWith("R") ? pc18.green : row.state.startsWith("Z") ? pc18.red : pc18.dim;
19955
+ const stateFn = row.state.startsWith("R") ? pc19.green : row.state.startsWith("Z") ? pc19.red : pc19.dim;
20027
19956
  console.log([
20028
19957
  row.pid.padEnd(5),
20029
19958
  row.user.slice(0, 8).padEnd(8),
@@ -20052,7 +19981,7 @@ function registerPs(program2) {
20052
19981
  const containerName = `olam-${worldId}-devbox`;
20053
19982
  let watchInterval;
20054
19983
  function fetchAndPrint() {
20055
- const result = spawnSync11(
19984
+ const result = spawnSync12(
20056
19985
  "docker",
20057
19986
  ["top", containerName, "pid", "user", "pcpu", "pmem", "stime", "stat", "cmd"],
20058
19987
  { encoding: "utf-8", timeout: 3e3 }
@@ -20072,7 +20001,7 @@ function registerPs(program2) {
20072
20001
  printTable2(rows);
20073
20002
  if (opts.watch) {
20074
20003
  process.stdout.write(`
20075
- ${pc18.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
20004
+ ${pc19.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
20076
20005
  `);
20077
20006
  }
20078
20007
  }
@@ -20089,20 +20018,20 @@ ${pc18.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
20089
20018
 
20090
20019
  // src/commands/keys.ts
20091
20020
  init_output();
20092
- import * as fs29 from "node:fs";
20021
+ import * as fs28 from "node:fs";
20093
20022
  import * as os17 from "node:os";
20094
- import * as path33 from "node:path";
20023
+ import * as path32 from "node:path";
20095
20024
  import YAML4 from "yaml";
20096
20025
  function olamHome2() {
20097
- return process.env.OLAM_HOME ?? path33.join(os17.homedir(), ".olam");
20026
+ return process.env.OLAM_HOME ?? path32.join(os17.homedir(), ".olam");
20098
20027
  }
20099
20028
  function keysFilePath() {
20100
- return path33.join(olamHome2(), "keys.yaml");
20029
+ return path32.join(olamHome2(), "keys.yaml");
20101
20030
  }
20102
20031
  function readKeysFile() {
20103
20032
  const filePath = keysFilePath();
20104
- if (!fs29.existsSync(filePath)) return null;
20105
- const raw = fs29.readFileSync(filePath, "utf-8").trim();
20033
+ if (!fs28.existsSync(filePath)) return null;
20034
+ const raw = fs28.readFileSync(filePath, "utf-8").trim();
20106
20035
  if (raw.length === 0) return null;
20107
20036
  try {
20108
20037
  const parsed = YAML4.parse(raw);
@@ -20118,13 +20047,13 @@ function readKeysFile() {
20118
20047
  }
20119
20048
  function writeKeysFile(keys) {
20120
20049
  const dir = olamHome2();
20121
- if (!fs29.existsSync(dir)) {
20122
- fs29.mkdirSync(dir, { recursive: true });
20050
+ if (!fs28.existsSync(dir)) {
20051
+ fs28.mkdirSync(dir, { recursive: true });
20123
20052
  }
20124
20053
  const filePath = keysFilePath();
20125
20054
  const content = YAML4.stringify(keys);
20126
- fs29.writeFileSync(filePath, content, { encoding: "utf-8", mode: 384 });
20127
- fs29.chmodSync(filePath, 384);
20055
+ fs28.writeFileSync(filePath, content, { encoding: "utf-8", mode: 384 });
20056
+ fs28.chmodSync(filePath, 384);
20128
20057
  }
20129
20058
  function redact(value) {
20130
20059
  if (value.length <= 8) return value + "...";
@@ -20167,7 +20096,7 @@ function registerKeys(program2) {
20167
20096
  }
20168
20097
  const { [key]: _removed, ...rest } = existing;
20169
20098
  if (Object.keys(rest).length === 0) {
20170
- fs29.unlinkSync(keysFilePath());
20099
+ fs28.unlinkSync(keysFilePath());
20171
20100
  } else {
20172
20101
  writeKeysFile(rest);
20173
20102
  }
@@ -20190,33 +20119,33 @@ function registerKeys(program2) {
20190
20119
  }
20191
20120
 
20192
20121
  // src/commands/world-snapshot.ts
20193
- import * as fs31 from "node:fs";
20194
- import * as path35 from "node:path";
20122
+ import * as fs30 from "node:fs";
20123
+ import * as path34 from "node:path";
20195
20124
  import { execSync as execSync9 } from "node:child_process";
20196
- import pc19 from "picocolors";
20125
+ import pc20 from "picocolors";
20197
20126
 
20198
20127
  // ../core/dist/world/snapshot.js
20199
- import * as crypto7 from "node:crypto";
20200
- import * as fs30 from "node:fs";
20128
+ import * as crypto6 from "node:crypto";
20129
+ import * as fs29 from "node:fs";
20201
20130
  import * as os18 from "node:os";
20202
- import * as path34 from "node:path";
20203
- import { execFileSync as execFileSync5 } from "node:child_process";
20131
+ import * as path33 from "node:path";
20132
+ import { execFileSync as execFileSync6 } from "node:child_process";
20204
20133
  function snapshotsDir() {
20205
- return process.env["OLAM_SNAPSHOTS_DIR"] ?? path34.join(os18.homedir(), ".olam", "snapshots");
20134
+ return process.env["OLAM_SNAPSHOTS_DIR"] ?? path33.join(os18.homedir(), ".olam", "snapshots");
20206
20135
  }
20207
20136
  function snapshotKindDir(worldId, kind) {
20208
- return path34.join(snapshotsDir(), worldId, kind);
20137
+ return path33.join(snapshotsDir(), worldId, kind);
20209
20138
  }
20210
20139
  function snapshotTarPath(worldId, kind, repoName, hash) {
20211
20140
  const base = repoName ? `${repoName}-${hash}` : hash;
20212
- return path34.join(snapshotKindDir(worldId, kind), `${base}.tar.gz`);
20141
+ return path33.join(snapshotKindDir(worldId, kind), `${base}.tar.gz`);
20213
20142
  }
20214
20143
  function manifestPath(tarPath) {
20215
20144
  return tarPath.replace(/\.tar\.gz$/, ".manifest.json");
20216
20145
  }
20217
20146
  function hashBuffers(entries) {
20218
20147
  const sorted = [...entries].sort((a, b) => a.path.localeCompare(b.path));
20219
- const hash = crypto7.createHash("sha256");
20148
+ const hash = crypto6.createHash("sha256");
20220
20149
  for (const entry of sorted) {
20221
20150
  hash.update(entry.path);
20222
20151
  hash.update("\0");
@@ -20226,17 +20155,17 @@ function hashBuffers(entries) {
20226
20155
  return hash.digest("hex").slice(0, 12);
20227
20156
  }
20228
20157
  function computeGemsFingerprint(repoDir) {
20229
- const lockfile = path34.join(repoDir, "Gemfile.lock");
20230
- if (!fs30.existsSync(lockfile))
20158
+ const lockfile = path33.join(repoDir, "Gemfile.lock");
20159
+ if (!fs29.existsSync(lockfile))
20231
20160
  return null;
20232
- return hashBuffers([{ path: "Gemfile.lock", content: fs30.readFileSync(lockfile) }]);
20161
+ return hashBuffers([{ path: "Gemfile.lock", content: fs29.readFileSync(lockfile) }]);
20233
20162
  }
20234
20163
  function computeNodeFingerprint(repoDir) {
20235
20164
  const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
20236
20165
  for (const name of candidates) {
20237
- const lockfile = path34.join(repoDir, name);
20238
- if (fs30.existsSync(lockfile)) {
20239
- return hashBuffers([{ path: name, content: fs30.readFileSync(lockfile) }]);
20166
+ const lockfile = path33.join(repoDir, name);
20167
+ if (fs29.existsSync(lockfile)) {
20168
+ return hashBuffers([{ path: name, content: fs29.readFileSync(lockfile) }]);
20240
20169
  }
20241
20170
  }
20242
20171
  return null;
@@ -20246,64 +20175,64 @@ function computePgFingerprint(repoDirs) {
20246
20175
  const entries = [];
20247
20176
  for (const repoDir of repoDirs) {
20248
20177
  for (const pattern of patterns) {
20249
- const filePath = path34.join(repoDir, pattern);
20250
- if (fs30.existsSync(filePath)) {
20251
- entries.push({ path: filePath, content: fs30.readFileSync(filePath) });
20178
+ const filePath = path33.join(repoDir, pattern);
20179
+ if (fs29.existsSync(filePath)) {
20180
+ entries.push({ path: filePath, content: fs29.readFileSync(filePath) });
20252
20181
  }
20253
20182
  }
20254
20183
  }
20255
20184
  return entries.length > 0 ? hashBuffers(entries) : null;
20256
20185
  }
20257
20186
  function packTarball(srcDir, destPath, opts = {}) {
20258
- fs30.mkdirSync(path34.dirname(destPath), { recursive: true });
20187
+ fs29.mkdirSync(path33.dirname(destPath), { recursive: true });
20259
20188
  const tmp = `${destPath}.tmp`;
20260
20189
  const args = [];
20261
20190
  if (opts.followSymlinks)
20262
20191
  args.push("-h");
20263
20192
  args.push("-czf", tmp, "-C", srcDir, ".");
20264
20193
  try {
20265
- execFileSync5("tar", args, { stdio: "pipe" });
20266
- fs30.renameSync(tmp, destPath);
20194
+ execFileSync6("tar", args, { stdio: "pipe" });
20195
+ fs29.renameSync(tmp, destPath);
20267
20196
  } catch (err) {
20268
20197
  try {
20269
- fs30.rmSync(tmp, { force: true });
20198
+ fs29.rmSync(tmp, { force: true });
20270
20199
  } catch {
20271
20200
  }
20272
20201
  throw err;
20273
20202
  }
20274
20203
  }
20275
20204
  function writeManifest(manifest, tarPath) {
20276
- fs30.writeFileSync(manifestPath(tarPath), JSON.stringify(manifest, null, 2), "utf-8");
20205
+ fs29.writeFileSync(manifestPath(tarPath), JSON.stringify(manifest, null, 2), "utf-8");
20277
20206
  }
20278
20207
  function readManifest(tarPath) {
20279
20208
  const mPath = manifestPath(tarPath);
20280
- if (!fs30.existsSync(mPath))
20209
+ if (!fs29.existsSync(mPath))
20281
20210
  return null;
20282
20211
  try {
20283
- return JSON.parse(fs30.readFileSync(mPath, "utf-8"));
20212
+ return JSON.parse(fs29.readFileSync(mPath, "utf-8"));
20284
20213
  } catch {
20285
20214
  return null;
20286
20215
  }
20287
20216
  }
20288
20217
  function listSnapshots(worldIdFilter) {
20289
20218
  const root = snapshotsDir();
20290
- if (!fs30.existsSync(root))
20219
+ if (!fs29.existsSync(root))
20291
20220
  return [];
20292
20221
  const now = Date.now();
20293
20222
  const results = [];
20294
- const worlds = worldIdFilter ? [worldIdFilter] : fs30.readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
20223
+ const worlds = worldIdFilter ? [worldIdFilter] : fs29.readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
20295
20224
  for (const worldId of worlds) {
20296
- const worldDir = path34.join(root, worldId);
20297
- if (!fs30.existsSync(worldDir) || !fs30.statSync(worldDir).isDirectory())
20225
+ const worldDir = path33.join(root, worldId);
20226
+ if (!fs29.existsSync(worldDir) || !fs29.statSync(worldDir).isDirectory())
20298
20227
  continue;
20299
20228
  for (const kind of ["gems", "node", "pg"]) {
20300
- const kindDir = path34.join(worldDir, kind);
20301
- if (!fs30.existsSync(kindDir))
20229
+ const kindDir = path33.join(worldDir, kind);
20230
+ if (!fs29.existsSync(kindDir))
20302
20231
  continue;
20303
- const tarballs = fs30.readdirSync(kindDir).filter((f) => f.endsWith(".tar.gz"));
20232
+ const tarballs = fs29.readdirSync(kindDir).filter((f) => f.endsWith(".tar.gz"));
20304
20233
  for (const tarFile of tarballs) {
20305
- const tarPath = path34.join(kindDir, tarFile);
20306
- const stat = fs30.statSync(tarPath);
20234
+ const tarPath = path33.join(kindDir, tarFile);
20235
+ const stat = fs29.statSync(tarPath);
20307
20236
  const manifest = readManifest(tarPath);
20308
20237
  if (!manifest)
20309
20238
  continue;
@@ -20379,7 +20308,7 @@ async function handleCreate2(worldId, kindArg) {
20379
20308
  const label = r.repo ? `${r.kind}/${r.repo}` : r.kind;
20380
20309
  if (r.ok) {
20381
20310
  printSuccess(`${label}`);
20382
- console.log(` ${pc19.dim(r.tarPath)}`);
20311
+ console.log(` ${pc20.dim(r.tarPath)}`);
20383
20312
  } else {
20384
20313
  printWarning(`${label}: ${r.msg ?? "skipped"}`);
20385
20314
  }
@@ -20393,17 +20322,17 @@ function resolveKinds(arg) {
20393
20322
  return [];
20394
20323
  }
20395
20324
  async function captureGems(worldId, workspacePath, repo) {
20396
- const repoDir = path35.join(workspacePath, repo);
20325
+ const repoDir = path34.join(workspacePath, repo);
20397
20326
  const fingerprint = computeGemsFingerprint(repoDir);
20398
20327
  if (!fingerprint) {
20399
20328
  return { ok: false, tarPath: "", msg: "no Gemfile.lock \u2014 layer does not apply" };
20400
20329
  }
20401
20330
  const tarPath = snapshotTarPath(worldId, "gems", repo, fingerprint);
20402
- const vendorBundle = path35.join(repoDir, "vendor", "bundle");
20403
- if (fs31.existsSync(vendorBundle)) {
20331
+ const vendorBundle = path34.join(repoDir, "vendor", "bundle");
20332
+ if (fs30.existsSync(vendorBundle)) {
20404
20333
  try {
20405
20334
  packTarball(vendorBundle, tarPath);
20406
- const stat = fs31.statSync(tarPath);
20335
+ const stat = fs30.statSync(tarPath);
20407
20336
  const manifest = {
20408
20337
  kind: "gems",
20409
20338
  worldId,
@@ -20436,10 +20365,10 @@ async function captureGems(worldId, workspacePath, repo) {
20436
20365
  `docker exec ${containerName} sh -c 'mkdir -p "$(dirname ${tmpTar})" && tar -czf ${tmpTar}.tmp -C ${bundlePath} . && mv ${tmpTar}.tmp ${tmpTar}'`,
20437
20366
  { stdio: "pipe", timeout: 12e4 }
20438
20367
  );
20439
- fs31.mkdirSync(path35.dirname(tarPath), { recursive: true });
20368
+ fs30.mkdirSync(path34.dirname(tarPath), { recursive: true });
20440
20369
  execSync9(`docker cp ${containerName}:${tmpTar} "${tarPath}"`, { stdio: "pipe", timeout: 12e4 });
20441
20370
  execSync9(`docker exec ${containerName} rm -f ${tmpTar}`, { stdio: "pipe" });
20442
- const stat = fs31.statSync(tarPath);
20371
+ const stat = fs30.statSync(tarPath);
20443
20372
  const manifest = {
20444
20373
  kind: "gems",
20445
20374
  worldId,
@@ -20456,19 +20385,19 @@ async function captureGems(worldId, workspacePath, repo) {
20456
20385
  }
20457
20386
  }
20458
20387
  async function captureNode(worldId, workspacePath, repo) {
20459
- const repoDir = path35.join(workspacePath, repo);
20388
+ const repoDir = path34.join(workspacePath, repo);
20460
20389
  const fingerprint = computeNodeFingerprint(repoDir);
20461
20390
  if (!fingerprint) {
20462
20391
  return { ok: false, tarPath: "", msg: "no lockfile \u2014 layer does not apply" };
20463
20392
  }
20464
- const nodeModules = path35.join(repoDir, "node_modules");
20465
- if (!fs31.existsSync(nodeModules)) {
20393
+ const nodeModules = path34.join(repoDir, "node_modules");
20394
+ if (!fs30.existsSync(nodeModules)) {
20466
20395
  return { ok: false, tarPath: "", msg: "node_modules not installed yet" };
20467
20396
  }
20468
20397
  const tarPath = snapshotTarPath(worldId, "node", repo, fingerprint);
20469
20398
  try {
20470
20399
  packTarball(nodeModules, tarPath);
20471
- const stat = fs31.statSync(tarPath);
20400
+ const stat = fs30.statSync(tarPath);
20472
20401
  const manifest = {
20473
20402
  kind: "node",
20474
20403
  worldId,
@@ -20485,7 +20414,7 @@ async function captureNode(worldId, workspacePath, repo) {
20485
20414
  }
20486
20415
  }
20487
20416
  async function capturePg(worldId, workspacePath, repoNames) {
20488
- const repoDirs = repoNames.map((r) => path35.join(workspacePath, r));
20417
+ const repoDirs = repoNames.map((r) => path34.join(workspacePath, r));
20489
20418
  const fingerprint = computePgFingerprint(repoDirs);
20490
20419
  if (!fingerprint) {
20491
20420
  return { ok: false, tarPath: "", msg: "no Gemfile.lock / schema.rb \u2014 layer does not apply" };
@@ -20500,13 +20429,13 @@ async function capturePg(worldId, workspacePath, repoNames) {
20500
20429
  }
20501
20430
  try {
20502
20431
  execSync9(`docker stop ${containerName}`, { stdio: "pipe", timeout: 3e4 });
20503
- fs31.mkdirSync(path35.dirname(tarPath), { recursive: true });
20432
+ fs30.mkdirSync(path34.dirname(tarPath), { recursive: true });
20504
20433
  execSync9(
20505
- `docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${path35.dirname(tarPath)}:/dest" alpine sh -c 'tar -czf /dest/${path35.basename(tarPath)}.tmp -C /pgdata . && mv /dest/${path35.basename(tarPath)}.tmp /dest/${path35.basename(tarPath)}'`,
20434
+ `docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${path34.dirname(tarPath)}:/dest" alpine sh -c 'tar -czf /dest/${path34.basename(tarPath)}.tmp -C /pgdata . && mv /dest/${path34.basename(tarPath)}.tmp /dest/${path34.basename(tarPath)}'`,
20506
20435
  { stdio: "pipe", timeout: 18e4 }
20507
20436
  );
20508
20437
  execSync9(`docker start ${containerName}`, { stdio: "pipe", timeout: 3e4 });
20509
- const stat = fs31.statSync(tarPath);
20438
+ const stat = fs30.statSync(tarPath);
20510
20439
  const manifest = {
20511
20440
  kind: "pg",
20512
20441
  worldId,
@@ -20529,7 +20458,7 @@ function handleList2(worldIdFilter) {
20529
20458
  const entries = listSnapshots(worldIdFilter);
20530
20459
  if (entries.length === 0) {
20531
20460
  const where = worldIdFilter ? ` for world "${worldIdFilter}"` : "";
20532
- console.log(pc19.dim(`No snapshots found${where}. Run \`olam world snapshot create <worldId>\` first.`));
20461
+ console.log(pc20.dim(`No snapshots found${where}. Run \`olam world snapshot create <worldId>\` first.`));
20533
20462
  return;
20534
20463
  }
20535
20464
  printHeader(`${entries.length} snapshot(s)`);
@@ -20538,15 +20467,15 @@ function handleList2(worldIdFilter) {
20538
20467
  for (const entry of entries) {
20539
20468
  const { manifest } = entry;
20540
20469
  if (manifest.worldId !== lastWorldId) {
20541
- console.log(pc19.bold(manifest.worldId));
20470
+ console.log(pc20.bold(manifest.worldId));
20542
20471
  lastWorldId = manifest.worldId;
20543
20472
  }
20544
20473
  const repo = manifest.repo ?? "(all repos)";
20545
20474
  const size = formatBytes2(manifest.sizeBytes);
20546
20475
  const age = formatAge2(entry.ageMs);
20547
- const kindColor = manifest.kind === "gems" ? pc19.magenta(manifest.kind) : manifest.kind === "node" ? pc19.cyan(manifest.kind) : pc19.yellow(manifest.kind);
20476
+ const kindColor = manifest.kind === "gems" ? pc20.magenta(manifest.kind) : manifest.kind === "node" ? pc20.cyan(manifest.kind) : pc20.yellow(manifest.kind);
20548
20477
  console.log(
20549
- ` ${kindColor.padEnd(6)} ${pc19.dim(repo.padEnd(24))} ${manifest.fingerprint} ${size.padStart(8)} ${age}`
20478
+ ` ${kindColor.padEnd(6)} ${pc20.dim(repo.padEnd(24))} ${manifest.fingerprint} ${size.padStart(8)} ${age}`
20550
20479
  );
20551
20480
  }
20552
20481
  console.log();
@@ -20581,35 +20510,35 @@ function formatAge2(ms) {
20581
20510
  // src/commands/refresh.ts
20582
20511
  init_context();
20583
20512
  init_output();
20584
- import * as fs33 from "node:fs";
20513
+ import * as fs32 from "node:fs";
20585
20514
  import * as os19 from "node:os";
20586
- import * as path37 from "node:path";
20587
- import { spawnSync as spawnSync12 } from "node:child_process";
20515
+ import * as path36 from "node:path";
20516
+ import { spawnSync as spawnSync13 } from "node:child_process";
20588
20517
  import ora8 from "ora";
20589
20518
 
20590
20519
  // src/commands/refresh-helpers.ts
20591
- import * as fs32 from "node:fs";
20592
- import * as path36 from "node:path";
20520
+ import * as fs31 from "node:fs";
20521
+ import * as path35 from "node:path";
20593
20522
  function collectCpSourceFiles(standaloneDir) {
20594
- if (!fs32.existsSync(standaloneDir)) {
20523
+ if (!fs31.existsSync(standaloneDir)) {
20595
20524
  throw new Error(`CP standalone dir not found: ${standaloneDir}`);
20596
20525
  }
20597
20526
  const entries = [];
20598
- const topLevel = fs32.readdirSync(standaloneDir).filter((f) => {
20599
- const stat = fs32.statSync(path36.join(standaloneDir, f));
20527
+ const topLevel = fs31.readdirSync(standaloneDir).filter((f) => {
20528
+ const stat = fs31.statSync(path35.join(standaloneDir, f));
20600
20529
  return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
20601
20530
  }).sort();
20602
20531
  for (const f of topLevel) {
20603
- entries.push({ srcPath: path36.join(standaloneDir, f), destRelPath: f });
20532
+ entries.push({ srcPath: path35.join(standaloneDir, f), destRelPath: f });
20604
20533
  }
20605
- const libDir = path36.join(standaloneDir, "lib");
20606
- if (fs32.existsSync(libDir) && fs32.statSync(libDir).isDirectory()) {
20607
- const libFiles = fs32.readdirSync(libDir).filter((f) => {
20608
- const stat = fs32.statSync(path36.join(libDir, f));
20534
+ const libDir = path35.join(standaloneDir, "lib");
20535
+ if (fs31.existsSync(libDir) && fs31.statSync(libDir).isDirectory()) {
20536
+ const libFiles = fs31.readdirSync(libDir).filter((f) => {
20537
+ const stat = fs31.statSync(path35.join(libDir, f));
20609
20538
  return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
20610
20539
  }).sort();
20611
20540
  for (const f of libFiles) {
20612
- entries.push({ srcPath: path36.join(libDir, f), destRelPath: `lib/${f}` });
20541
+ entries.push({ srcPath: path35.join(libDir, f), destRelPath: `lib/${f}` });
20613
20542
  }
20614
20543
  }
20615
20544
  return entries;
@@ -20628,7 +20557,7 @@ var RESTART_TIMEOUT_S = 30;
20628
20557
  var HEALTH_POLL_MS = 500;
20629
20558
  var HEALTH_TIMEOUT_MS = 3e4;
20630
20559
  function docker(args) {
20631
- const result = spawnSync12("docker", args, {
20560
+ const result = spawnSync13("docker", args, {
20632
20561
  encoding: "utf-8",
20633
20562
  stdio: ["ignore", "pipe", "pipe"]
20634
20563
  });
@@ -20667,16 +20596,16 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
20667
20596
  error: err instanceof Error ? err.message : String(err)
20668
20597
  };
20669
20598
  }
20670
- const stagingDir = fs33.mkdtempSync(
20671
- path37.join(os19.tmpdir(), `olam-refresh-${worldId}-`)
20599
+ const stagingDir = fs32.mkdtempSync(
20600
+ path36.join(os19.tmpdir(), `olam-refresh-${worldId}-`)
20672
20601
  );
20673
20602
  try {
20674
20603
  const hasLib = entries.some((e) => e.destRelPath.startsWith("lib/"));
20675
20604
  if (hasLib) {
20676
- fs33.mkdirSync(path37.join(stagingDir, "lib"), { recursive: true });
20605
+ fs32.mkdirSync(path36.join(stagingDir, "lib"), { recursive: true });
20677
20606
  }
20678
20607
  for (const { srcPath, destRelPath } of entries) {
20679
- fs33.copyFileSync(srcPath, path37.join(stagingDir, destRelPath));
20608
+ fs32.copyFileSync(srcPath, path36.join(stagingDir, destRelPath));
20680
20609
  }
20681
20610
  const cpResult = docker([
20682
20611
  "cp",
@@ -20691,7 +20620,7 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
20691
20620
  };
20692
20621
  }
20693
20622
  } finally {
20694
- fs33.rmSync(stagingDir, { recursive: true, force: true });
20623
+ fs32.rmSync(stagingDir, { recursive: true, force: true });
20695
20624
  }
20696
20625
  if (opts.restart) {
20697
20626
  const restartResult = docker([
@@ -20728,11 +20657,11 @@ function registerRefresh(program2) {
20728
20657
  process.exitCode = 1;
20729
20658
  return;
20730
20659
  }
20731
- const standaloneDir = path37.join(
20660
+ const standaloneDir = path36.join(
20732
20661
  process.cwd(),
20733
20662
  "packages/control-plane/standalone"
20734
20663
  );
20735
- if (!fs33.existsSync(standaloneDir)) {
20664
+ if (!fs32.existsSync(standaloneDir)) {
20736
20665
  printError(
20737
20666
  `CP standalone source not found at ${standaloneDir}.
20738
20667
  Run \`olam refresh\` from the olam repo root.`
@@ -20811,11 +20740,11 @@ Run \`olam refresh\` from the olam repo root.`
20811
20740
  }
20812
20741
 
20813
20742
  // src/commands/diagnose.ts
20814
- import * as fs34 from "node:fs";
20743
+ import * as fs33 from "node:fs";
20815
20744
  import * as os20 from "node:os";
20816
- import * as path38 from "node:path";
20817
- import { execFileSync as execFileSync6, execSync as execSync10 } from "node:child_process";
20818
- import pc20 from "picocolors";
20745
+ import * as path37 from "node:path";
20746
+ import { execFileSync as execFileSync7, execSync as execSync10 } from "node:child_process";
20747
+ import pc21 from "picocolors";
20819
20748
 
20820
20749
  // ../core/dist/diagnose/secret-stripper.js
20821
20750
  var SECRET_PATTERNS = [
@@ -20848,9 +20777,9 @@ function stripSecrets(input) {
20848
20777
  }
20849
20778
 
20850
20779
  // src/commands/diagnose.ts
20851
- var DIAGNOSTICS_DIR = path38.join(os20.homedir(), ".olam", "diagnostics");
20852
- var LOG_DIR = path38.join(os20.homedir(), ".olam", "log");
20853
- var CACHE_DIR = path38.join(os20.homedir(), ".olam", "cache");
20780
+ var DIAGNOSTICS_DIR = path37.join(os20.homedir(), ".olam", "diagnostics");
20781
+ var LOG_DIR = path37.join(os20.homedir(), ".olam", "log");
20782
+ var CACHE_DIR = path37.join(os20.homedir(), ".olam", "cache");
20854
20783
  var LOG_TAIL_LINES = 200;
20855
20784
  function safeExec(cmd) {
20856
20785
  try {
@@ -20860,14 +20789,14 @@ function safeExec(cmd) {
20860
20789
  }
20861
20790
  }
20862
20791
  function defaultZip(zipPath, files) {
20863
- execFileSync6("zip", ["-j", zipPath, ...files]);
20792
+ execFileSync7("zip", ["-j", zipPath, ...files]);
20864
20793
  }
20865
20794
  async function buildDiagnosticsZip(_exec = (cmd) => safeExec(cmd), _outDir = DIAGNOSTICS_DIR, _logDir = LOG_DIR, _zip = defaultZip) {
20866
20795
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 23);
20867
- const zipPath = path38.join(_outDir, `olam-diag-${ts}.zip`);
20868
- const tmpDir = fs34.mkdtempSync(path38.join(os20.tmpdir(), "olam-diag-"));
20796
+ const zipPath = path37.join(_outDir, `olam-diag-${ts}.zip`);
20797
+ const tmpDir = fs33.mkdtempSync(path37.join(os20.tmpdir(), "olam-diag-"));
20869
20798
  try {
20870
- fs34.mkdirSync(_outDir, { recursive: true });
20799
+ fs33.mkdirSync(_outDir, { recursive: true });
20871
20800
  const entries = [];
20872
20801
  const version = process.env["OLAM_CLI_VERSION"] ?? "unknown";
20873
20802
  const nodeVersion = process.version;
@@ -20883,14 +20812,14 @@ platform: ${platform}
20883
20812
  `uptime: ${os20.uptime()}s`
20884
20813
  ].join("\n") + "\n";
20885
20814
  _writeEntry(tmpDir, "os-info.txt", stripSecrets(osContent), entries);
20886
- const depsFile = path38.join(CACHE_DIR, "deps.json");
20887
- if (fs34.existsSync(depsFile)) {
20888
- const deps = fs34.readFileSync(depsFile, "utf-8");
20815
+ const depsFile = path37.join(CACHE_DIR, "deps.json");
20816
+ if (fs33.existsSync(depsFile)) {
20817
+ const deps = fs33.readFileSync(depsFile, "utf-8");
20889
20818
  _writeEntry(tmpDir, "deps.json", stripSecrets(deps), entries);
20890
20819
  }
20891
20820
  const latestLog = _latestLog(_logDir);
20892
20821
  if (latestLog) {
20893
- const lines = fs34.readFileSync(latestLog, "utf-8").split("\n");
20822
+ const lines = fs33.readFileSync(latestLog, "utf-8").split("\n");
20894
20823
  const tail = lines.slice(-LOG_TAIL_LINES).join("\n");
20895
20824
  _writeEntry(tmpDir, "log-tail.txt", stripSecrets(tail), entries);
20896
20825
  }
@@ -20902,38 +20831,38 @@ platform: ${platform}
20902
20831
  if (authAudit) {
20903
20832
  _writeEntry(tmpDir, "audit-auth-callers.txt", stripSecrets(authAudit), entries);
20904
20833
  }
20905
- const fileArgs = entries.map((e) => path38.join(tmpDir, e));
20834
+ const fileArgs = entries.map((e) => path37.join(tmpDir, e));
20906
20835
  try {
20907
20836
  _zip(zipPath, fileArgs);
20908
20837
  } catch (err) {
20909
20838
  throw new Error(`zip command produced no output file. zip stderr: ${err.message}`);
20910
20839
  }
20911
- if (!fs34.existsSync(zipPath)) {
20840
+ if (!fs33.existsSync(zipPath)) {
20912
20841
  throw new Error("zip command produced no output file.");
20913
20842
  }
20914
20843
  return { zipPath, entries };
20915
20844
  } finally {
20916
20845
  try {
20917
- fs34.rmSync(tmpDir, { recursive: true, force: true });
20846
+ fs33.rmSync(tmpDir, { recursive: true, force: true });
20918
20847
  } catch {
20919
20848
  }
20920
20849
  }
20921
20850
  }
20922
20851
  function _writeEntry(dir, name, content, entries) {
20923
- fs34.writeFileSync(path38.join(dir, name), content, { mode: 420 });
20852
+ fs33.writeFileSync(path37.join(dir, name), content, { mode: 420 });
20924
20853
  entries.push(name);
20925
20854
  }
20926
20855
  function _latestLog(logDir) {
20927
- if (!fs34.existsSync(logDir)) return null;
20928
- const files = fs34.readdirSync(logDir).filter((f) => f.startsWith("host-")).sort().reverse();
20929
- return files.length > 0 ? path38.join(logDir, files[0]) : null;
20856
+ if (!fs33.existsSync(logDir)) return null;
20857
+ const files = fs33.readdirSync(logDir).filter((f) => f.startsWith("host-")).sort().reverse();
20858
+ return files.length > 0 ? path37.join(logDir, files[0]) : null;
20930
20859
  }
20931
20860
  async function buildTelemetryPayload() {
20932
20861
  const channel = "stable";
20933
- const manifestFile = path38.join(CACHE_DIR, "manifest.json");
20862
+ const manifestFile = path37.join(CACHE_DIR, "manifest.json");
20934
20863
  let manifestAgeHours = null;
20935
- if (fs34.existsSync(manifestFile)) {
20936
- const mtime = fs34.statSync(manifestFile).mtime.getTime();
20864
+ if (fs33.existsSync(manifestFile)) {
20865
+ const mtime = fs33.statSync(manifestFile).mtime.getTime();
20937
20866
  manifestAgeHours = Math.round((Date.now() - mtime) / 36e5);
20938
20867
  }
20939
20868
  return {
@@ -20953,47 +20882,47 @@ function registerDiagnose(program2) {
20953
20882
  return;
20954
20883
  }
20955
20884
  if (!opts.quiet) {
20956
- console.log(pc20.cyan("Building diagnostics zip\u2026"));
20885
+ console.log(pc21.cyan("Building diagnostics zip\u2026"));
20957
20886
  }
20958
20887
  try {
20959
20888
  const { zipPath, entries } = await buildDiagnosticsZip();
20960
20889
  if (!opts.quiet) {
20961
- console.log(pc20.green(`Done: ${zipPath}`));
20962
- console.log(pc20.dim(`Contents: ${entries.join(", ")}`));
20890
+ console.log(pc21.green(`Done: ${zipPath}`));
20891
+ console.log(pc21.dim(`Contents: ${entries.join(", ")}`));
20963
20892
  }
20964
20893
  if (opts.upload) {
20965
- console.log(pc20.yellow(
20894
+ console.log(pc21.yellow(
20966
20895
  `Telemetry endpoint not yet provisioned. Share the zip manually:
20967
20896
  File: ${zipPath}
20968
20897
  See docs/runbooks/share-diagnostics.md for instructions.`
20969
20898
  ));
20970
20899
  }
20971
20900
  } catch (err) {
20972
- console.error(pc20.red(`Diagnose failed: ${err.message}`));
20901
+ console.error(pc21.red(`Diagnose failed: ${err.message}`));
20973
20902
  process.exitCode = 1;
20974
20903
  }
20975
20904
  });
20976
20905
  }
20977
20906
 
20978
20907
  // src/commands/update.ts
20979
- import * as fs37 from "node:fs";
20908
+ import * as fs36 from "node:fs";
20980
20909
  import * as os22 from "node:os";
20981
- import * as path41 from "node:path";
20910
+ import * as path40 from "node:path";
20982
20911
  import { execSync as execSync11 } from "node:child_process";
20983
- import pc21 from "picocolors";
20912
+ import pc22 from "picocolors";
20984
20913
 
20985
20914
  // src/lib/symlink-reconcile.ts
20986
- import * as fs35 from "node:fs";
20987
- import * as path39 from "node:path";
20915
+ import * as fs34 from "node:fs";
20916
+ import * as path38 from "node:path";
20988
20917
  var realFs = {
20989
- readdirSync: (p) => fs35.readdirSync(p),
20990
- existsSync: (p) => fs35.existsSync(p),
20991
- lstatSync: (p) => fs35.lstatSync(p),
20992
- readlinkSync: (p) => fs35.readlinkSync(p),
20993
- symlinkSync: (t, l) => fs35.symlinkSync(t, l),
20994
- unlinkSync: (p) => fs35.unlinkSync(p),
20918
+ readdirSync: (p) => fs34.readdirSync(p),
20919
+ existsSync: (p) => fs34.existsSync(p),
20920
+ lstatSync: (p) => fs34.lstatSync(p),
20921
+ readlinkSync: (p) => fs34.readlinkSync(p),
20922
+ symlinkSync: (t, l) => fs34.symlinkSync(t, l),
20923
+ unlinkSync: (p) => fs34.unlinkSync(p),
20995
20924
  mkdirSync: (p, o) => {
20996
- fs35.mkdirSync(p, o);
20925
+ fs34.mkdirSync(p, o);
20997
20926
  }
20998
20927
  };
20999
20928
  function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
@@ -21003,8 +20932,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
21003
20932
  _fs.mkdirSync(claudeSkillsDir, { recursive: true });
21004
20933
  const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
21005
20934
  for (const skill of sourceSkills) {
21006
- const linkPath = path39.join(claudeSkillsDir, skill);
21007
- const target = path39.join(npmSkillsDir, skill);
20935
+ const linkPath = path38.join(claudeSkillsDir, skill);
20936
+ const target = path38.join(npmSkillsDir, skill);
21008
20937
  if (!_fs.existsSync(linkPath)) {
21009
20938
  try {
21010
20939
  _fs.symlinkSync(target, linkPath);
@@ -21017,7 +20946,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
21017
20946
  }
21018
20947
  const deployedEntries = _fs.existsSync(claudeSkillsDir) ? _fs.readdirSync(claudeSkillsDir).filter((d) => d.startsWith("olam-")) : [];
21019
20948
  for (const entry of deployedEntries) {
21020
- const linkPath = path39.join(claudeSkillsDir, entry);
20949
+ const linkPath = path38.join(claudeSkillsDir, entry);
21021
20950
  let isSymlink = false;
21022
20951
  try {
21023
20952
  isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
@@ -21042,9 +20971,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
21042
20971
 
21043
20972
  // src/commands/update.ts
21044
20973
  var PACKAGE_NAME = "@pleri/olam-cli";
21045
- var CACHE_DIR2 = path41.join(os22.homedir(), ".olam", "cache");
21046
- var LOG_DIR2 = path41.join(os22.homedir(), ".olam", "log");
21047
- var LAST_STABLE_FILE = path41.join(CACHE_DIR2, "last-stable.txt");
20974
+ var CACHE_DIR2 = path40.join(os22.homedir(), ".olam", "cache");
20975
+ var LOG_DIR2 = path40.join(os22.homedir(), ".olam", "log");
20976
+ var LAST_STABLE_FILE = path40.join(CACHE_DIR2, "last-stable.txt");
21048
20977
  function defaultExec(cmd) {
21049
20978
  try {
21050
20979
  const stdout = execSync11(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
@@ -21066,22 +20995,22 @@ function getCurrentVersion(_exec = defaultExec) {
21066
20995
  }
21067
20996
  function readLastStable(file = LAST_STABLE_FILE) {
21068
20997
  try {
21069
- const v = fs37.readFileSync(file, "utf-8").trim();
20998
+ const v = fs36.readFileSync(file, "utf-8").trim();
21070
20999
  return v || null;
21071
21000
  } catch {
21072
21001
  return null;
21073
21002
  }
21074
21003
  }
21075
21004
  function writeLastStable(version, file = LAST_STABLE_FILE) {
21076
- fs37.mkdirSync(path41.dirname(file), { recursive: true });
21077
- fs37.writeFileSync(file, version, { mode: 420 });
21005
+ fs36.mkdirSync(path40.dirname(file), { recursive: true });
21006
+ fs36.writeFileSync(file, version, { mode: 420 });
21078
21007
  }
21079
21008
  function logUpdateFailure(stderr) {
21080
21009
  const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
21081
- const logFile = path41.join(LOG_DIR2, `update-${ts}.log`);
21010
+ const logFile = path40.join(LOG_DIR2, `update-${ts}.log`);
21082
21011
  try {
21083
- fs37.mkdirSync(LOG_DIR2, { recursive: true });
21084
- fs37.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
21012
+ fs36.mkdirSync(LOG_DIR2, { recursive: true });
21013
+ fs36.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
21085
21014
  ${stderr}
21086
21015
  `, "utf-8");
21087
21016
  } catch {
@@ -21132,52 +21061,52 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
21132
21061
  writeLastStable(prevVersion);
21133
21062
  }
21134
21063
  if (!quiet) {
21135
- console.log(pc21.cyan(`Installing ${PACKAGE_NAME}@${channel}\u2026`));
21064
+ console.log(pc22.cyan(`Installing ${PACKAGE_NAME}@${channel}\u2026`));
21136
21065
  }
21137
21066
  const installResult = _exec(`npm install -g ${PACKAGE_NAME}@${channel}`);
21138
21067
  if (installResult.exitCode !== 0) {
21139
21068
  logUpdateFailure(installResult.stderr);
21140
21069
  if (!quiet) {
21141
- console.error(pc21.red("Update failed."));
21070
+ console.error(pc22.red("Update failed."));
21142
21071
  }
21143
21072
  const prev = readLastStable();
21144
21073
  if (prev) {
21145
21074
  if (!quiet) {
21146
- console.log(pc21.yellow(`Restoring to ${prev}\u2026`));
21075
+ console.log(pc22.yellow(`Restoring to ${prev}\u2026`));
21147
21076
  }
21148
21077
  const restoreResult = _exec(`npm install -g ${PACKAGE_NAME}@${prev}`);
21149
21078
  if (restoreResult.exitCode !== 0) {
21150
21079
  if (!quiet) {
21151
- console.error(pc21.red(
21080
+ console.error(pc22.red(
21152
21081
  `Restore also failed. Run: npm install -g ${PACKAGE_NAME}@${prev} manually.`
21153
21082
  ));
21154
21083
  }
21155
21084
  } else if (!quiet) {
21156
- console.log(pc21.yellow(`Restored to ${prev}.`));
21085
+ console.log(pc22.yellow(`Restored to ${prev}.`));
21157
21086
  }
21158
21087
  } else if (!quiet) {
21159
- console.error(pc21.red("No previous version cached; cannot auto-restore."));
21088
+ console.error(pc22.red("No previous version cached; cannot auto-restore."));
21160
21089
  }
21161
21090
  return { action: "restored", prevVersion: prev ?? void 0, exitCode: 11 };
21162
21091
  }
21163
21092
  const newVersion = getCurrentVersion(_exec) ?? void 0;
21164
21093
  if (!quiet && newVersion) {
21165
- console.log(pc21.green(`Updated to ${newVersion}.`));
21094
+ console.log(pc22.green(`Updated to ${newVersion}.`));
21166
21095
  }
21167
21096
  const npmRootResult = _getNpmRoot("npm root -g");
21168
21097
  let symlinkResult = { added: [], removed: [] };
21169
21098
  if (npmRootResult.exitCode === 0) {
21170
21099
  const npmRoot = npmRootResult.stdout.trim();
21171
- const npmSkillsDir = path41.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
21172
- const claudeSkillsDir = path41.join(os22.homedir(), ".claude", "skills");
21100
+ const npmSkillsDir = path40.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
21101
+ const claudeSkillsDir = path40.join(os22.homedir(), ".claude", "skills");
21173
21102
  const rec = _reconcile(npmSkillsDir, claudeSkillsDir);
21174
21103
  symlinkResult = { added: rec.added, removed: rec.removed };
21175
21104
  if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
21176
21105
  if (rec.added.length > 0) {
21177
- console.log(pc21.dim(`Skills added: ${rec.added.join(", ")}`));
21106
+ console.log(pc22.dim(`Skills added: ${rec.added.join(", ")}`));
21178
21107
  }
21179
21108
  if (rec.removed.length > 0) {
21180
- console.log(pc21.dim(`Skills removed (dangling): ${rec.removed.join(", ")}`));
21109
+ console.log(pc22.dim(`Skills removed (dangling): ${rec.removed.join(", ")}`));
21181
21110
  }
21182
21111
  }
21183
21112
  }
@@ -21215,8 +21144,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
21215
21144
  if (npmRootResult.exitCode === 0) {
21216
21145
  const npmRoot = npmRootResult.stdout.trim();
21217
21146
  _reconcile(
21218
- path41.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
21219
- path41.join(os22.homedir(), ".claude", "skills")
21147
+ path40.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
21148
+ path40.join(os22.homedir(), ".claude", "skills")
21220
21149
  );
21221
21150
  }
21222
21151
  return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
@@ -21271,7 +21200,7 @@ function registerUpdate(program2) {
21271
21200
  // src/commands/begin.ts
21272
21201
  init_host_cp();
21273
21202
  init_open_url();
21274
- import pc22 from "picocolors";
21203
+ import pc23 from "picocolors";
21275
21204
  async function doBegin(opts, _startFn = startHostCp, _openFn = openUrl) {
21276
21205
  const prevExitCode = process.exitCode;
21277
21206
  await _startFn({ showToken: opts.showToken });
@@ -21281,7 +21210,7 @@ async function doBegin(opts, _startFn = startHostCp, _openFn = openUrl) {
21281
21210
  const token = readToken();
21282
21211
  if (token) {
21283
21212
  const base = `http://127.0.0.1:${HOST_CP_PORT}/`;
21284
- console.log(pc22.dim(`Opening ${base}`));
21213
+ console.log(pc23.dim(`Opening ${base}`));
21285
21214
  _openFn(`${base}?token=${token}`);
21286
21215
  }
21287
21216
  }
@@ -21377,8 +21306,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
21377
21306
  function authHeaders() {
21378
21307
  return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
21379
21308
  }
21380
- async function apiFetch(path45, init = {}) {
21381
- const res = await fetch(`${BASE_URL}${path45}`, {
21309
+ async function apiFetch(path44, init = {}) {
21310
+ const res = await fetch(`${BASE_URL}${path44}`, {
21382
21311
  ...init,
21383
21312
  headers: {
21384
21313
  "Content-Type": "application/json",
@@ -21530,7 +21459,7 @@ function registerMcpAdd(cmd) {
21530
21459
 
21531
21460
  // src/commands/mcp/list.ts
21532
21461
  init_output();
21533
- import pc23 from "picocolors";
21462
+ import pc24 from "picocolors";
21534
21463
  function registerMcpList(cmd) {
21535
21464
  cmd.command("list").description("List all registered MCP credentials").action(async () => {
21536
21465
  const client = getMcpAuthClient();
@@ -21545,8 +21474,8 @@ function registerMcpList(cmd) {
21545
21474
  }
21546
21475
  const mcps = data.mcps ?? [];
21547
21476
  if (mcps.length === 0) {
21548
- console.log(pc23.dim("No MCP credentials registered."));
21549
- console.log(pc23.dim("Add one with: olam mcp add <service>"));
21477
+ console.log(pc24.dim("No MCP credentials registered."));
21478
+ console.log(pc24.dim("Add one with: olam mcp add <service>"));
21550
21479
  return;
21551
21480
  }
21552
21481
  const [c0, c1, c2, c3] = [16, 20, 10, 24];
@@ -21557,12 +21486,12 @@ function registerMcpList(cmd) {
21557
21486
  "ENV VAR".padEnd(c3),
21558
21487
  "STATUS"
21559
21488
  ].join(" ");
21560
- console.log(pc23.dim(header));
21561
- console.log(pc23.dim("\u2500".repeat(header.length)));
21489
+ console.log(pc24.dim(header));
21490
+ console.log(pc24.dim("\u2500".repeat(header.length)));
21562
21491
  for (const m of mcps) {
21563
- const status = !m.validated ? pc23.yellow("unvalidated") : m.expired ? pc23.red("expired") : pc23.green("active");
21492
+ const status = !m.validated ? pc24.yellow("unvalidated") : m.expired ? pc24.red("expired") : pc24.green("active");
21564
21493
  const row = [
21565
- pc23.cyan(m.service.padEnd(c0)),
21494
+ pc24.cyan(m.service.padEnd(c0)),
21566
21495
  m.label.padEnd(c1).slice(0, c1),
21567
21496
  m.type.padEnd(c2),
21568
21497
  (m.envName ?? "\u2014").padEnd(c3).slice(0, c3),
@@ -21590,13 +21519,13 @@ function registerMcpRemove(cmd) {
21590
21519
 
21591
21520
  // src/commands/mcp/status.ts
21592
21521
  init_output();
21593
- import pc24 from "picocolors";
21522
+ import pc25 from "picocolors";
21594
21523
  function formatExpiry(expiresAt) {
21595
21524
  if (!expiresAt) return "\u2014";
21596
21525
  const ms = expiresAt - Date.now();
21597
- if (ms <= 0) return pc24.red("expired");
21526
+ if (ms <= 0) return pc25.red("expired");
21598
21527
  const hours = ms / (1e3 * 60 * 60);
21599
- if (hours < 1) return pc24.yellow(`${Math.ceil(ms / 6e4)}m`);
21528
+ if (hours < 1) return pc25.yellow(`${Math.ceil(ms / 6e4)}m`);
21600
21529
  return `${hours.toFixed(1)}h`;
21601
21530
  }
21602
21531
  function registerMcpStatus(cmd) {
@@ -21613,14 +21542,14 @@ function registerMcpStatus(cmd) {
21613
21542
  const mcps = data.mcps ?? [];
21614
21543
  printHeader(`MCP Credentials (${mcps.length})`);
21615
21544
  if (mcps.length === 0) {
21616
- console.log(pc24.dim("No credentials registered."));
21545
+ console.log(pc25.dim("No credentials registered."));
21617
21546
  return;
21618
21547
  }
21619
21548
  for (const m of mcps) {
21620
- const stateColor = !m.validated ? pc24.yellow : m.expired ? pc24.red : pc24.green;
21549
+ const stateColor = !m.validated ? pc25.yellow : m.expired ? pc25.red : pc25.green;
21621
21550
  const stateLabel = !m.validated ? "unvalidated" : m.expired ? "expired" : "active";
21622
21551
  console.log(`
21623
- ${pc24.cyan(m.service)} ${stateColor(`[${stateLabel}]`)}`);
21552
+ ${pc25.cyan(m.service)} ${stateColor(`[${stateLabel}]`)}`);
21624
21553
  console.log(` label: ${m.label}`);
21625
21554
  console.log(` type: ${m.type}`);
21626
21555
  if (m.envName) console.log(` env var: ${m.envName}`);
@@ -21635,15 +21564,15 @@ function registerMcpStatus(cmd) {
21635
21564
  // src/commands/mcp/import.ts
21636
21565
  init_output();
21637
21566
  import * as readline3 from "node:readline";
21638
- import pc25 from "picocolors";
21567
+ import pc26 from "picocolors";
21639
21568
 
21640
21569
  // src/commands/mcp/import-discovery.ts
21641
- import * as fs38 from "node:fs";
21570
+ import * as fs37 from "node:fs";
21642
21571
  import * as os23 from "node:os";
21643
- import * as path42 from "node:path";
21572
+ import * as path41 from "node:path";
21644
21573
  function readJsonFile(filePath) {
21645
21574
  try {
21646
- const raw = fs38.readFileSync(filePath, "utf-8");
21575
+ const raw = fs37.readFileSync(filePath, "utf-8");
21647
21576
  return JSON.parse(raw);
21648
21577
  } catch {
21649
21578
  return null;
@@ -21672,24 +21601,24 @@ function extractMcpServers(obj, source, sourceLabel) {
21672
21601
  }
21673
21602
  function getClaudeDesktopPath() {
21674
21603
  if (process.platform === "darwin") {
21675
- return path42.join(os23.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
21604
+ return path41.join(os23.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
21676
21605
  }
21677
21606
  if (process.platform === "win32") {
21678
- const appData = process.env["APPDATA"] ?? path42.join(os23.homedir(), "AppData", "Roaming");
21679
- return path42.join(appData, "Claude", "claude_desktop_config.json");
21607
+ const appData = process.env["APPDATA"] ?? path41.join(os23.homedir(), "AppData", "Roaming");
21608
+ return path41.join(appData, "Claude", "claude_desktop_config.json");
21680
21609
  }
21681
- return path42.join(os23.homedir(), ".config", "Claude", "claude_desktop_config.json");
21610
+ return path41.join(os23.homedir(), ".config", "Claude", "claude_desktop_config.json");
21682
21611
  }
21683
21612
  function getOlamRepoPaths() {
21684
21613
  const configPaths = [
21685
- path42.join(os23.homedir(), ".olam", "config.yaml"),
21686
- path42.join(process.cwd(), ".olam", "config.yaml")
21614
+ path41.join(os23.homedir(), ".olam", "config.yaml"),
21615
+ path41.join(process.cwd(), ".olam", "config.yaml")
21687
21616
  ];
21688
21617
  const paths = [];
21689
21618
  for (const configPath of configPaths) {
21690
- if (!fs38.existsSync(configPath)) continue;
21619
+ if (!fs37.existsSync(configPath)) continue;
21691
21620
  try {
21692
- const raw = fs38.readFileSync(configPath, "utf-8");
21621
+ const raw = fs37.readFileSync(configPath, "utf-8");
21693
21622
  const repoMatches = [...raw.matchAll(/path:\s*["']?([^\s"'\n]+)/g)];
21694
21623
  for (const m of repoMatches) {
21695
21624
  if (m[1]) paths.push(m[1]);
@@ -21705,7 +21634,7 @@ async function discoverMcpSources(repoPaths) {
21705
21634
  const sources = [];
21706
21635
  const sourceDefs = [
21707
21636
  {
21708
- path: path42.join(os23.homedir(), ".claude.json"),
21637
+ path: path41.join(os23.homedir(), ".claude.json"),
21709
21638
  label: "Claude Code (~/.claude.json)"
21710
21639
  },
21711
21640
  {
@@ -21713,19 +21642,19 @@ async function discoverMcpSources(repoPaths) {
21713
21642
  label: "Claude Desktop"
21714
21643
  },
21715
21644
  {
21716
- path: path42.join(os23.homedir(), ".cursor", "mcp.json"),
21645
+ path: path41.join(os23.homedir(), ".cursor", "mcp.json"),
21717
21646
  label: "Cursor (~/.cursor/mcp.json)"
21718
21647
  },
21719
21648
  {
21720
- path: path42.join(os23.homedir(), ".codeium", "windsurf", "mcp_config.json"),
21649
+ path: path41.join(os23.homedir(), ".codeium", "windsurf", "mcp_config.json"),
21721
21650
  label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
21722
21651
  }
21723
21652
  ];
21724
21653
  const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
21725
21654
  for (const repoPath of resolvedRepoPaths) {
21726
21655
  sourceDefs.push({
21727
- path: path42.join(repoPath, ".mcp.json"),
21728
- label: `.mcp.json (${path42.basename(repoPath)})`
21656
+ path: path41.join(repoPath, ".mcp.json"),
21657
+ label: `.mcp.json (${path41.basename(repoPath)})`
21729
21658
  });
21730
21659
  }
21731
21660
  const reads = await Promise.all(
@@ -21805,13 +21734,13 @@ async function validateMcpEntry(entry) {
21805
21734
  // src/commands/mcp/import.ts
21806
21735
  async function multiSelectPicker(entries) {
21807
21736
  if (entries.length === 0) return [];
21808
- console.log("\n" + pc25.bold("Discovered MCP servers:"));
21737
+ console.log("\n" + pc26.bold("Discovered MCP servers:"));
21809
21738
  entries.forEach((e, i) => {
21810
21739
  console.log(
21811
- ` ${pc25.dim(`[${i + 1}]`)} ${pc25.cyan(e.name.padEnd(20))} ${pc25.dim(e.sourceLabel)}`
21740
+ ` ${pc26.dim(`[${i + 1}]`)} ${pc26.cyan(e.name.padEnd(20))} ${pc26.dim(e.sourceLabel)}`
21812
21741
  );
21813
21742
  });
21814
- console.log("\n" + pc25.dim('Enter numbers to import (e.g. 1,2,3 or "all" or Enter to skip):'));
21743
+ console.log("\n" + pc26.dim('Enter numbers to import (e.g. 1,2,3 or "all" or Enter to skip):'));
21815
21744
  const answer = await new Promise((resolve8) => {
21816
21745
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
21817
21746
  rl.question("> ", (ans) => {
@@ -21838,7 +21767,7 @@ function registerMcpImport(cmd) {
21838
21767
  const repoPaths = opts.repoPaths ? opts.repoPaths.split(",").map((s) => s.trim()) : void 0;
21839
21768
  const { entries, sources, durationMs } = await discoverMcpSources(repoPaths);
21840
21769
  if (entries.length === 0) {
21841
- console.log(pc25.dim("No MCP servers found in any source path."));
21770
+ console.log(pc26.dim("No MCP servers found in any source path."));
21842
21771
  return;
21843
21772
  }
21844
21773
  printInfo("Sources", sources.length > 0 ? sources.join(", ") : "none");
@@ -21851,15 +21780,15 @@ function registerMcpImport(cmd) {
21851
21780
  candidates = filtered;
21852
21781
  }
21853
21782
  if (skippedCount > 0) {
21854
- console.log(pc25.dim(`skipped: ${skippedCount} already registered`));
21783
+ console.log(pc26.dim(`skipped: ${skippedCount} already registered`));
21855
21784
  }
21856
21785
  if (candidates.length === 0) {
21857
- console.log(pc25.dim("Nothing new to import. Use --reimport to force."));
21786
+ console.log(pc26.dim("Nothing new to import. Use --reimport to force."));
21858
21787
  return;
21859
21788
  }
21860
21789
  const selected = await multiSelectPicker(candidates);
21861
21790
  if (selected.length === 0) {
21862
- console.log(pc25.dim("No servers selected."));
21791
+ console.log(pc26.dim("No servers selected."));
21863
21792
  return;
21864
21793
  }
21865
21794
  console.log(`
@@ -21870,16 +21799,16 @@ Importing ${selected.length} server(s)\u2026`);
21870
21799
  let validated = false;
21871
21800
  let validationReason = "skipped";
21872
21801
  if (opts.validate !== false) {
21873
- process.stdout.write(` ${pc25.dim("\u2192")} ${entry.name} validating\u2026 `);
21802
+ process.stdout.write(` ${pc26.dim("\u2192")} ${entry.name} validating\u2026 `);
21874
21803
  const vr = await validateMcpEntry(entry);
21875
21804
  validated = vr.validated;
21876
21805
  validationReason = vr.reason;
21877
21806
  process.stdout.write(
21878
- validated ? pc25.green("ok\n") : pc25.yellow(`unvalidated (${vr.reason})
21807
+ validated ? pc26.green("ok\n") : pc26.yellow(`unvalidated (${vr.reason})
21879
21808
  `)
21880
21809
  );
21881
21810
  } else {
21882
- console.log(` ${pc25.dim("\u2192")} ${entry.name} ${pc25.dim("(validation skipped)")}`);
21811
+ console.log(` ${pc26.dim("\u2192")} ${entry.name} ${pc26.dim("(validation skipped)")}`);
21883
21812
  }
21884
21813
  if (validated) validatedCount++;
21885
21814
  const result = await client.staticAdd({
@@ -21894,21 +21823,21 @@ Importing ${selected.length} server(s)\u2026`);
21894
21823
  }
21895
21824
  }
21896
21825
  console.log("");
21897
- console.log(pc25.green(`\u2713 Imported ${importedCount}/${selected.length}`));
21826
+ console.log(pc26.green(`\u2713 Imported ${importedCount}/${selected.length}`));
21898
21827
  if (validatedCount > 0) {
21899
- console.log(pc25.dim(` ${validatedCount} validated, ${importedCount - validatedCount} unvalidated`));
21828
+ console.log(pc26.dim(` ${validatedCount} validated, ${importedCount - validatedCount} unvalidated`));
21900
21829
  }
21901
21830
  });
21902
21831
  }
21903
21832
 
21904
21833
  // src/commands/mcp/revoke.ts
21905
21834
  init_output();
21906
- import pc26 from "picocolors";
21835
+ import pc27 from "picocolors";
21907
21836
  function registerMcpRevoke(cmd) {
21908
21837
  cmd.command("revoke <user> <world> <service>").description("Revoke a user's MCP service entitlement (multi-tenant mode only)").action(async (user, world, service) => {
21909
21838
  const multiTenant = (process.env["OLAM_MCP_MULTI_TENANT"] ?? "").toLowerCase() === "true";
21910
21839
  if (!multiTenant) {
21911
- console.warn(pc26.yellow("\u26A0 revocation only meaningful in multi_tenant mode \u2014 no-op"));
21840
+ console.warn(pc27.yellow("\u26A0 revocation only meaningful in multi_tenant mode \u2014 no-op"));
21912
21841
  return;
21913
21842
  }
21914
21843
  const baseUrl = process.env["OLAM_MCP_AUTH_SERVICE_URL"] ?? "http://127.0.0.1:9998";
@@ -21937,8 +21866,8 @@ function registerMcpRevoke(cmd) {
21937
21866
  process.exitCode = 1;
21938
21867
  return;
21939
21868
  }
21940
- console.log(pc26.green(`\u2713 Revoked: ${user} / ${world} / ${service}`));
21941
- console.log(pc26.dim(" Next fetch-creds call returns 403; token cleared on next merge."));
21869
+ console.log(pc27.green(`\u2713 Revoked: ${user} / ${world} / ${service}`));
21870
+ console.log(pc27.dim(" Next fetch-creds call returns 403; token cleared on next merge."));
21942
21871
  });
21943
21872
  }
21944
21873
 
@@ -21955,18 +21884,18 @@ function registerMcp(program2) {
21955
21884
  }
21956
21885
 
21957
21886
  // src/pleri-config.ts
21958
- import * as fs39 from "node:fs";
21959
- import * as path43 from "node:path";
21887
+ import * as fs38 from "node:fs";
21888
+ import * as path42 from "node:path";
21960
21889
  function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
21961
21890
  if (process.env.PLERI_BASE_URL) {
21962
21891
  return true;
21963
21892
  }
21964
- const configPath = path43.join(configDir, "config.yaml");
21965
- if (!fs39.existsSync(configPath)) {
21893
+ const configPath = path42.join(configDir, "config.yaml");
21894
+ if (!fs38.existsSync(configPath)) {
21966
21895
  return false;
21967
21896
  }
21968
21897
  try {
21969
- const contents = fs39.readFileSync(configPath, "utf8");
21898
+ const contents = fs38.readFileSync(configPath, "utf8");
21970
21899
  return /^[^#\n]*\bpleri:/m.test(contents);
21971
21900
  } catch {
21972
21901
  return false;
@@ -21977,14 +21906,14 @@ function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
21977
21906
  var program = new Command();
21978
21907
  function readCliVersion() {
21979
21908
  try {
21980
- const here = path44.dirname(fileURLToPath4(import.meta.url));
21909
+ const here = path43.dirname(fileURLToPath4(import.meta.url));
21981
21910
  for (const candidate of [
21982
- path44.join(here, "package.json"),
21983
- path44.join(here, "..", "package.json"),
21984
- path44.join(here, "..", "..", "package.json")
21911
+ path43.join(here, "package.json"),
21912
+ path43.join(here, "..", "package.json"),
21913
+ path43.join(here, "..", "..", "package.json")
21985
21914
  ]) {
21986
- if (fs40.existsSync(candidate)) {
21987
- const pkg = JSON.parse(fs40.readFileSync(candidate, "utf-8"));
21915
+ if (fs39.existsSync(candidate)) {
21916
+ const pkg = JSON.parse(fs39.readFileSync(candidate, "utf-8"));
21988
21917
  if (typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;
21989
21918
  }
21990
21919
  }
@@ -22023,4 +21952,5 @@ registerBegin(program);
22023
21952
  registerStop(program);
22024
21953
  registerWorldUpgrade(program);
22025
21954
  registerMcp(program);
21955
+ registerServices(program);
22026
21956
  program.parse();