@pleri/olam-cli 0.1.168 → 0.1.170

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 (64) hide show
  1. package/README.md +38 -0
  2. package/dist/commands/auth-status.d.ts +1 -0
  3. package/dist/commands/auth-status.d.ts.map +1 -1
  4. package/dist/commands/auth-status.js +45 -4
  5. package/dist/commands/auth-status.js.map +1 -1
  6. package/dist/commands/create.d.ts.map +1 -1
  7. package/dist/commands/create.js +26 -0
  8. package/dist/commands/create.js.map +1 -1
  9. package/dist/commands/enter.d.ts.map +1 -1
  10. package/dist/commands/enter.js +5 -0
  11. package/dist/commands/enter.js.map +1 -1
  12. package/dist/commands/resume.d.ts +63 -0
  13. package/dist/commands/resume.d.ts.map +1 -0
  14. package/dist/commands/resume.js +174 -0
  15. package/dist/commands/resume.js.map +1 -0
  16. package/dist/commands/setup.d.ts +19 -0
  17. package/dist/commands/setup.d.ts.map +1 -1
  18. package/dist/commands/setup.js +157 -19
  19. package/dist/commands/setup.js.map +1 -1
  20. package/dist/image-digests.json +8 -8
  21. package/dist/index.js +1021 -576
  22. package/dist/index.js.map +1 -1
  23. package/dist/lib/health-probes.d.ts +28 -0
  24. package/dist/lib/health-probes.d.ts.map +1 -1
  25. package/dist/lib/health-probes.js +75 -0
  26. package/dist/lib/health-probes.js.map +1 -1
  27. package/dist/lib/k8s-context-discovery.d.ts +80 -0
  28. package/dist/lib/k8s-context-discovery.d.ts.map +1 -0
  29. package/dist/lib/k8s-context-discovery.js +102 -0
  30. package/dist/lib/k8s-context-discovery.js.map +1 -0
  31. package/dist/mcp-server.js +1273 -771
  32. package/dist/spawn/home-override.d.ts +82 -0
  33. package/dist/spawn/home-override.d.ts.map +1 -0
  34. package/dist/spawn/home-override.js +107 -0
  35. package/dist/spawn/home-override.js.map +1 -0
  36. package/hermes-bundle/version.json +1 -1
  37. package/host-cp/k8s/manifests/30-configmap.yaml +5 -0
  38. package/host-cp/k8s/manifests/50-deployment.yaml +9 -2
  39. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
  40. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
  41. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
  42. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
  43. package/host-cp/lifecycle/classify.mjs +110 -0
  44. package/host-cp/lifecycle/emit.mjs +119 -0
  45. package/host-cp/lifecycle/evidence.mjs +45 -0
  46. package/host-cp/lifecycle/failure-kinds.mjs +56 -0
  47. package/host-cp/lifecycle/index.mjs +22 -0
  48. package/host-cp/lifecycle/phases.mjs +52 -0
  49. package/host-cp/observability/grafana-port-forward.sh +1 -1
  50. package/host-cp/observability/kyverno-cardinality-mutate.sh +2 -2
  51. package/host-cp/observability/loki-ingest.sh +1 -1
  52. package/host-cp/observability/ndjson-span-sink.mjs +131 -0
  53. package/host-cp/observability/prom-no-double-grafana.sh +4 -4
  54. package/host-cp/observability/redactor.mjs +72 -0
  55. package/host-cp/recovery/engine.mjs +148 -0
  56. package/host-cp/recovery/index.mjs +16 -0
  57. package/host-cp/recovery/ledger.mjs +105 -0
  58. package/host-cp/recovery/recipes.mjs +46 -0
  59. package/host-cp/recovery/scenarios.mjs +124 -0
  60. package/host-cp/recovery/step-runners.mjs +263 -0
  61. package/host-cp/src/docker-events.mjs +30 -6
  62. package/host-cp/src/pr-nanny.mjs +55 -3
  63. package/host-cp/src/server.mjs +173 -0
  64. package/package.json +1 -1
@@ -445,8 +445,8 @@ var init_parseUtil = __esm({
445
445
  init_errors();
446
446
  init_en();
447
447
  makeIssue = (params) => {
448
- const { data, path: path52, errorMaps, issueData } = params;
449
- const fullPath = [...path52, ...issueData.path || []];
448
+ const { data, path: path53, errorMaps, issueData } = params;
449
+ const fullPath = [...path53, ...issueData.path || []];
450
450
  const fullIssue = {
451
451
  ...issueData,
452
452
  path: fullPath
@@ -754,11 +754,11 @@ var init_types = __esm({
754
754
  init_parseUtil();
755
755
  init_util();
756
756
  ParseInputLazyPath = class {
757
- constructor(parent, value, path52, key) {
757
+ constructor(parent, value, path53, key) {
758
758
  this._cachedPath = [];
759
759
  this.parent = parent;
760
760
  this.data = value;
761
- this._path = path52;
761
+ this._path = path53;
762
762
  this._key = key;
763
763
  }
764
764
  get path() {
@@ -7090,7 +7090,7 @@ var require_compile = __commonJS({
7090
7090
  const schOrFunc = root.refs[ref];
7091
7091
  if (schOrFunc)
7092
7092
  return schOrFunc;
7093
- let _sch = resolve14.call(this, root, ref);
7093
+ let _sch = resolve15.call(this, root, ref);
7094
7094
  if (_sch === void 0) {
7095
7095
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
7096
7096
  const { schemaId } = this.opts;
@@ -7117,7 +7117,7 @@ var require_compile = __commonJS({
7117
7117
  function sameSchemaEnv(s1, s2) {
7118
7118
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
7119
7119
  }
7120
- function resolve14(root, ref) {
7120
+ function resolve15(root, ref) {
7121
7121
  let sch;
7122
7122
  while (typeof (sch = this.refs[ref]) == "string")
7123
7123
  ref = sch;
@@ -7332,8 +7332,8 @@ var require_utils = __commonJS({
7332
7332
  }
7333
7333
  return ind;
7334
7334
  }
7335
- function removeDotSegments(path52) {
7336
- let input = path52;
7335
+ function removeDotSegments(path53) {
7336
+ let input = path53;
7337
7337
  const output = [];
7338
7338
  let nextSlash = -1;
7339
7339
  let len = 0;
@@ -7532,8 +7532,8 @@ var require_schemes = __commonJS({
7532
7532
  wsComponent.secure = void 0;
7533
7533
  }
7534
7534
  if (wsComponent.resourceName) {
7535
- const [path52, query] = wsComponent.resourceName.split("?");
7536
- wsComponent.path = path52 && path52 !== "/" ? path52 : void 0;
7535
+ const [path53, query] = wsComponent.resourceName.split("?");
7536
+ wsComponent.path = path53 && path53 !== "/" ? path53 : void 0;
7537
7537
  wsComponent.query = query;
7538
7538
  wsComponent.resourceName = void 0;
7539
7539
  }
@@ -7692,7 +7692,7 @@ var require_fast_uri = __commonJS({
7692
7692
  }
7693
7693
  return uri;
7694
7694
  }
7695
- function resolve14(baseURI, relativeURI, options) {
7695
+ function resolve15(baseURI, relativeURI, options) {
7696
7696
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
7697
7697
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
7698
7698
  schemelessOptions.skipEscape = true;
@@ -7919,7 +7919,7 @@ var require_fast_uri = __commonJS({
7919
7919
  var fastUri = {
7920
7920
  SCHEMES,
7921
7921
  normalize,
7922
- resolve: resolve14,
7922
+ resolve: resolve15,
7923
7923
  resolveComponent,
7924
7924
  equal,
7925
7925
  serialize,
@@ -10895,12 +10895,12 @@ var require_dist = __commonJS({
10895
10895
  throw new Error(`Unknown format "${name}"`);
10896
10896
  return f;
10897
10897
  };
10898
- function addFormats(ajv, list, fs51, exportName) {
10898
+ function addFormats(ajv, list, fs52, exportName) {
10899
10899
  var _a3;
10900
10900
  var _b;
10901
10901
  (_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
10902
10902
  for (const f of list)
10903
- ajv.addFormat(f, fs51[f]);
10903
+ ajv.addFormat(f, fs52[f]);
10904
10904
  }
10905
10905
  module.exports = exports = formatsPlugin;
10906
10906
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -11008,7 +11008,7 @@ import YAML from "yaml";
11008
11008
  function bootstrapStepCmd(entry) {
11009
11009
  return typeof entry === "string" ? entry : entry.cmd;
11010
11010
  }
11011
- function refineForbiddenKeys(value, path52, ctx, rejectSource) {
11011
+ function refineForbiddenKeys(value, path53, ctx, rejectSource) {
11012
11012
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
11013
11013
  return;
11014
11014
  }
@@ -11016,12 +11016,12 @@ function refineForbiddenKeys(value, path52, ctx, rejectSource) {
11016
11016
  if (FORBIDDEN_KEYS.has(key)) {
11017
11017
  ctx.addIssue({
11018
11018
  code: external_exports.ZodIssueCode.custom,
11019
- path: [...path52, key],
11019
+ path: [...path53, key],
11020
11020
  message: `forbidden key "${key}" (prototype-pollution surface)`
11021
11021
  });
11022
11022
  continue;
11023
11023
  }
11024
- if (rejectSource && path52.length === 0 && key === "source") {
11024
+ if (rejectSource && path53.length === 0 && key === "source") {
11025
11025
  ctx.addIssue({
11026
11026
  code: external_exports.ZodIssueCode.custom,
11027
11027
  path: ["source"],
@@ -11029,21 +11029,21 @@ function refineForbiddenKeys(value, path52, ctx, rejectSource) {
11029
11029
  });
11030
11030
  continue;
11031
11031
  }
11032
- refineForbiddenKeys(value[key], [...path52, key], ctx, false);
11032
+ refineForbiddenKeys(value[key], [...path53, key], ctx, false);
11033
11033
  }
11034
11034
  }
11035
- function rejectForbiddenKeys(value, path52, rejectSource) {
11035
+ function rejectForbiddenKeys(value, path53, rejectSource) {
11036
11036
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
11037
11037
  return;
11038
11038
  }
11039
11039
  for (const key of Object.keys(value)) {
11040
11040
  if (FORBIDDEN_KEYS.has(key)) {
11041
- throw new Error(`[manifest] ${path52}: forbidden key "${key}" (prototype-pollution surface)`);
11041
+ throw new Error(`[manifest] ${path53}: forbidden key "${key}" (prototype-pollution surface)`);
11042
11042
  }
11043
11043
  if (rejectSource && key === "source") {
11044
- throw new Error(`[manifest] ${path52}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11044
+ throw new Error(`[manifest] ${path53}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11045
11045
  }
11046
- rejectForbiddenKeys(value[key], `${path52}.${key}`, false);
11046
+ rejectForbiddenKeys(value[key], `${path53}.${key}`, false);
11047
11047
  }
11048
11048
  }
11049
11049
  function unknownTopLevelKeys(parsed) {
@@ -11080,8 +11080,8 @@ function loadRepoManifest(repoDir) {
11080
11080
  } else {
11081
11081
  return null;
11082
11082
  }
11083
- const stat = lstatSync(manifestPath2);
11084
- if (stat.isSymbolicLink()) {
11083
+ const stat2 = lstatSync(manifestPath2);
11084
+ if (stat2.isSymbolicLink()) {
11085
11085
  throw new Error(`[manifest] ${manifestPath2}: symbolic links are not permitted`);
11086
11086
  }
11087
11087
  const raw = readFileSync3(manifestPath2, "utf-8");
@@ -11432,7 +11432,13 @@ var init_schema2 = __esm({
11432
11432
  user: external_exports.string().min(1),
11433
11433
  key: external_exports.string().optional()
11434
11434
  });
11435
- computeProviderType = external_exports.enum(["docker", "ssh", "e2b", "cloudflare"]);
11435
+ computeProviderType = external_exports.enum([
11436
+ "docker",
11437
+ "ssh",
11438
+ "e2b",
11439
+ "cloudflare",
11440
+ "cloudflare-isolate"
11441
+ ]);
11436
11442
  stackImageSchema = external_exports.object({
11437
11443
  enabled: external_exports.boolean().optional().default(true),
11438
11444
  auto_commit: external_exports.boolean().optional().default(true),
@@ -11444,6 +11450,15 @@ var init_schema2 = __esm({
11444
11450
  }).optional(),
11445
11451
  ssh: external_exports.object({ hosts: external_exports.array(sshHostSchema).optional() }).optional(),
11446
11452
  e2b: external_exports.object({ template: external_exports.string().optional() }).optional(),
11453
+ // V8-isolate runtime tier per ADR 022. Pure isolate, no DO, no Container.
11454
+ // worker_url points at the deployed olam-worker-runner-isolate Worker.
11455
+ // Same https-or-localhost guard as the cloudflare profile — bearer token
11456
+ // in cleartext would leak the OLAM_TASK_TOKEN.
11457
+ "cloudflare-isolate": external_exports.object({
11458
+ worker_url: external_exports.string().url("worker_url must be a valid URL").refine(isSecureOrLocalhost, {
11459
+ message: "worker_url must use https:// (or http://localhost for dev)"
11460
+ }).optional()
11461
+ }).optional(),
11447
11462
  cloudflare: external_exports.object({
11448
11463
  account_id: external_exports.string().optional(),
11449
11464
  // https-only refine: bare http:// would send the operator's Pylon
@@ -12076,23 +12091,23 @@ var init_schema4 = __esm({
12076
12091
  });
12077
12092
 
12078
12093
  // ../core/dist/global-config/store.js
12079
- import * as fs10 from "node:fs";
12094
+ import * as fs11 from "node:fs";
12080
12095
  import * as os7 from "node:os";
12081
- import * as path13 from "node:path";
12096
+ import * as path14 from "node:path";
12082
12097
  function globalConfigPath() {
12083
12098
  const override = process.env["OLAM_GLOBAL_CONFIG_PATH"];
12084
12099
  if (override && override.length > 0)
12085
12100
  return override;
12086
- return path13.join(os7.homedir(), ".olam", "config.json");
12101
+ return path14.join(os7.homedir(), ".olam", "config.json");
12087
12102
  }
12088
12103
  function readGlobalConfig() {
12089
12104
  const configPath = globalConfigPath();
12090
- if (!fs10.existsSync(configPath)) {
12105
+ if (!fs11.existsSync(configPath)) {
12091
12106
  return { ...DEFAULT_GLOBAL_CONFIG };
12092
12107
  }
12093
12108
  let raw;
12094
12109
  try {
12095
- raw = fs10.readFileSync(configPath, "utf-8");
12110
+ raw = fs11.readFileSync(configPath, "utf-8");
12096
12111
  } catch (err) {
12097
12112
  throw new GlobalConfigReadError(configPath, err);
12098
12113
  }
@@ -12129,11 +12144,11 @@ function migrateSchemaVersion(parsed) {
12129
12144
  function writeGlobalConfig(config2) {
12130
12145
  const configPath = globalConfigPath();
12131
12146
  const validated = GlobalConfigSchema.parse(config2);
12132
- const dir = path13.dirname(configPath);
12133
- fs10.mkdirSync(dir, { recursive: true });
12147
+ const dir = path14.dirname(configPath);
12148
+ fs11.mkdirSync(dir, { recursive: true });
12134
12149
  const tmp = `${configPath}.tmp-${process.pid}`;
12135
- fs10.writeFileSync(tmp, JSON.stringify(validated, null, 2) + "\n", { mode: 420 });
12136
- fs10.renameSync(tmp, configPath);
12150
+ fs11.writeFileSync(tmp, JSON.stringify(validated, null, 2) + "\n", { mode: 420 });
12151
+ fs11.renameSync(tmp, configPath);
12137
12152
  }
12138
12153
  var GlobalConfigReadError;
12139
12154
  var init_store = __esm({
@@ -12152,12 +12167,12 @@ var init_store = __esm({
12152
12167
  });
12153
12168
 
12154
12169
  // ../core/dist/global-config/repos.js
12155
- import * as fs11 from "node:fs";
12170
+ import * as fs12 from "node:fs";
12156
12171
  import * as os8 from "node:os";
12157
- import * as path14 from "node:path";
12172
+ import * as path15 from "node:path";
12158
12173
  function expandPath(p) {
12159
12174
  if (p === "~" || p.startsWith("~/")) {
12160
- return path14.join(os8.homedir(), p.slice(1));
12175
+ return path15.join(os8.homedir(), p.slice(1));
12161
12176
  }
12162
12177
  return p;
12163
12178
  }
@@ -12170,7 +12185,7 @@ function addRepo(entry) {
12170
12185
  throw new Error(`repo "${entry.name}" already registered. Use "olam repos update" to change its path.`);
12171
12186
  }
12172
12187
  const resolvedPath = expandPath(entry.path);
12173
- if (!fs11.existsSync(resolvedPath)) {
12188
+ if (!fs12.existsSync(resolvedPath)) {
12174
12189
  throw new Error(`path "${entry.path}" does not exist. Verify the path is correct.`);
12175
12190
  }
12176
12191
  const now = Date.now();
@@ -12199,7 +12214,7 @@ function updateRepo(name, updates) {
12199
12214
  throw new Error(`repo "${name}" is not registered. Run "olam repos list" to see registered repos.`);
12200
12215
  }
12201
12216
  const resolvedUpdatePath = updates.path !== void 0 ? expandPath(updates.path) : void 0;
12202
- if (resolvedUpdatePath !== void 0 && !fs11.existsSync(resolvedUpdatePath)) {
12217
+ if (resolvedUpdatePath !== void 0 && !fs12.existsSync(resolvedUpdatePath)) {
12203
12218
  throw new Error(`path "${updates.path}" does not exist. Verify the path is correct.`);
12204
12219
  }
12205
12220
  const existing = config2.repos[idx];
@@ -12396,7 +12411,7 @@ var init_port_validator = __esm({
12396
12411
  });
12397
12412
 
12398
12413
  // ../core/dist/global-config/bridge.js
12399
- import * as fs12 from "node:fs";
12414
+ import * as fs13 from "node:fs";
12400
12415
  function repoEntryToRepoConfig(entry) {
12401
12416
  if (!entry.url) {
12402
12417
  throw new Error(`Repo "${entry.name}" has no url. Re-register:
@@ -12404,7 +12419,7 @@ function repoEntryToRepoConfig(entry) {
12404
12419
  olam repos add ${entry.name} --path ${entry.path}`);
12405
12420
  }
12406
12421
  const repoPath = resolveTildePath(entry.path);
12407
- if (!fs12.existsSync(repoPath)) {
12422
+ if (!fs13.existsSync(repoPath)) {
12408
12423
  throw new Error(`Repo "${entry.name}" path "${repoPath}" no longer exists. Run: olam repos update ${entry.name} --path <new-path>`);
12409
12424
  }
12410
12425
  let manifest = null;
@@ -12435,15 +12450,15 @@ var init_bridge = __esm({
12435
12450
  });
12436
12451
 
12437
12452
  // ../core/dist/skill-sources/trust-audit-log.js
12438
- import * as fs13 from "node:fs";
12439
- import * as path15 from "node:path";
12453
+ import * as fs14 from "node:fs";
12454
+ import * as path16 from "node:path";
12440
12455
  import * as os9 from "node:os";
12441
12456
  function skillSourcesAuditLogPath() {
12442
12457
  const override = process.env["OLAM_SKILL_SOURCES_AUDIT_LOG_PATH"];
12443
12458
  if (override && override.length > 0)
12444
12459
  return override;
12445
- const stateDir = process.env["OLAM_STATE_DIR"] ?? path15.join(os9.homedir(), ".olam", "state");
12446
- return path15.join(stateDir, SKILL_SOURCES_AUDIT_LOG_FILENAME);
12460
+ const stateDir = process.env["OLAM_STATE_DIR"] ?? path16.join(os9.homedir(), ".olam", "state");
12461
+ return path16.join(stateDir, SKILL_SOURCES_AUDIT_LOG_FILENAME);
12447
12462
  }
12448
12463
  function appendTrustAudit(entry) {
12449
12464
  const candidate = {
@@ -12452,20 +12467,20 @@ function appendTrustAudit(entry) {
12452
12467
  };
12453
12468
  const validated = TrustAuditEntrySchema.parse(candidate);
12454
12469
  const filePath = skillSourcesAuditLogPath();
12455
- fs13.mkdirSync(path15.dirname(filePath), { recursive: true, mode: 448 });
12456
- const fd = fs13.openSync(filePath, "a", 384);
12470
+ fs14.mkdirSync(path16.dirname(filePath), { recursive: true, mode: 448 });
12471
+ const fd = fs14.openSync(filePath, "a", 384);
12457
12472
  try {
12458
- fs13.writeSync(fd, JSON.stringify(validated) + "\n");
12473
+ fs14.writeSync(fd, JSON.stringify(validated) + "\n");
12459
12474
  } finally {
12460
- fs13.closeSync(fd);
12475
+ fs14.closeSync(fd);
12461
12476
  }
12462
12477
  return validated;
12463
12478
  }
12464
12479
  function readTrustAuditLog() {
12465
12480
  const filePath = skillSourcesAuditLogPath();
12466
- if (!fs13.existsSync(filePath))
12481
+ if (!fs14.existsSync(filePath))
12467
12482
  return { entries: [], errors: [] };
12468
- const raw = fs13.readFileSync(filePath, "utf-8");
12483
+ const raw = fs14.readFileSync(filePath, "utf-8");
12469
12484
  const lines = raw.split("\n");
12470
12485
  const entries = [];
12471
12486
  const errors = [];
@@ -12666,17 +12681,17 @@ var init_store2 = __esm({
12666
12681
 
12667
12682
  // ../core/dist/skill-sources/clone.js
12668
12683
  import { execFileSync as execFileSync2 } from "node:child_process";
12669
- import * as fs14 from "node:fs";
12684
+ import * as fs15 from "node:fs";
12670
12685
  import * as os10 from "node:os";
12671
- import * as path16 from "node:path";
12686
+ import * as path17 from "node:path";
12672
12687
  function skillSourcesRootDir() {
12673
12688
  const override = process.env["OLAM_SKILL_SOURCES_DIR"];
12674
12689
  if (override && override.length > 0)
12675
12690
  return override;
12676
- return path16.join(os10.homedir(), ".olam", "state", "skill-sources");
12691
+ return path17.join(os10.homedir(), ".olam", "state", "skill-sources");
12677
12692
  }
12678
12693
  function skillSourceClonePath(id) {
12679
- return path16.join(skillSourcesRootDir(), id);
12694
+ return path17.join(skillSourcesRootDir(), id);
12680
12695
  }
12681
12696
  function runGit(args, cwd) {
12682
12697
  try {
@@ -12691,15 +12706,15 @@ function runGit(args, cwd) {
12691
12706
  }
12692
12707
  function cloneSkillSource(opts) {
12693
12708
  const clonePath = skillSourceClonePath(opts.id);
12694
- if (fs14.existsSync(clonePath)) {
12709
+ if (fs15.existsSync(clonePath)) {
12695
12710
  throw new Error(`clone path "${clonePath}" already exists. Remove the existing skill-source first.`);
12696
12711
  }
12697
- fs14.mkdirSync(skillSourcesRootDir(), { recursive: true });
12712
+ fs15.mkdirSync(skillSourcesRootDir(), { recursive: true });
12698
12713
  try {
12699
12714
  runGit(["clone", "--depth", "1", "--branch", opts.branch, opts.gitUrl, clonePath]);
12700
12715
  } catch (err) {
12701
- if (fs14.existsSync(clonePath)) {
12702
- fs14.rmSync(clonePath, { recursive: true, force: true });
12716
+ if (fs15.existsSync(clonePath)) {
12717
+ fs15.rmSync(clonePath, { recursive: true, force: true });
12703
12718
  }
12704
12719
  throw new SkillSourceGitError("clone", opts.gitUrl, err);
12705
12720
  }
@@ -12713,7 +12728,7 @@ function cloneSkillSource(opts) {
12713
12728
  }
12714
12729
  function pullSkillSource(opts) {
12715
12730
  const clonePath = skillSourceClonePath(opts.id);
12716
- if (!fs14.existsSync(clonePath)) {
12731
+ if (!fs15.existsSync(clonePath)) {
12717
12732
  throw new Error(`clone path "${clonePath}" does not exist. Run "olam skills source add" first.`);
12718
12733
  }
12719
12734
  try {
@@ -12731,8 +12746,8 @@ function pullSkillSource(opts) {
12731
12746
  }
12732
12747
  function removeSkillSourceClone(id) {
12733
12748
  const clonePath = skillSourceClonePath(id);
12734
- if (fs14.existsSync(clonePath)) {
12735
- fs14.rmSync(clonePath, { recursive: true, force: true });
12749
+ if (fs15.existsSync(clonePath)) {
12750
+ fs15.rmSync(clonePath, { recursive: true, force: true });
12736
12751
  }
12737
12752
  }
12738
12753
  var SkillSourceGitError;
@@ -12755,7 +12770,7 @@ var init_clone = __esm({
12755
12770
  });
12756
12771
 
12757
12772
  // ../core/dist/skill-sources/hook-template.js
12758
- import * as fs15 from "node:fs";
12773
+ import * as fs16 from "node:fs";
12759
12774
  function buildSkillsHookEntry() {
12760
12775
  return {
12761
12776
  matcher: "",
@@ -12814,14 +12829,14 @@ function computeUninstall(settings) {
12814
12829
  return { status: "removed", settingsAfter: next };
12815
12830
  }
12816
12831
  function uninstallSkillsHookFromFile(filePath) {
12817
- if (!fs15.existsSync(filePath)) {
12832
+ if (!fs16.existsSync(filePath)) {
12818
12833
  return { status: "no-settings" };
12819
12834
  }
12820
- const raw = fs15.readFileSync(filePath, "utf-8");
12835
+ const raw = fs16.readFileSync(filePath, "utf-8");
12821
12836
  const settings = raw.trim() ? JSON.parse(raw) : {};
12822
12837
  const result = computeUninstall(settings);
12823
12838
  if (result.status === "removed" && result.settingsAfter) {
12824
- fs15.writeFileSync(filePath, JSON.stringify(result.settingsAfter, null, 2) + "\n");
12839
+ fs16.writeFileSync(filePath, JSON.stringify(result.settingsAfter, null, 2) + "\n");
12825
12840
  }
12826
12841
  return result;
12827
12842
  }
@@ -12837,8 +12852,8 @@ var init_hook_template = __esm({
12837
12852
  });
12838
12853
 
12839
12854
  // ../core/dist/world/merge-settings.js
12840
- import * as fs16 from "node:fs";
12841
- import * as path17 from "node:path";
12855
+ import * as fs17 from "node:fs";
12856
+ import * as path18 from "node:path";
12842
12857
  import * as crypto4 from "node:crypto";
12843
12858
  function mergeHomeSettingsJson(filePath, options) {
12844
12859
  let settings;
@@ -12898,10 +12913,10 @@ function mergeHomeSettingsJson(filePath, options) {
12898
12913
  return { status: "installed", message: `settings.json updated at ${filePath}` };
12899
12914
  }
12900
12915
  function readSettings(filePath) {
12901
- if (!fs16.existsSync(filePath)) {
12916
+ if (!fs17.existsSync(filePath)) {
12902
12917
  return {};
12903
12918
  }
12904
- const raw = fs16.readFileSync(filePath, "utf-8");
12919
+ const raw = fs17.readFileSync(filePath, "utf-8");
12905
12920
  if (!raw.trim())
12906
12921
  return {};
12907
12922
  return JSON.parse(raw);
@@ -12922,13 +12937,13 @@ function isHookSentinelPresent(matchers, sentinel) {
12922
12937
  return false;
12923
12938
  }
12924
12939
  function atomicWriteJson(filePath, data) {
12925
- const dir = path17.dirname(filePath);
12926
- fs16.mkdirSync(dir, { recursive: true });
12940
+ const dir = path18.dirname(filePath);
12941
+ fs17.mkdirSync(dir, { recursive: true });
12927
12942
  const rand = crypto4.randomBytes(6).toString("hex");
12928
12943
  const tmp = `${filePath}.tmp.${process.pid}.${rand}`;
12929
12944
  const json = JSON.stringify(data, null, 2) + "\n";
12930
- fs16.writeFileSync(tmp, json, { mode: 420 });
12931
- fs16.renameSync(tmp, filePath);
12945
+ fs17.writeFileSync(tmp, json, { mode: 420 });
12946
+ fs17.renameSync(tmp, filePath);
12932
12947
  }
12933
12948
  var init_merge_settings = __esm({
12934
12949
  "../core/dist/world/merge-settings.js"() {
@@ -12937,25 +12952,25 @@ var init_merge_settings = __esm({
12937
12952
  });
12938
12953
 
12939
12954
  // ../core/dist/skill-sources/hook-install.js
12940
- import * as fs17 from "node:fs";
12941
- import * as path18 from "node:path";
12955
+ import * as fs18 from "node:fs";
12956
+ import * as path19 from "node:path";
12942
12957
  import * as os11 from "node:os";
12943
12958
  function settingsPathFor(scope, cwd) {
12944
12959
  if (scope === "user") {
12945
- return path18.join(os11.homedir(), ".claude", "settings.json");
12960
+ return path19.join(os11.homedir(), ".claude", "settings.json");
12946
12961
  }
12947
- return path18.join(cwd ?? process.cwd(), ".claude", "settings.json");
12962
+ return path19.join(cwd ?? process.cwd(), ".claude", "settings.json");
12948
12963
  }
12949
12964
  function backupFile(filePath) {
12950
- if (!fs17.existsSync(filePath))
12965
+ if (!fs18.existsSync(filePath))
12951
12966
  return null;
12952
12967
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
12953
12968
  const backupPath = `${filePath}.olam-bak.${ts}`;
12954
- fs17.copyFileSync(filePath, backupPath);
12969
+ fs18.copyFileSync(filePath, backupPath);
12955
12970
  return backupPath;
12956
12971
  }
12957
12972
  function installSkillsHookToFile(filePath) {
12958
- fs17.mkdirSync(path18.dirname(filePath), { recursive: true });
12973
+ fs18.mkdirSync(path19.dirname(filePath), { recursive: true });
12959
12974
  const backupPath = backupFile(filePath);
12960
12975
  const result = mergeHomeSettingsJson(filePath, {
12961
12976
  ensureHook: {
@@ -12966,7 +12981,7 @@ function installSkillsHookToFile(filePath) {
12966
12981
  });
12967
12982
  if (result.status === "already-present" && backupPath) {
12968
12983
  try {
12969
- fs17.unlinkSync(backupPath);
12984
+ fs18.unlinkSync(backupPath);
12970
12985
  } catch {
12971
12986
  }
12972
12987
  return { status: "already-present", filePath, backupPath: null };
@@ -12974,11 +12989,11 @@ function installSkillsHookToFile(filePath) {
12974
12989
  return { status: result.status, filePath, backupPath };
12975
12990
  }
12976
12991
  function isSkillsHookInstalled(filePath) {
12977
- if (!fs17.existsSync(filePath))
12992
+ if (!fs18.existsSync(filePath))
12978
12993
  return false;
12979
12994
  let parsed;
12980
12995
  try {
12981
- parsed = JSON.parse(fs17.readFileSync(filePath, "utf-8"));
12996
+ parsed = JSON.parse(fs18.readFileSync(filePath, "utf-8"));
12982
12997
  } catch {
12983
12998
  return false;
12984
12999
  }
@@ -13016,36 +13031,36 @@ var init_hook_install = __esm({
13016
13031
  });
13017
13032
 
13018
13033
  // ../core/dist/skill-sources/migration-snapshot.js
13019
- import * as fs18 from "node:fs";
13034
+ import * as fs19 from "node:fs";
13020
13035
  import * as os12 from "node:os";
13021
- import * as path19 from "node:path";
13036
+ import * as path20 from "node:path";
13022
13037
  function claudeDirInternal() {
13023
13038
  const override = process.env["OLAM_CLAUDE_DIR"];
13024
13039
  if (override && override.length > 0)
13025
13040
  return override;
13026
- return path19.join(os12.homedir(), ".claude");
13041
+ return path20.join(os12.homedir(), ".claude");
13027
13042
  }
13028
13043
  function migrationSnapshotsDir() {
13029
13044
  const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
13030
13045
  if (override && override.length > 0)
13031
13046
  return override;
13032
- return path19.join(os12.homedir(), ".olam", "state", "migration-snapshots");
13047
+ return path20.join(os12.homedir(), ".olam", "state", "migration-snapshots");
13033
13048
  }
13034
13049
  function listToolboxManagedSymlinks(toolboxPath) {
13035
13050
  const claude = claudeDirInternal();
13036
13051
  const out = [];
13037
13052
  const BUCKETS2 = ["skills", "agents", "scripts", "rules", "commands"];
13038
13053
  for (const bucket of BUCKETS2) {
13039
- const dir = path19.join(claude, bucket);
13040
- if (!fs18.existsSync(dir))
13054
+ const dir = path20.join(claude, bucket);
13055
+ if (!fs19.existsSync(dir))
13041
13056
  continue;
13042
- for (const name of fs18.readdirSync(dir)) {
13043
- const link = path19.join(dir, name);
13057
+ for (const name of fs19.readdirSync(dir)) {
13058
+ const link = path20.join(dir, name);
13044
13059
  try {
13045
- const stat = fs18.lstatSync(link);
13046
- if (!stat.isSymbolicLink())
13060
+ const stat2 = fs19.lstatSync(link);
13061
+ if (!stat2.isSymbolicLink())
13047
13062
  continue;
13048
- const target = fs18.readlinkSync(link);
13063
+ const target = fs19.readlinkSync(link);
13049
13064
  if (target.startsWith(toolboxPath)) {
13050
13065
  out.push({ link, target });
13051
13066
  }
@@ -13058,25 +13073,25 @@ function listToolboxManagedSymlinks(toolboxPath) {
13058
13073
  function detectToolboxState(opts) {
13059
13074
  const claude = claudeDirInternal();
13060
13075
  const toolboxPath = opts.toolboxPath;
13061
- const namespace = opts.namespace ?? path19.basename(toolboxPath);
13062
- const atlasUserFile = path19.join(claude, ".atlas-user");
13063
- const atlasUser = fs18.existsSync(atlasUserFile) ? fs18.readFileSync(atlasUserFile, "utf-8").trim() || void 0 : void 0;
13076
+ const namespace = opts.namespace ?? path20.basename(toolboxPath);
13077
+ const atlasUserFile = path20.join(claude, ".atlas-user");
13078
+ const atlasUser = fs19.existsSync(atlasUserFile) ? fs19.readFileSync(atlasUserFile, "utf-8").trim() || void 0 : void 0;
13064
13079
  let subscriptionsJson;
13065
13080
  if (atlasUser) {
13066
- const sp = path19.join(toolboxPath, "members", atlasUser, "subscriptions.json");
13067
- if (fs18.existsSync(sp)) {
13081
+ const sp = path20.join(toolboxPath, "members", atlasUser, "subscriptions.json");
13082
+ if (fs19.existsSync(sp)) {
13068
13083
  try {
13069
- subscriptionsJson = JSON.parse(fs18.readFileSync(sp, "utf-8"));
13084
+ subscriptionsJson = JSON.parse(fs19.readFileSync(sp, "utf-8"));
13070
13085
  } catch {
13071
13086
  }
13072
13087
  }
13073
13088
  }
13074
13089
  const atlasManagedSymlinks = listToolboxManagedSymlinks(toolboxPath);
13075
13090
  let originalSessionStartHook;
13076
- const settingsPath = path19.join(claude, "settings.json");
13077
- if (fs18.existsSync(settingsPath)) {
13091
+ const settingsPath = path20.join(claude, "settings.json");
13092
+ if (fs19.existsSync(settingsPath)) {
13078
13093
  try {
13079
- const settings = JSON.parse(fs18.readFileSync(settingsPath, "utf-8"));
13094
+ const settings = JSON.parse(fs19.readFileSync(settingsPath, "utf-8"));
13080
13095
  const ss = settings?.hooks?.SessionStart;
13081
13096
  if (Array.isArray(ss))
13082
13097
  originalSessionStartHook = ss;
@@ -13099,21 +13114,21 @@ function detectToolboxState(opts) {
13099
13114
  }
13100
13115
  function writeMigrationSnapshot(snapshot) {
13101
13116
  const dir = migrationSnapshotsDir();
13102
- fs18.mkdirSync(dir, { recursive: true });
13117
+ fs19.mkdirSync(dir, { recursive: true });
13103
13118
  const stamp = snapshot.takenAt.replace(/[:.]/g, "-");
13104
- const file = path19.join(dir, `${snapshot.namespace}-${stamp}.json`);
13105
- fs18.writeFileSync(file, JSON.stringify(snapshot, null, 2) + "\n", { mode: 420 });
13119
+ const file = path20.join(dir, `${snapshot.namespace}-${stamp}.json`);
13120
+ fs19.writeFileSync(file, JSON.stringify(snapshot, null, 2) + "\n", { mode: 420 });
13106
13121
  return file;
13107
13122
  }
13108
13123
  function readLatestMigrationSnapshot(opts = {}) {
13109
13124
  const dir = migrationSnapshotsDir();
13110
- if (!fs18.existsSync(dir))
13125
+ if (!fs19.existsSync(dir))
13111
13126
  return void 0;
13112
- const files = fs18.readdirSync(dir).filter((f) => f.endsWith(".json")).sort().reverse();
13127
+ const files = fs19.readdirSync(dir).filter((f) => f.endsWith(".json")).sort().reverse();
13113
13128
  for (const f of files) {
13114
- const full = path19.join(dir, f);
13129
+ const full = path20.join(dir, f);
13115
13130
  try {
13116
- const snapshot = JSON.parse(fs18.readFileSync(full, "utf-8"));
13131
+ const snapshot = JSON.parse(fs19.readFileSync(full, "utf-8"));
13117
13132
  if (snapshot.schemaVersion !== MIGRATION_SNAPSHOT_SCHEMA_VERSION)
13118
13133
  continue;
13119
13134
  if (opts.namespace !== void 0 && snapshot.namespace !== opts.namespace)
@@ -13126,7 +13141,7 @@ function readLatestMigrationSnapshot(opts = {}) {
13126
13141
  return void 0;
13127
13142
  }
13128
13143
  function readMigrationSnapshotFromPath(p) {
13129
- return JSON.parse(fs18.readFileSync(p, "utf-8"));
13144
+ return JSON.parse(fs19.readFileSync(p, "utf-8"));
13130
13145
  }
13131
13146
  var MIGRATION_SNAPSHOT_SCHEMA_VERSION;
13132
13147
  var init_migration_snapshot = __esm({
@@ -13137,15 +13152,15 @@ var init_migration_snapshot = __esm({
13137
13152
  });
13138
13153
 
13139
13154
  // ../core/dist/skill-sync/artifact-resolver.js
13140
- import * as fs19 from "node:fs";
13141
- import * as path20 from "node:path";
13155
+ import * as fs20 from "node:fs";
13156
+ import * as path21 from "node:path";
13142
13157
  function resolveSubscriptions(opts) {
13143
13158
  const { clonePath, atlasUser } = opts;
13144
13159
  if (atlasUser) {
13145
- const subsPath = path20.join(clonePath, "members", atlasUser, "subscriptions.json");
13146
- if (fs19.existsSync(subsPath)) {
13160
+ const subsPath = path21.join(clonePath, "members", atlasUser, "subscriptions.json");
13161
+ if (fs20.existsSync(subsPath)) {
13147
13162
  try {
13148
- const parsed = JSON.parse(fs19.readFileSync(subsPath, "utf-8"));
13163
+ const parsed = JSON.parse(fs20.readFileSync(subsPath, "utf-8"));
13149
13164
  if (Array.isArray(parsed?.categories)) {
13150
13165
  return {
13151
13166
  categories: parsed.categories.filter((c) => typeof c === "string"),
@@ -13157,10 +13172,10 @@ function resolveSubscriptions(opts) {
13157
13172
  }
13158
13173
  }
13159
13174
  }
13160
- const catsPath = path20.join(clonePath, "shared", "categories.json");
13161
- if (fs19.existsSync(catsPath)) {
13175
+ const catsPath = path21.join(clonePath, "shared", "categories.json");
13176
+ if (fs20.existsSync(catsPath)) {
13162
13177
  try {
13163
- const parsed = JSON.parse(fs19.readFileSync(catsPath, "utf-8"));
13178
+ const parsed = JSON.parse(fs20.readFileSync(catsPath, "utf-8"));
13164
13179
  if (Array.isArray(parsed?.categories)) {
13165
13180
  return {
13166
13181
  categories: parsed.categories.map((c) => c.id).filter((id) => typeof id === "string"),
@@ -13171,14 +13186,14 @@ function resolveSubscriptions(opts) {
13171
13186
  } catch {
13172
13187
  }
13173
13188
  }
13174
- const sharedDir = path20.join(clonePath, "shared");
13189
+ const sharedDir = path21.join(clonePath, "shared");
13175
13190
  const cats = [];
13176
- if (fs19.existsSync(sharedDir)) {
13177
- for (const name of fs19.readdirSync(sharedDir)) {
13178
- const dir = path20.join(sharedDir, name);
13179
- if (!fs19.statSync(dir).isDirectory())
13191
+ if (fs20.existsSync(sharedDir)) {
13192
+ for (const name of fs20.readdirSync(sharedDir)) {
13193
+ const dir = path21.join(sharedDir, name);
13194
+ if (!fs20.statSync(dir).isDirectory())
13180
13195
  continue;
13181
- if (fs19.existsSync(path20.join(dir, "skills")) || fs19.existsSync(path20.join(dir, "agents"))) {
13196
+ if (fs20.existsSync(path21.join(dir, "skills")) || fs20.existsSync(path21.join(dir, "agents"))) {
13182
13197
  cats.push(name);
13183
13198
  }
13184
13199
  }
@@ -13186,29 +13201,29 @@ function resolveSubscriptions(opts) {
13186
13201
  return { categories: cats, fromSubscriptionsFile: false, atlasUser };
13187
13202
  }
13188
13203
  function listDirSafe(dir) {
13189
- if (!fs19.existsSync(dir))
13204
+ if (!fs20.existsSync(dir))
13190
13205
  return [];
13191
- return fs19.readdirSync(dir);
13206
+ return fs20.readdirSync(dir);
13192
13207
  }
13193
13208
  function resolveSkillsDir(opts) {
13194
13209
  const { sourceId, baseDir } = opts;
13195
13210
  const out = [];
13196
13211
  for (const name of listDirSafe(baseDir)) {
13197
- const subdir = path20.join(baseDir, name);
13198
- if (!fs19.statSync(subdir).isDirectory())
13212
+ const subdir = path21.join(baseDir, name);
13213
+ if (!fs20.statSync(subdir).isDirectory())
13199
13214
  continue;
13200
- if (!fs19.existsSync(path20.join(subdir, "SKILL.md")))
13215
+ if (!fs20.existsSync(path21.join(subdir, "SKILL.md")))
13201
13216
  continue;
13202
13217
  out.push({ kind: "skill", sourceId, sourcePath: subdir, deployBasename: name });
13203
- const subagentsDir = path20.join(subdir, "references", "agents");
13204
- if (fs19.existsSync(subagentsDir) && fs19.statSync(subagentsDir).isDirectory()) {
13218
+ const subagentsDir = path21.join(subdir, "references", "agents");
13219
+ if (fs20.existsSync(subagentsDir) && fs20.statSync(subagentsDir).isDirectory()) {
13205
13220
  for (const f of listDirSafe(subagentsDir)) {
13206
13221
  if (!f.endsWith(".md"))
13207
13222
  continue;
13208
13223
  out.push({
13209
13224
  kind: "subagent",
13210
13225
  sourceId,
13211
- sourcePath: path20.join(subagentsDir, f),
13226
+ sourcePath: path21.join(subagentsDir, f),
13212
13227
  deployBasename: f,
13213
13228
  parentSkill: name
13214
13229
  });
@@ -13221,18 +13236,18 @@ function resolveAgentsDir(opts) {
13221
13236
  const { sourceId, baseDir } = opts;
13222
13237
  const out = [];
13223
13238
  for (const name of listDirSafe(baseDir)) {
13224
- const full = path20.join(baseDir, name);
13225
- const stat = fs19.statSync(full);
13226
- if (stat.isFile() && name.endsWith(".md")) {
13239
+ const full = path21.join(baseDir, name);
13240
+ const stat2 = fs20.statSync(full);
13241
+ if (stat2.isFile() && name.endsWith(".md")) {
13227
13242
  out.push({ kind: "agent", sourceId, sourcePath: full, deployBasename: name });
13228
- } else if (stat.isDirectory()) {
13243
+ } else if (stat2.isDirectory()) {
13229
13244
  for (const f of listDirSafe(full)) {
13230
13245
  if (!f.endsWith(".md"))
13231
13246
  continue;
13232
13247
  out.push({
13233
13248
  kind: "agent",
13234
13249
  sourceId,
13235
- sourcePath: path20.join(full, f),
13250
+ sourcePath: path21.join(full, f),
13236
13251
  deployBasename: `${name}-${f}`
13237
13252
  });
13238
13253
  }
@@ -13244,11 +13259,11 @@ function resolveScriptsDir(opts) {
13244
13259
  const { sourceId, baseDir } = opts;
13245
13260
  const out = [];
13246
13261
  for (const name of listDirSafe(baseDir)) {
13247
- const full = path20.join(baseDir, name);
13248
- const stat = fs19.statSync(full);
13249
- if (stat.isFile() && name.endsWith(".sh")) {
13262
+ const full = path21.join(baseDir, name);
13263
+ const stat2 = fs20.statSync(full);
13264
+ if (stat2.isFile() && name.endsWith(".sh")) {
13250
13265
  out.push({ kind: "script", sourceId, sourcePath: full, deployBasename: name });
13251
- } else if (stat.isDirectory()) {
13266
+ } else if (stat2.isDirectory()) {
13252
13267
  out.push({ kind: "script", sourceId, sourcePath: full, deployBasename: name });
13253
13268
  }
13254
13269
  }
@@ -13260,8 +13275,8 @@ function resolveRulesDir(opts) {
13260
13275
  for (const name of listDirSafe(baseDir)) {
13261
13276
  if (!name.endsWith(".md"))
13262
13277
  continue;
13263
- const full = path20.join(baseDir, name);
13264
- if (!fs19.statSync(full).isFile())
13278
+ const full = path21.join(baseDir, name);
13279
+ if (!fs20.statSync(full).isFile())
13265
13280
  continue;
13266
13281
  out.push({ kind: "rule", sourceId, sourcePath: full, deployBasename: name });
13267
13282
  }
@@ -13273,8 +13288,8 @@ function resolveJsonDir(opts) {
13273
13288
  for (const name of listDirSafe(baseDir)) {
13274
13289
  if (!name.endsWith(".json"))
13275
13290
  continue;
13276
- const full = path20.join(baseDir, name);
13277
- if (!fs19.statSync(full).isFile())
13291
+ const full = path21.join(baseDir, name);
13292
+ if (!fs20.statSync(full).isFile())
13278
13293
  continue;
13279
13294
  out.push({ kind, sourceId, sourcePath: full, deployBasename: name });
13280
13295
  }
@@ -13286,8 +13301,8 @@ function resolveOverlaysDir(opts) {
13286
13301
  for (const name of listDirSafe(baseDir)) {
13287
13302
  if (!name.endsWith(".md"))
13288
13303
  continue;
13289
- const full = path20.join(baseDir, name);
13290
- if (!fs19.statSync(full).isFile())
13304
+ const full = path21.join(baseDir, name);
13305
+ if (!fs20.statSync(full).isFile())
13291
13306
  continue;
13292
13307
  const deployBasename = name.replace(/\.md$/, "");
13293
13308
  out.push({
@@ -13305,33 +13320,33 @@ function resolveSourceArtifacts(opts) {
13305
13320
  const subscription = resolveSubscriptions({ clonePath, atlasUser });
13306
13321
  const artifacts = [];
13307
13322
  for (const cat of subscription.categories) {
13308
- const catDir = path20.join(clonePath, "shared", cat);
13309
- if (!fs19.existsSync(catDir))
13323
+ const catDir = path21.join(clonePath, "shared", cat);
13324
+ if (!fs20.existsSync(catDir))
13310
13325
  continue;
13311
- artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path20.join(catDir, "skills") }));
13312
- artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path20.join(catDir, "agents") }));
13313
- artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path20.join(catDir, "scripts") }));
13314
- artifacts.push(...resolveRulesDir({ sourceId, baseDir: path20.join(catDir, "rules") }));
13315
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path20.join(catDir, "hooks"), kind: "hook" }));
13316
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path20.join(catDir, "permissions"), kind: "permission" }));
13326
+ artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path21.join(catDir, "skills") }));
13327
+ artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path21.join(catDir, "agents") }));
13328
+ artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path21.join(catDir, "scripts") }));
13329
+ artifacts.push(...resolveRulesDir({ sourceId, baseDir: path21.join(catDir, "rules") }));
13330
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(catDir, "hooks"), kind: "hook" }));
13331
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(catDir, "permissions"), kind: "permission" }));
13317
13332
  }
13318
13333
  if (atlasUser) {
13319
- const memberRoot = path20.join(clonePath, "members", atlasUser);
13320
- if (fs19.existsSync(memberRoot)) {
13321
- artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path20.join(memberRoot, "skills") }));
13322
- artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path20.join(memberRoot, "agents") }));
13323
- artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path20.join(memberRoot, "scripts") }));
13324
- artifacts.push(...resolveRulesDir({ sourceId, baseDir: path20.join(memberRoot, "rules") }));
13325
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path20.join(memberRoot, "hooks"), kind: "hook" }));
13326
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path20.join(memberRoot, "permissions"), kind: "permission" }));
13334
+ const memberRoot = path21.join(clonePath, "members", atlasUser);
13335
+ if (fs20.existsSync(memberRoot)) {
13336
+ artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path21.join(memberRoot, "skills") }));
13337
+ artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path21.join(memberRoot, "agents") }));
13338
+ artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path21.join(memberRoot, "scripts") }));
13339
+ artifacts.push(...resolveRulesDir({ sourceId, baseDir: path21.join(memberRoot, "rules") }));
13340
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(memberRoot, "hooks"), kind: "hook" }));
13341
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(memberRoot, "permissions"), kind: "permission" }));
13327
13342
  artifacts.push(...resolveOverlaysDir({
13328
13343
  sourceId,
13329
- baseDir: path20.join(memberRoot, "skills.overrides"),
13344
+ baseDir: path21.join(memberRoot, "skills.overrides"),
13330
13345
  targetKind: "skill"
13331
13346
  }));
13332
13347
  artifacts.push(...resolveOverlaysDir({
13333
13348
  sourceId,
13334
- baseDir: path20.join(memberRoot, "agents.overrides"),
13349
+ baseDir: path21.join(memberRoot, "agents.overrides"),
13335
13350
  targetKind: "agent"
13336
13351
  }));
13337
13352
  }
@@ -13396,14 +13411,14 @@ var init_shim_targets = __esm({
13396
13411
  });
13397
13412
 
13398
13413
  // ../core/dist/skill-sync/symlink-deployer.js
13399
- import * as fs20 from "node:fs";
13414
+ import * as fs21 from "node:fs";
13400
13415
  import * as os13 from "node:os";
13401
- import * as path21 from "node:path";
13416
+ import * as path22 from "node:path";
13402
13417
  function claudeDir() {
13403
13418
  const override = process.env["OLAM_CLAUDE_DIR"];
13404
13419
  if (override && override.length > 0)
13405
13420
  return override;
13406
- return path21.join(os13.homedir(), ".claude");
13421
+ return path22.join(os13.homedir(), ".claude");
13407
13422
  }
13408
13423
  function bucketFor(kind) {
13409
13424
  switch (kind) {
@@ -13463,16 +13478,16 @@ function detectCollisions(artifacts) {
13463
13478
  function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, expectedAgentWinnerNames) {
13464
13479
  const shadowBackups = [];
13465
13480
  for (const bucket of BUCKETS) {
13466
- const dir = path21.join(claude, bucket);
13467
- if (!fs20.existsSync(dir))
13481
+ const dir = path22.join(claude, bucket);
13482
+ if (!fs21.existsSync(dir))
13468
13483
  continue;
13469
- for (const name of fs20.readdirSync(dir)) {
13484
+ for (const name of fs21.readdirSync(dir)) {
13470
13485
  if (name === ".olam-merged")
13471
13486
  continue;
13472
- const p = path21.join(dir, name);
13487
+ const p = path22.join(dir, name);
13473
13488
  try {
13474
- const stat = fs20.lstatSync(p);
13475
- if (stat.isSymbolicLink()) {
13489
+ const stat2 = fs21.lstatSync(p);
13490
+ if (stat2.isSymbolicLink()) {
13476
13491
  if (bucket === "scripts" && overlayReferences !== void 0) {
13477
13492
  const refs = overlayReferences.get(name);
13478
13493
  if (refs !== void 0 && refs.length > 0 && checkShimRemoval(name, "0.0.0") !== null) {
@@ -13492,8 +13507,8 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, e
13492
13507
  `);
13493
13508
  }
13494
13509
  }
13495
- fs20.unlinkSync(p);
13496
- } else if (bucket === "agents" && stat.isFile() && !name.includes(".shadow-backup-")) {
13510
+ fs21.unlinkSync(p);
13511
+ } else if (bucket === "agents" && stat2.isFile() && !name.includes(".shadow-backup-")) {
13497
13512
  const hasWinner = expectedAgentWinnerNames !== void 0 ? expectedAgentWinnerNames.has(name) : true;
13498
13513
  if (hasWinner) {
13499
13514
  const backup = shadowBackup(p);
@@ -13509,34 +13524,34 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, e
13509
13524
  function shadowBackup(link) {
13510
13525
  const epoch = Math.floor(Date.now() / 1e3);
13511
13526
  const backup = `${link}.shadow-backup-${epoch}`;
13512
- fs20.renameSync(link, backup);
13527
+ fs21.renameSync(link, backup);
13513
13528
  return backup;
13514
13529
  }
13515
13530
  function linkIfNeeded(target, link) {
13516
13531
  try {
13517
- const existing = fs20.readlinkSync(link);
13532
+ const existing = fs21.readlinkSync(link);
13518
13533
  if (existing === target)
13519
13534
  return { created: false };
13520
13535
  } catch {
13521
13536
  }
13522
13537
  let isLink = false;
13523
13538
  try {
13524
- isLink = fs20.lstatSync(link).isSymbolicLink();
13539
+ isLink = fs21.lstatSync(link).isSymbolicLink();
13525
13540
  } catch {
13526
13541
  }
13527
13542
  let backup;
13528
13543
  if (isLink) {
13529
- fs20.unlinkSync(link);
13530
- } else if (fs20.existsSync(link)) {
13544
+ fs21.unlinkSync(link);
13545
+ } else if (fs21.existsSync(link)) {
13531
13546
  backup = shadowBackup(link);
13532
13547
  }
13533
- fs20.symlinkSync(target, link);
13548
+ fs21.symlinkSync(target, link);
13534
13549
  return { created: true, shadowBackup: backup };
13535
13550
  }
13536
13551
  function deployArtifacts(artifacts, opts) {
13537
13552
  const claude = claudeDir();
13538
13553
  for (const bucket of BUCKETS) {
13539
- fs20.mkdirSync(path21.join(claude, bucket), { recursive: true });
13554
+ fs21.mkdirSync(path22.join(claude, bucket), { recursive: true });
13540
13555
  }
13541
13556
  const { winners, collisions } = detectCollisions(artifacts);
13542
13557
  const expectedAgentWinnerNames = new Set(winners.filter((a) => a.kind === "agent").map((a) => a.deployBasename));
@@ -13546,11 +13561,11 @@ function deployArtifacts(artifacts, opts) {
13546
13561
  const bucket = bucketFor(artifact.kind);
13547
13562
  if (!bucket)
13548
13563
  continue;
13549
- const linkPath = path21.join(claude, bucket, artifact.deployBasename);
13564
+ const linkPath = path22.join(claude, bucket, artifact.deployBasename);
13550
13565
  if (artifact.kind === "agent" && artifact.resolvedContent !== void 0) {
13551
13566
  const tmpPath = `${linkPath}.tmp-${process.pid}-${Date.now()}`;
13552
- fs20.writeFileSync(tmpPath, artifact.resolvedContent);
13553
- fs20.renameSync(tmpPath, linkPath);
13567
+ fs21.writeFileSync(tmpPath, artifact.resolvedContent);
13568
+ fs21.renameSync(tmpPath, linkPath);
13554
13569
  result.linked += 1;
13555
13570
  continue;
13556
13571
  }
@@ -13572,7 +13587,7 @@ var init_symlink_deployer = __esm({
13572
13587
  });
13573
13588
 
13574
13589
  // ../core/dist/meta-hooks/memory-recall.js
13575
- import * as fs21 from "node:fs";
13590
+ import * as fs22 from "node:fs";
13576
13591
  function buildMemoryRecallHookEntry() {
13577
13592
  return {
13578
13593
  matcher: OLAM_META_MEMORY_RECALL_MATCHER,
@@ -13647,7 +13662,7 @@ var init_memory_recall = __esm({
13647
13662
  });
13648
13663
 
13649
13664
  // ../core/dist/meta-hooks/memory-classify.js
13650
- import * as fs22 from "node:fs";
13665
+ import * as fs23 from "node:fs";
13651
13666
  function buildMemoryClassifyHookEntry() {
13652
13667
  return {
13653
13668
  matcher: OLAM_META_MEMORY_CLASSIFY_MATCHER,
@@ -13731,26 +13746,26 @@ var init_meta_hooks = __esm({
13731
13746
  });
13732
13747
 
13733
13748
  // ../core/dist/skill-sync/settings-merger.js
13734
- import * as fs23 from "node:fs";
13749
+ import * as fs24 from "node:fs";
13735
13750
  import * as os14 from "node:os";
13736
- import * as path22 from "node:path";
13751
+ import * as path23 from "node:path";
13737
13752
  function claudeSettingsPath() {
13738
13753
  const override = process.env["OLAM_CLAUDE_SETTINGS_PATH"];
13739
13754
  if (override && override.length > 0)
13740
13755
  return override;
13741
- return path22.join(claudeDirInternal2(), "settings.json");
13756
+ return path23.join(claudeDirInternal2(), "settings.json");
13742
13757
  }
13743
13758
  function claudeDirInternal2() {
13744
13759
  const override = process.env["OLAM_CLAUDE_DIR"];
13745
13760
  if (override && override.length > 0)
13746
13761
  return override;
13747
- return path22.join(os14.homedir(), ".claude");
13762
+ return path23.join(os14.homedir(), ".claude");
13748
13763
  }
13749
13764
  function settingsBackupDir() {
13750
13765
  const override = process.env["OLAM_SETTINGS_BACKUP_DIR"];
13751
13766
  if (override && override.length > 0)
13752
13767
  return override;
13753
- return path22.join(os14.homedir(), ".olam", "state", "settings-backups");
13768
+ return path23.join(os14.homedir(), ".olam", "state", "settings-backups");
13754
13769
  }
13755
13770
  function dedupeByMatcher(entries) {
13756
13771
  const map = /* @__PURE__ */ new Map();
@@ -13797,28 +13812,28 @@ function tagOlam(entry) {
13797
13812
  return { ...entry, [OLAM_SKILLS_MARKER]: true };
13798
13813
  }
13799
13814
  function readJson(file) {
13800
- return JSON.parse(fs23.readFileSync(file, "utf-8"));
13815
+ return JSON.parse(fs24.readFileSync(file, "utf-8"));
13801
13816
  }
13802
13817
  function rotateBackups(backupDir) {
13803
- if (!fs23.existsSync(backupDir))
13818
+ if (!fs24.existsSync(backupDir))
13804
13819
  return;
13805
- const files = fs23.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path22.join(backupDir, f), mtime: fs23.statSync(path22.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
13820
+ const files = fs24.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path23.join(backupDir, f), mtime: fs24.statSync(path23.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
13806
13821
  for (const f of files.slice(BACKUP_RETENTION)) {
13807
13822
  try {
13808
- fs23.unlinkSync(f.full);
13823
+ fs24.unlinkSync(f.full);
13809
13824
  } catch {
13810
13825
  }
13811
13826
  }
13812
13827
  }
13813
13828
  function backupSettings() {
13814
13829
  const src = claudeSettingsPath();
13815
- if (!fs23.existsSync(src))
13830
+ if (!fs24.existsSync(src))
13816
13831
  return void 0;
13817
13832
  const dir = settingsBackupDir();
13818
- fs23.mkdirSync(dir, { recursive: true });
13833
+ fs24.mkdirSync(dir, { recursive: true });
13819
13834
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13820
- const dest = path22.join(dir, `settings-${stamp}.json`);
13821
- fs23.copyFileSync(src, dest);
13835
+ const dest = path23.join(dir, `settings-${stamp}.json`);
13836
+ fs24.copyFileSync(src, dest);
13822
13837
  rotateBackups(dir);
13823
13838
  return dest;
13824
13839
  }
@@ -13826,7 +13841,7 @@ function mergeSettings(input) {
13826
13841
  const settingsPath = claudeSettingsPath();
13827
13842
  const backupPath = backupSettings();
13828
13843
  let base = {};
13829
- if (fs23.existsSync(settingsPath)) {
13844
+ if (fs24.existsSync(settingsPath)) {
13830
13845
  try {
13831
13846
  base = readJson(settingsPath);
13832
13847
  } catch {
@@ -13894,10 +13909,10 @@ function mergeSettings(input) {
13894
13909
  ...input.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
13895
13910
  }
13896
13911
  };
13897
- fs23.mkdirSync(path22.dirname(settingsPath), { recursive: true });
13912
+ fs24.mkdirSync(path23.dirname(settingsPath), { recursive: true });
13898
13913
  const tmp = `${settingsPath}.tmp-${process.pid}`;
13899
- fs23.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
13900
- fs23.renameSync(tmp, settingsPath);
13914
+ fs24.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
13915
+ fs24.renameSync(tmp, settingsPath);
13901
13916
  return { backupPath, hooksAdded, permissionsCount: permSet.size, dualWriteDeduped, dualWriteDroppedCommands };
13902
13917
  }
13903
13918
  var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
@@ -13954,16 +13969,16 @@ var init_schema5 = __esm({
13954
13969
 
13955
13970
  // ../core/dist/skill-sync/per-project-override.js
13956
13971
  import { execFileSync as execFileSync3 } from "node:child_process";
13957
- import * as fs24 from "node:fs";
13958
- import * as path23 from "node:path";
13972
+ import * as fs25 from "node:fs";
13973
+ import * as path24 from "node:path";
13959
13974
  import { parse as parseYaml3 } from "yaml";
13960
13975
  function findProjectOverride(startDir) {
13961
- let dir = path23.resolve(startDir);
13962
- const root = path23.parse(dir).root;
13976
+ let dir = path24.resolve(startDir);
13977
+ const root = path24.parse(dir).root;
13963
13978
  while (true) {
13964
- const candidate = path23.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
13965
- if (fs24.existsSync(candidate) && fs24.statSync(candidate).isFile()) {
13966
- const raw = fs24.readFileSync(candidate, "utf-8");
13979
+ const candidate = path24.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
13980
+ if (fs25.existsSync(candidate) && fs25.statSync(candidate).isFile()) {
13981
+ const raw = fs25.readFileSync(candidate, "utf-8");
13967
13982
  let parsed;
13968
13983
  try {
13969
13984
  parsed = parseYaml3(raw);
@@ -13976,7 +13991,7 @@ function findProjectOverride(startDir) {
13976
13991
  }
13977
13992
  if (dir === root)
13978
13993
  return void 0;
13979
- dir = path23.dirname(dir);
13994
+ dir = path24.dirname(dir);
13980
13995
  }
13981
13996
  }
13982
13997
  function applyOverrideToArtifacts(artifacts, override) {
@@ -14017,14 +14032,14 @@ var init_per_project_override = __esm({
14017
14032
  "../core/dist/skill-sync/per-project-override.js"() {
14018
14033
  "use strict";
14019
14034
  init_schema5();
14020
- PROJECT_OVERRIDE_RELATIVE_PATH = path23.join(".olam", "skill-overrides.yaml");
14035
+ PROJECT_OVERRIDE_RELATIVE_PATH = path24.join(".olam", "skill-overrides.yaml");
14021
14036
  }
14022
14037
  });
14023
14038
 
14024
14039
  // ../core/dist/lib/file-lock.js
14025
- import * as fs25 from "node:fs";
14040
+ import * as fs26 from "node:fs";
14026
14041
  import * as os15 from "node:os";
14027
- import * as path24 from "node:path";
14042
+ import * as path25 from "node:path";
14028
14043
  function defaultIsPidAlive(pid) {
14029
14044
  try {
14030
14045
  process.kill(pid, 0);
@@ -14035,11 +14050,11 @@ function defaultIsPidAlive(pid) {
14035
14050
  }
14036
14051
  }
14037
14052
  function sleep3(ms) {
14038
- return new Promise((resolve14) => setTimeout(resolve14, ms));
14053
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
14039
14054
  }
14040
14055
  function readLockMeta(lockPath) {
14041
14056
  try {
14042
- const raw = fs25.readFileSync(lockPath, "utf-8");
14057
+ const raw = fs26.readFileSync(lockPath, "utf-8");
14043
14058
  const parsed = JSON.parse(raw);
14044
14059
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
14045
14060
  return parsed;
@@ -14058,12 +14073,12 @@ function isLockStale(meta2, opts) {
14058
14073
  }
14059
14074
  function tryAcquireOnce(lockPath, meta2, opts) {
14060
14075
  try {
14061
- fs25.mkdirSync(path24.dirname(lockPath), { recursive: true });
14062
- const fd = fs25.openSync(lockPath, "wx", 384);
14076
+ fs26.mkdirSync(path25.dirname(lockPath), { recursive: true });
14077
+ const fd = fs26.openSync(lockPath, "wx", 384);
14063
14078
  try {
14064
- fs25.writeSync(fd, JSON.stringify(meta2));
14079
+ fs26.writeSync(fd, JSON.stringify(meta2));
14065
14080
  } finally {
14066
- fs25.closeSync(fd);
14081
+ fs26.closeSync(fd);
14067
14082
  }
14068
14083
  return true;
14069
14084
  } catch (err) {
@@ -14073,14 +14088,14 @@ function tryAcquireOnce(lockPath, meta2, opts) {
14073
14088
  const existing = readLockMeta(lockPath);
14074
14089
  if (existing === void 0) {
14075
14090
  try {
14076
- fs25.unlinkSync(lockPath);
14091
+ fs26.unlinkSync(lockPath);
14077
14092
  } catch {
14078
14093
  }
14079
14094
  return tryAcquireOnce(lockPath, meta2, opts);
14080
14095
  }
14081
14096
  if (isLockStale(existing, opts)) {
14082
14097
  try {
14083
- fs25.unlinkSync(lockPath);
14098
+ fs26.unlinkSync(lockPath);
14084
14099
  } catch {
14085
14100
  }
14086
14101
  return tryAcquireOnce(lockPath, meta2, opts);
@@ -14090,7 +14105,7 @@ function tryAcquireOnce(lockPath, meta2, opts) {
14090
14105
  }
14091
14106
  async function acquireFileLock(lockDir, options = {}) {
14092
14107
  const lockFilename = options.lockFilename ?? DEFAULT_LOCK_FILENAME;
14093
- const lockPath = path24.join(lockDir, lockFilename);
14108
+ const lockPath = path25.join(lockDir, lockFilename);
14094
14109
  const acquireTimeoutMs = options.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS;
14095
14110
  const staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS;
14096
14111
  const now = options.now ?? Date.now;
@@ -14110,7 +14125,7 @@ async function acquireFileLock(lockDir, options = {}) {
14110
14125
  lockPath,
14111
14126
  release: () => {
14112
14127
  try {
14113
- fs25.unlinkSync(lockPath);
14128
+ fs26.unlinkSync(lockPath);
14114
14129
  } catch {
14115
14130
  }
14116
14131
  }
@@ -14214,11 +14229,11 @@ var init_min_version_filter = __esm({
14214
14229
  });
14215
14230
 
14216
14231
  // ../core/dist/skill-sync/overlay-scan.js
14217
- import * as fs26 from "node:fs";
14218
- import * as path25 from "node:path";
14232
+ import * as fs27 from "node:fs";
14233
+ import * as path26 from "node:path";
14219
14234
  function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
14220
14235
  const result = /* @__PURE__ */ new Map();
14221
- if (!fs26.existsSync(overlayRoot)) {
14236
+ if (!fs27.existsSync(overlayRoot)) {
14222
14237
  return result;
14223
14238
  }
14224
14239
  if (basenames.length === 0) {
@@ -14227,13 +14242,13 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
14227
14242
  const mdFiles = [];
14228
14243
  let overlayRootReal;
14229
14244
  try {
14230
- overlayRootReal = fs26.realpathSync(overlayRoot);
14245
+ overlayRootReal = fs27.realpathSync(overlayRoot);
14231
14246
  } catch {
14232
14247
  return result;
14233
14248
  }
14234
14249
  for (const subdir of OVERRIDE_SUBDIRS) {
14235
- const dir = path25.join(overlayRoot, subdir);
14236
- if (!fs26.existsSync(dir))
14250
+ const dir = path26.join(overlayRoot, subdir);
14251
+ if (!fs27.existsSync(dir))
14237
14252
  continue;
14238
14253
  walkMarkdown(dir, mdFiles, caps.maxFiles);
14239
14254
  }
@@ -14241,25 +14256,25 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
14241
14256
  for (const filepath of mdFiles) {
14242
14257
  let realFile;
14243
14258
  try {
14244
- realFile = fs26.realpathSync(filepath);
14259
+ realFile = fs27.realpathSync(filepath);
14245
14260
  } catch (err) {
14246
14261
  const code = err.code;
14247
14262
  if (code === "ENOENT" || code === "EACCES")
14248
14263
  continue;
14249
14264
  throw err;
14250
14265
  }
14251
- const rel = path25.relative(overlayRootReal, realFile);
14252
- if (rel.startsWith("..") || path25.isAbsolute(rel)) {
14266
+ const rel = path26.relative(overlayRootReal, realFile);
14267
+ if (rel.startsWith("..") || path26.isAbsolute(rel)) {
14253
14268
  continue;
14254
14269
  }
14255
14270
  let content;
14256
14271
  try {
14257
- const stat = fs26.statSync(filepath);
14258
- totalBytes += stat.size;
14272
+ const stat2 = fs27.statSync(filepath);
14273
+ totalBytes += stat2.size;
14259
14274
  if (totalBytes > caps.maxTotalBytes) {
14260
14275
  throw new Error(`[overlay-scan] aborted: overlay tree exceeds ${caps.maxTotalBytes} total bytes. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
14261
14276
  }
14262
- content = fs26.readFileSync(filepath, "utf8");
14277
+ content = fs27.readFileSync(filepath, "utf8");
14263
14278
  } catch (err) {
14264
14279
  const code = err.code;
14265
14280
  if (code === "ENOENT" || code === "EACCES") {
@@ -14267,7 +14282,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
14267
14282
  }
14268
14283
  throw err;
14269
14284
  }
14270
- const relpath = path25.relative(overlayRoot, filepath).split(path25.sep).join("/");
14285
+ const relpath = path26.relative(overlayRoot, filepath).split(path26.sep).join("/");
14271
14286
  for (const basename6 of basenames) {
14272
14287
  if (content.includes(basename6)) {
14273
14288
  const list = result.get(basename6) ?? [];
@@ -14281,7 +14296,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
14281
14296
  function walkMarkdown(dir, out, cap) {
14282
14297
  let entries;
14283
14298
  try {
14284
- entries = fs26.readdirSync(dir, { withFileTypes: true });
14299
+ entries = fs27.readdirSync(dir, { withFileTypes: true });
14285
14300
  } catch (err) {
14286
14301
  if (err.code === "ENOENT")
14287
14302
  return;
@@ -14291,7 +14306,7 @@ function walkMarkdown(dir, out, cap) {
14291
14306
  if (out.length >= cap) {
14292
14307
  throw new Error(`[overlay-scan] aborted: overlay tree contains > ${cap} markdown files. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
14293
14308
  }
14294
- const full = path25.join(dir, entry.name);
14309
+ const full = path26.join(dir, entry.name);
14295
14310
  if (entry.isSymbolicLink())
14296
14311
  continue;
14297
14312
  if (entry.isDirectory()) {
@@ -14316,12 +14331,12 @@ var init_overlay_scan = __esm({
14316
14331
  });
14317
14332
 
14318
14333
  // ../core/dist/skill-sync/settings-json-lock.js
14319
- import * as fs27 from "node:fs";
14334
+ import * as fs28 from "node:fs";
14320
14335
  import * as os16 from "node:os";
14321
- import * as path26 from "node:path";
14336
+ import * as path27 from "node:path";
14322
14337
  function defaultSettingsJsonLockPath() {
14323
- const stateDir = process.env["OLAM_STATE_DIR"] ?? path26.join(os16.homedir(), ".olam", "state");
14324
- return path26.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
14338
+ const stateDir = process.env["OLAM_STATE_DIR"] ?? path27.join(os16.homedir(), ".olam", "state");
14339
+ return path27.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
14325
14340
  }
14326
14341
  function defaultIsPidAlive2(pid) {
14327
14342
  try {
@@ -14333,11 +14348,11 @@ function defaultIsPidAlive2(pid) {
14333
14348
  }
14334
14349
  }
14335
14350
  function sleep4(ms) {
14336
- return new Promise((resolve14) => setTimeout(resolve14, ms));
14351
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
14337
14352
  }
14338
14353
  function readLockMeta2(lockPath) {
14339
14354
  try {
14340
- const raw = fs27.readFileSync(lockPath, "utf-8");
14355
+ const raw = fs28.readFileSync(lockPath, "utf-8");
14341
14356
  const parsed = JSON.parse(raw);
14342
14357
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
14343
14358
  return parsed;
@@ -14360,12 +14375,12 @@ function isLockStale2(meta2, opts) {
14360
14375
  function tryAcquireOnce2(lockPath, meta2, opts) {
14361
14376
  for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
14362
14377
  try {
14363
- fs27.mkdirSync(path26.dirname(lockPath), { recursive: true });
14364
- const fd = fs27.openSync(lockPath, "wx", 384);
14378
+ fs28.mkdirSync(path27.dirname(lockPath), { recursive: true });
14379
+ const fd = fs28.openSync(lockPath, "wx", 384);
14365
14380
  try {
14366
- fs27.writeSync(fd, JSON.stringify(meta2));
14381
+ fs28.writeSync(fd, JSON.stringify(meta2));
14367
14382
  } finally {
14368
- fs27.closeSync(fd);
14383
+ fs28.closeSync(fd);
14369
14384
  }
14370
14385
  return true;
14371
14386
  } catch (err) {
@@ -14383,9 +14398,9 @@ function tryAcquireOnce2(lockPath, meta2, opts) {
14383
14398
  }
14384
14399
  const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
14385
14400
  try {
14386
- fs27.renameSync(lockPath, victimPath);
14401
+ fs28.renameSync(lockPath, victimPath);
14387
14402
  try {
14388
- fs27.unlinkSync(victimPath);
14403
+ fs28.unlinkSync(victimPath);
14389
14404
  } catch {
14390
14405
  }
14391
14406
  } catch (err) {
@@ -14417,7 +14432,7 @@ async function acquireSettingsJsonLock(options = {}) {
14417
14432
  lockPath,
14418
14433
  release: () => {
14419
14434
  try {
14420
- fs27.unlinkSync(lockPath);
14435
+ fs28.unlinkSync(lockPath);
14421
14436
  } catch {
14422
14437
  }
14423
14438
  }
@@ -14520,14 +14535,14 @@ var init_services_status = __esm({
14520
14535
 
14521
14536
  // ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
14522
14537
  import * as crypto5 from "node:crypto";
14523
- import * as fs28 from "node:fs";
14538
+ import * as fs29 from "node:fs";
14524
14539
  import * as os17 from "node:os";
14525
- import * as path27 from "node:path";
14540
+ import * as path28 from "node:path";
14526
14541
  function migrationSnapshotsDir2() {
14527
14542
  const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
14528
14543
  if (override && override.length > 0)
14529
14544
  return override;
14530
- return path27.join(os17.homedir(), ".olam", "state", "migration-snapshots");
14545
+ return path28.join(os17.homedir(), ".olam", "state", "migration-snapshots");
14531
14546
  }
14532
14547
  function writeMetaHooksSnapshot(originalSettings) {
14533
14548
  const snapshot = {
@@ -14538,11 +14553,11 @@ function writeMetaHooksSnapshot(originalSettings) {
14538
14553
  };
14539
14554
  const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
14540
14555
  const dir = migrationSnapshotsDir2();
14541
- fs28.mkdirSync(dir, { recursive: true });
14556
+ fs29.mkdirSync(dir, { recursive: true });
14542
14557
  const stamp = validated.takenAt.replace(/[:.]/g, "-");
14543
14558
  const rand = crypto5.randomBytes(3).toString("hex");
14544
- const file = path27.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
14545
- fs28.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
14559
+ const file = path28.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
14560
+ fs29.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
14546
14561
  return file;
14547
14562
  }
14548
14563
  var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
@@ -14909,44 +14924,44 @@ var init_markdown_merger = __esm({
14909
14924
  });
14910
14925
 
14911
14926
  // ../core/dist/skill-sync/managed-merge.js
14912
- import * as fs29 from "node:fs";
14913
- import * as path28 from "node:path";
14927
+ import * as fs30 from "node:fs";
14928
+ import * as path29 from "node:path";
14914
14929
  function materializeMergedSkill(opts) {
14915
14930
  const { sourceId, sourcePath, deployBasename, mergedContent, claudeDir: claudeDir2 } = opts;
14916
- const managedDir = path28.join(claudeDir2, ".olam-merged", sourceId, deployBasename);
14917
- const sourceRoot = path28.resolve(path28.join(claudeDir2, ".olam-merged", sourceId));
14918
- const managedResolved = path28.resolve(managedDir);
14919
- if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path28.sep))) {
14931
+ const managedDir = path29.join(claudeDir2, ".olam-merged", sourceId, deployBasename);
14932
+ const sourceRoot = path29.resolve(path29.join(claudeDir2, ".olam-merged", sourceId));
14933
+ const managedResolved = path29.resolve(managedDir);
14934
+ if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path29.sep))) {
14920
14935
  throw new Error(`[managed-merge] refusing to materialize: deployBasename "${deployBasename}" escapes managed root "${sourceRoot}" (resolved to "${managedResolved}")`);
14921
14936
  }
14922
- fs29.mkdirSync(managedDir, { recursive: true });
14923
- const skillMdPath = path28.join(managedDir, "SKILL.md");
14937
+ fs30.mkdirSync(managedDir, { recursive: true });
14938
+ const skillMdPath = path29.join(managedDir, "SKILL.md");
14924
14939
  const tmpPath = `${skillMdPath}.tmp-${process.pid}-${Date.now()}`;
14925
- fs29.writeFileSync(tmpPath, mergedContent);
14926
- fs29.renameSync(tmpPath, skillMdPath);
14927
- const baseEntries = fs29.readdirSync(sourcePath);
14940
+ fs30.writeFileSync(tmpPath, mergedContent);
14941
+ fs30.renameSync(tmpPath, skillMdPath);
14942
+ const baseEntries = fs30.readdirSync(sourcePath);
14928
14943
  for (const entry of baseEntries) {
14929
14944
  if (entry === "SKILL.md")
14930
14945
  continue;
14931
- const linkPath = path28.join(managedDir, entry);
14932
- const targetAbsolute = path28.join(sourcePath, entry);
14933
- const targetRelative = path28.relative(managedDir, targetAbsolute);
14946
+ const linkPath = path29.join(managedDir, entry);
14947
+ const targetAbsolute = path29.join(sourcePath, entry);
14948
+ const targetRelative = path29.relative(managedDir, targetAbsolute);
14934
14949
  try {
14935
- fs29.lstatSync(linkPath);
14936
- fs29.rmSync(linkPath, { recursive: true, force: true });
14950
+ fs30.lstatSync(linkPath);
14951
+ fs30.rmSync(linkPath, { recursive: true, force: true });
14937
14952
  } catch {
14938
14953
  }
14939
- fs29.symlinkSync(targetRelative, linkPath);
14954
+ fs30.symlinkSync(targetRelative, linkPath);
14940
14955
  }
14941
- const managedEntries = fs29.readdirSync(managedDir);
14956
+ const managedEntries = fs30.readdirSync(managedDir);
14942
14957
  const baseEntrySet = new Set(baseEntries);
14943
14958
  for (const entry of managedEntries) {
14944
14959
  if (entry === "SKILL.md")
14945
14960
  continue;
14946
14961
  if (!baseEntrySet.has(entry)) {
14947
- const stalePath = path28.join(managedDir, entry);
14962
+ const stalePath = path29.join(managedDir, entry);
14948
14963
  try {
14949
- fs29.rmSync(stalePath, { recursive: true, force: true });
14964
+ fs30.rmSync(stalePath, { recursive: true, force: true });
14950
14965
  } catch {
14951
14966
  }
14952
14967
  }
@@ -14954,7 +14969,7 @@ function materializeMergedSkill(opts) {
14954
14969
  return managedDir;
14955
14970
  }
14956
14971
  function cleanMergedDir(claudeDir2) {
14957
- fs29.rmSync(path28.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
14972
+ fs30.rmSync(path29.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
14958
14973
  }
14959
14974
  var init_managed_merge = __esm({
14960
14975
  "../core/dist/skill-sync/managed-merge.js"() {
@@ -15001,8 +15016,8 @@ var init_prefix_rules = __esm({
15001
15016
  });
15002
15017
 
15003
15018
  // ../core/dist/skill-sync/prefix-deploy.js
15004
- import * as fs30 from "node:fs";
15005
- import * as path29 from "node:path";
15019
+ import * as fs31 from "node:fs";
15020
+ import * as path30 from "node:path";
15006
15021
  function buildSourcePrefixMap(sources) {
15007
15022
  const byId = /* @__PURE__ */ new Map();
15008
15023
  const scopeById = /* @__PURE__ */ new Map();
@@ -15050,8 +15065,8 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
15050
15065
  continue;
15051
15066
  }
15052
15067
  if (artifact.kind === "skill") {
15053
- const skillMdPath = path29.join(artifact.sourcePath, "SKILL.md");
15054
- const content = fs30.readFileSync(skillMdPath);
15068
+ const skillMdPath = path30.join(artifact.sourcePath, "SKILL.md");
15069
+ const content = fs31.readFileSync(skillMdPath);
15055
15070
  const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
15056
15071
  const managedDir = materializeMergedSkill({
15057
15072
  sourceId: artifact.sourceId,
@@ -15063,7 +15078,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
15063
15078
  artifact.sourcePath = managedDir;
15064
15079
  artifact.deployBasename = renamed;
15065
15080
  } else {
15066
- const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs30.readFileSync(artifact.sourcePath);
15081
+ const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs31.readFileSync(artifact.sourcePath);
15067
15082
  const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
15068
15083
  artifact.resolvedContent = rewritten;
15069
15084
  artifact.deployBasename = renamed;
@@ -15115,12 +15130,12 @@ function sourceConfigPath(clonePath) {
15115
15130
  return join31(clonePath, "shared", "source-config.yaml");
15116
15131
  }
15117
15132
  function readSourceConfig(clonePath, sourceId) {
15118
- const path52 = sourceConfigPath(clonePath);
15119
- if (!existsSync31(path52))
15133
+ const path53 = sourceConfigPath(clonePath);
15134
+ if (!existsSync31(path53))
15120
15135
  return void 0;
15121
15136
  let raw;
15122
15137
  try {
15123
- raw = readFileSync29(path52, "utf-8");
15138
+ raw = readFileSync29(path53, "utf-8");
15124
15139
  } catch (err) {
15125
15140
  emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
15126
15141
  return void 0;
@@ -15199,16 +15214,16 @@ var init_resolve_source_config = __esm({
15199
15214
  });
15200
15215
 
15201
15216
  // ../core/dist/skill-sync/engine.js
15202
- import * as fs31 from "node:fs";
15217
+ import * as fs32 from "node:fs";
15203
15218
  import * as os18 from "node:os";
15204
- import * as path30 from "node:path";
15219
+ import * as path31 from "node:path";
15205
15220
  function resolveAtlasUser(override) {
15206
15221
  if (override)
15207
15222
  return override;
15208
- const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path30.join(os18.homedir(), ".claude");
15209
- const f = path30.join(claudeDir2, ".atlas-user");
15210
- if (fs31.existsSync(f)) {
15211
- return fs31.readFileSync(f, "utf-8").trim() || void 0;
15223
+ const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path31.join(os18.homedir(), ".claude");
15224
+ const f = path31.join(claudeDir2, ".atlas-user");
15225
+ if (fs32.existsSync(f)) {
15226
+ return fs32.readFileSync(f, "utf-8").trim() || void 0;
15212
15227
  }
15213
15228
  return void 0;
15214
15229
  }
@@ -15220,7 +15235,7 @@ async function syncSkills(opts = {}) {
15220
15235
  const perSource = [];
15221
15236
  for (const source of sources) {
15222
15237
  const clonePath = skillSourceClonePath(source.id);
15223
- if (!fs31.existsSync(clonePath))
15238
+ if (!fs32.existsSync(clonePath))
15224
15239
  continue;
15225
15240
  const { artifacts, subscription } = await withFileLock(clonePath, () => {
15226
15241
  const pinRef = projectOverride?.override.pin?.[source.id];
@@ -15260,7 +15275,7 @@ async function syncSkills(opts = {}) {
15260
15275
  const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
15261
15276
  const effectiveSources = sources.map((s) => {
15262
15277
  const clonePath = skillSourceClonePath(s.id);
15263
- const sourceConfig = fs31.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
15278
+ const sourceConfig = fs32.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
15264
15279
  const eff = resolveEffectivePrefix(s, sourceConfig);
15265
15280
  const entry = {
15266
15281
  id: s.id,
@@ -15363,13 +15378,13 @@ async function syncSkills(opts = {}) {
15363
15378
  let baseContent;
15364
15379
  let basePath;
15365
15380
  if (overlay.targetKind === "skill") {
15366
- basePath = path30.join(base.sourcePath, "SKILL.md");
15367
- baseContent = fs31.readFileSync(basePath, "utf-8");
15381
+ basePath = path31.join(base.sourcePath, "SKILL.md");
15382
+ baseContent = fs32.readFileSync(basePath, "utf-8");
15368
15383
  } else {
15369
15384
  basePath = base.sourcePath;
15370
- baseContent = fs31.readFileSync(basePath, "utf-8");
15385
+ baseContent = fs32.readFileSync(basePath, "utf-8");
15371
15386
  }
15372
- const overlayContent = fs31.readFileSync(overlay.sourcePath, "utf-8");
15387
+ const overlayContent = fs32.readFileSync(overlay.sourcePath, "utf-8");
15373
15388
  const label = `${overlay.sourceId}/${overlay.deployBasename}`;
15374
15389
  const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
15375
15390
  if ("error" in mergeResult) {
@@ -15430,7 +15445,7 @@ async function syncSkills(opts = {}) {
15430
15445
  summary.collisions = detectCollisions(baseArtifacts).collisions;
15431
15446
  return summary;
15432
15447
  }
15433
- const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path30.join(os18.homedir(), ".claude");
15448
+ const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path31.join(os18.homedir(), ".claude");
15434
15449
  const overlayReferences = scanOverlayReferences(claudeDirPath, SHIM_TARGETS.map((t) => t.basename));
15435
15450
  summary.deploy = deployArtifacts(baseArtifacts, {
15436
15451
  installedOlamVersion,
@@ -15456,19 +15471,19 @@ async function injectMetaHooksIntoSettings(opts) {
15456
15471
  const result = await withSettingsJsonLock(() => {
15457
15472
  let currentSettings = {};
15458
15473
  let settingsExisted = false;
15459
- if (fs31.existsSync(settingsFile)) {
15474
+ if (fs32.existsSync(settingsFile)) {
15460
15475
  settingsExisted = true;
15461
15476
  try {
15462
- const raw = fs31.readFileSync(settingsFile, "utf-8");
15477
+ const raw = fs32.readFileSync(settingsFile, "utf-8");
15463
15478
  currentSettings = raw.trim() ? JSON.parse(raw) : {};
15464
15479
  } catch {
15465
15480
  try {
15466
- const raw = fs31.readFileSync(settingsFile);
15467
- const bakDir = path30.join(path30.dirname(settingsFile), ".malformed-backups");
15468
- fs31.mkdirSync(bakDir, { recursive: true });
15481
+ const raw = fs32.readFileSync(settingsFile);
15482
+ const bakDir = path31.join(path31.dirname(settingsFile), ".malformed-backups");
15483
+ fs32.mkdirSync(bakDir, { recursive: true });
15469
15484
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
15470
- const bakFile = path30.join(bakDir, `settings.json.malformed.${stamp}.bak`);
15471
- fs31.writeFileSync(bakFile, raw, { mode: 384 });
15485
+ const bakFile = path31.join(bakDir, `settings.json.malformed.${stamp}.bak`);
15486
+ fs32.writeFileSync(bakFile, raw, { mode: 384 });
15472
15487
  snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
15473
15488
  } catch (bakErr) {
15474
15489
  snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
@@ -15518,10 +15533,10 @@ async function injectMetaHooksIntoSettings(opts) {
15518
15533
  } catch {
15519
15534
  }
15520
15535
  }
15521
- fs31.mkdirSync(path30.dirname(settingsFile), { recursive: true });
15536
+ fs32.mkdirSync(path31.dirname(settingsFile), { recursive: true });
15522
15537
  const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
15523
- fs31.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
15524
- fs31.renameSync(tmpPath, settingsFile);
15538
+ fs32.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
15539
+ fs32.renameSync(tmpPath, settingsFile);
15525
15540
  return inject;
15526
15541
  }, { reason: `syncSkills meta-hook injection (mode=${mode})` });
15527
15542
  return {
@@ -15562,19 +15577,19 @@ var init_engine = __esm({
15562
15577
  });
15563
15578
 
15564
15579
  // ../core/dist/skill-sync/shadow-backup-manager.js
15565
- import * as fs32 from "node:fs";
15566
- import * as path31 from "node:path";
15580
+ import * as fs33 from "node:fs";
15581
+ import * as path32 from "node:path";
15567
15582
  function listShadowBackups(opts = {}) {
15568
15583
  const claude = opts.claudeDirOverride ?? claudeDir();
15569
15584
  const now = opts.now ?? Date.now();
15570
15585
  const out = [];
15571
15586
  for (const bucket of SHADOW_BACKUP_BUCKETS) {
15572
- const bucketDir = path31.join(claude, bucket);
15573
- if (!fs32.existsSync(bucketDir))
15587
+ const bucketDir = path32.join(claude, bucket);
15588
+ if (!fs33.existsSync(bucketDir))
15574
15589
  continue;
15575
15590
  let entries;
15576
15591
  try {
15577
- entries = fs32.readdirSync(bucketDir);
15592
+ entries = fs33.readdirSync(bucketDir);
15578
15593
  } catch {
15579
15594
  continue;
15580
15595
  }
@@ -15585,10 +15600,10 @@ function listShadowBackups(opts = {}) {
15585
15600
  const epochSeconds = Number.parseInt(match[1], 10);
15586
15601
  if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
15587
15602
  continue;
15588
- const full = path31.join(bucketDir, name);
15603
+ const full = path32.join(bucketDir, name);
15589
15604
  let sizeBytes = 0;
15590
15605
  try {
15591
- const st = fs32.statSync(full);
15606
+ const st = fs33.statSync(full);
15592
15607
  if (st.isDirectory())
15593
15608
  continue;
15594
15609
  sizeBytes = st.size;
@@ -15601,7 +15616,7 @@ function listShadowBackups(opts = {}) {
15601
15616
  bucket,
15602
15617
  basename: name,
15603
15618
  originalBasename,
15604
- originalPath: path31.join(bucketDir, originalBasename),
15619
+ originalPath: path32.join(bucketDir, originalBasename),
15605
15620
  epochSeconds,
15606
15621
  ageMs: now - epochSeconds * 1e3,
15607
15622
  sizeBytes
@@ -15644,7 +15659,7 @@ function pruneShadowBackups(opts) {
15644
15659
  }
15645
15660
  if (!opts.dryRun) {
15646
15661
  try {
15647
- fs32.unlinkSync(b.path);
15662
+ fs33.unlinkSync(b.path);
15648
15663
  } catch {
15649
15664
  skipped.push(b);
15650
15665
  continue;
@@ -15655,24 +15670,24 @@ function pruneShadowBackups(opts) {
15655
15670
  return { deleted, skipped };
15656
15671
  }
15657
15672
  function restoreShadowBackup(opts) {
15658
- const abs = path31.resolve(opts.backupPath);
15659
- if (!fs32.existsSync(abs)) {
15673
+ const abs = path32.resolve(opts.backupPath);
15674
+ if (!fs33.existsSync(abs)) {
15660
15675
  throw new Error(`backup file not found: ${abs}`);
15661
15676
  }
15662
- const basename6 = path31.basename(abs);
15677
+ const basename6 = path32.basename(abs);
15663
15678
  const match = SHADOW_BACKUP_SUFFIX_RE.exec(basename6);
15664
15679
  if (!match) {
15665
15680
  throw new Error(`not a shadow-backup file (basename "${basename6}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
15666
15681
  }
15667
15682
  const originalBasename = basename6.slice(0, basename6.length - match[0].length);
15668
- const originalPath = path31.join(path31.dirname(abs), originalBasename);
15669
- if (fs32.existsSync(originalPath) && !opts.force) {
15683
+ const originalPath = path32.join(path32.dirname(abs), originalBasename);
15684
+ if (fs33.existsSync(originalPath) && !opts.force) {
15670
15685
  throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
15671
15686
  }
15672
- if (opts.force && fs32.existsSync(originalPath)) {
15673
- fs32.unlinkSync(originalPath);
15687
+ if (opts.force && fs33.existsSync(originalPath)) {
15688
+ fs33.unlinkSync(originalPath);
15674
15689
  }
15675
- fs32.renameSync(abs, originalPath);
15690
+ fs33.renameSync(abs, originalPath);
15676
15691
  return { restoredTo: originalPath };
15677
15692
  }
15678
15693
  var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
@@ -15686,14 +15701,14 @@ var init_shadow_backup_manager = __esm({
15686
15701
  });
15687
15702
 
15688
15703
  // ../core/dist/skill-sources/doctor-checks.js
15689
- import * as fs33 from "node:fs";
15690
- import * as path32 from "node:path";
15704
+ import * as fs34 from "node:fs";
15705
+ import * as path33 from "node:path";
15691
15706
  import * as os19 from "node:os";
15692
15707
  function claudeDirInternal3() {
15693
15708
  const override = process.env["OLAM_CLAUDE_DIR"];
15694
15709
  if (override && override.length > 0)
15695
15710
  return override;
15696
- return path32.join(os19.homedir(), ".claude");
15711
+ return path33.join(os19.homedir(), ".claude");
15697
15712
  }
15698
15713
  function checkStateFileParse() {
15699
15714
  const filePath = globalConfigPath();
@@ -15702,11 +15717,11 @@ function checkStateFileParse() {
15702
15717
  healthy: true,
15703
15718
  description: `~/.olam state file (${filePath})`
15704
15719
  };
15705
- if (!fs33.existsSync(filePath)) {
15720
+ if (!fs34.existsSync(filePath)) {
15706
15721
  result.details = ["(file does not yet exist \u2014 will be created on first write)"];
15707
15722
  return result;
15708
15723
  }
15709
- const raw = fs33.readFileSync(filePath, "utf-8");
15724
+ const raw = fs34.readFileSync(filePath, "utf-8");
15710
15725
  let parsed;
15711
15726
  try {
15712
15727
  parsed = JSON.parse(raw);
@@ -15716,8 +15731,8 @@ function checkStateFileParse() {
15716
15731
  result.details = [err instanceof Error ? err.message : String(err)];
15717
15732
  result.repair = () => {
15718
15733
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
15719
- fs33.renameSync(filePath, aside);
15720
- fs33.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
15734
+ fs34.renameSync(filePath, aside);
15735
+ fs34.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
15721
15736
  };
15722
15737
  return result;
15723
15738
  }
@@ -15728,7 +15743,7 @@ function checkStateFileParse() {
15728
15743
  result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
15729
15744
  result.repair = () => {
15730
15745
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
15731
- fs33.copyFileSync(filePath, aside);
15746
+ fs34.copyFileSync(filePath, aside);
15732
15747
  const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
15733
15748
  const next = {
15734
15749
  ...base,
@@ -15737,7 +15752,7 @@ function checkStateFileParse() {
15737
15752
  runbooks: [],
15738
15753
  skillSources: []
15739
15754
  };
15740
- fs33.writeFileSync(filePath, JSON.stringify(next, null, 2));
15755
+ fs34.writeFileSync(filePath, JSON.stringify(next, null, 2));
15741
15756
  };
15742
15757
  return result;
15743
15758
  }
@@ -15748,16 +15763,16 @@ function checkDanglingSymlinks() {
15748
15763
  const buckets = ["commands", "agents", "skills", "scripts", "rules"];
15749
15764
  const dangling = [];
15750
15765
  for (const bucket of buckets) {
15751
- const dir = path32.join(claude, bucket);
15752
- if (!fs33.existsSync(dir))
15766
+ const dir = path33.join(claude, bucket);
15767
+ if (!fs34.existsSync(dir))
15753
15768
  continue;
15754
- for (const name of fs33.readdirSync(dir)) {
15755
- const linkPath = path32.join(dir, name);
15769
+ for (const name of fs34.readdirSync(dir)) {
15770
+ const linkPath = path33.join(dir, name);
15756
15771
  try {
15757
- const lst = fs33.lstatSync(linkPath);
15772
+ const lst = fs34.lstatSync(linkPath);
15758
15773
  if (!lst.isSymbolicLink())
15759
15774
  continue;
15760
- if (!fs33.existsSync(linkPath)) {
15775
+ if (!fs34.existsSync(linkPath)) {
15761
15776
  dangling.push(linkPath);
15762
15777
  }
15763
15778
  } catch {
@@ -15775,7 +15790,7 @@ function checkDanglingSymlinks() {
15775
15790
  result.repair = () => {
15776
15791
  for (const p of dangling) {
15777
15792
  try {
15778
- fs33.unlinkSync(p);
15793
+ fs34.unlinkSync(p);
15779
15794
  } catch {
15780
15795
  }
15781
15796
  }
@@ -15790,19 +15805,19 @@ function checkOrphanedSnapshots() {
15790
15805
  healthy: true,
15791
15806
  description: `orphaned migration snapshots under ${dir}`
15792
15807
  };
15793
- if (!fs33.existsSync(dir)) {
15808
+ if (!fs34.existsSync(dir)) {
15794
15809
  return result;
15795
15810
  }
15796
15811
  const orphans = [];
15797
- for (const name of fs33.readdirSync(dir)) {
15812
+ for (const name of fs34.readdirSync(dir)) {
15798
15813
  if (!name.endsWith(".json"))
15799
15814
  continue;
15800
- const full = path32.join(dir, name);
15815
+ const full = path33.join(dir, name);
15801
15816
  try {
15802
- const stat = fs33.statSync(full);
15803
- if (!stat.isFile())
15817
+ const stat2 = fs34.statSync(full);
15818
+ if (!stat2.isFile())
15804
15819
  continue;
15805
- const raw = fs33.readFileSync(full, "utf-8");
15820
+ const raw = fs34.readFileSync(full, "utf-8");
15806
15821
  let parsed;
15807
15822
  try {
15808
15823
  parsed = JSON.parse(raw);
@@ -15827,7 +15842,7 @@ function checkOrphanedSnapshots() {
15827
15842
  result.repair = () => {
15828
15843
  for (const o of orphans) {
15829
15844
  try {
15830
- fs33.unlinkSync(o.path);
15845
+ fs34.unlinkSync(o.path);
15831
15846
  } catch {
15832
15847
  }
15833
15848
  }
@@ -15842,12 +15857,12 @@ function checkSentinelDrift() {
15842
15857
  healthy: true,
15843
15858
  description: `olam-skills sentinel block in ${filePath}`
15844
15859
  };
15845
- if (!fs33.existsSync(filePath)) {
15860
+ if (!fs34.existsSync(filePath)) {
15846
15861
  return result;
15847
15862
  }
15848
15863
  let parsed;
15849
15864
  try {
15850
- parsed = JSON.parse(fs33.readFileSync(filePath, "utf-8"));
15865
+ parsed = JSON.parse(fs34.readFileSync(filePath, "utf-8"));
15851
15866
  } catch {
15852
15867
  return result;
15853
15868
  }
@@ -15888,7 +15903,7 @@ function checkSentinelDrift() {
15888
15903
  backupSettings();
15889
15904
  } catch {
15890
15905
  }
15891
- const next = JSON.parse(fs33.readFileSync(filePath, "utf-8"));
15906
+ const next = JSON.parse(fs34.readFileSync(filePath, "utf-8"));
15892
15907
  if (!next.hooks)
15893
15908
  return;
15894
15909
  for (const stage of Object.keys(next.hooks)) {
@@ -15911,7 +15926,7 @@ function checkSentinelDrift() {
15911
15926
  return bad === void 0;
15912
15927
  });
15913
15928
  }
15914
- fs33.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
15929
+ fs34.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
15915
15930
  };
15916
15931
  }
15917
15932
  return result;
@@ -15935,8 +15950,8 @@ function checkMemberNameMissing() {
15935
15950
  return result;
15936
15951
  }
15937
15952
  const claudeDir2 = claudeDirInternal3();
15938
- const atlasUserPath = path32.join(claudeDir2, ".atlas-user");
15939
- const value = fs33.existsSync(atlasUserPath) ? fs33.readFileSync(atlasUserPath, "utf-8").trim() : "";
15953
+ const atlasUserPath = path33.join(claudeDir2, ".atlas-user");
15954
+ const value = fs34.existsSync(atlasUserPath) ? fs34.readFileSync(atlasUserPath, "utf-8").trim() : "";
15940
15955
  if (value.length > 0) {
15941
15956
  result.details = [`atlas-user: ${value}`];
15942
15957
  return result;
@@ -15944,10 +15959,10 @@ function checkMemberNameMissing() {
15944
15959
  result.healthy = false;
15945
15960
  result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
15946
15961
  const clonePath = skillSourceClonePath(atlasSource.id);
15947
- const membersDir = path32.join(clonePath, "members");
15948
- const existing = fs33.existsSync(membersDir) ? fs33.readdirSync(membersDir).filter((e) => {
15962
+ const membersDir = path33.join(clonePath, "members");
15963
+ const existing = fs34.existsSync(membersDir) ? fs34.readdirSync(membersDir).filter((e) => {
15949
15964
  try {
15950
- return fs33.statSync(path32.join(membersDir, e)).isDirectory();
15965
+ return fs34.statSync(path33.join(membersDir, e)).isDirectory();
15951
15966
  } catch {
15952
15967
  return false;
15953
15968
  }
@@ -15961,8 +15976,8 @@ function checkMemberNameMissing() {
15961
15976
  }
15962
15977
  function checkMemberOverlayDrift() {
15963
15978
  const claudeDir2 = claudeDirInternal3();
15964
- const atlasUserPath = path32.join(claudeDir2, ".atlas-user");
15965
- const atlasUser = fs33.existsSync(atlasUserPath) ? fs33.readFileSync(atlasUserPath, "utf-8").trim() : "";
15979
+ const atlasUserPath = path33.join(claudeDir2, ".atlas-user");
15980
+ const atlasUser = fs34.existsSync(atlasUserPath) ? fs34.readFileSync(atlasUserPath, "utf-8").trim() : "";
15966
15981
  if (atlasUser.length === 0) {
15967
15982
  return [];
15968
15983
  }
@@ -15978,26 +15993,26 @@ function checkMemberOverlayDrift() {
15978
15993
  const clonePath = skillSourceClonePath(atlasSource.id);
15979
15994
  const results = [];
15980
15995
  for (const kind of ["skills", "agents"]) {
15981
- const localRoot = path32.join(claudeDir2, `${kind}.overrides`);
15982
- if (!fs33.existsSync(localRoot))
15996
+ const localRoot = path33.join(claudeDir2, `${kind}.overrides`);
15997
+ if (!fs34.existsSync(localRoot))
15983
15998
  continue;
15984
15999
  let entries;
15985
16000
  try {
15986
- entries = fs33.readdirSync(localRoot);
16001
+ entries = fs34.readdirSync(localRoot);
15987
16002
  } catch {
15988
16003
  continue;
15989
16004
  }
15990
16005
  for (const entry of entries) {
15991
- const localFile = path32.join(localRoot, entry);
15992
- let stat;
16006
+ const localFile = path33.join(localRoot, entry);
16007
+ let stat2;
15993
16008
  try {
15994
- stat = fs33.statSync(localFile);
16009
+ stat2 = fs34.statSync(localFile);
15995
16010
  } catch {
15996
16011
  continue;
15997
16012
  }
15998
- if (!stat.isFile())
16013
+ if (!stat2.isFile())
15999
16014
  continue;
16000
- const cloneFile = path32.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
16015
+ const cloneFile = path33.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
16001
16016
  const localSha = sha256OfPath(localFile);
16002
16017
  const cloneSha = sha256OfPath(cloneFile);
16003
16018
  if (localSha === cloneSha) {
@@ -16421,10 +16436,10 @@ function mergeDefs(...defs) {
16421
16436
  function cloneDef(schema) {
16422
16437
  return mergeDefs(schema._zod.def);
16423
16438
  }
16424
- function getElementAtPath(obj, path52) {
16425
- if (!path52)
16439
+ function getElementAtPath(obj, path53) {
16440
+ if (!path53)
16426
16441
  return obj;
16427
- return path52.reduce((acc, key) => acc?.[key], obj);
16442
+ return path53.reduce((acc, key) => acc?.[key], obj);
16428
16443
  }
16429
16444
  function promiseAllObject(promisesObj) {
16430
16445
  const keys = Object.keys(promisesObj);
@@ -16833,11 +16848,11 @@ function explicitlyAborted(x, startIndex = 0) {
16833
16848
  }
16834
16849
  return false;
16835
16850
  }
16836
- function prefixIssues(path52, issues) {
16851
+ function prefixIssues(path53, issues) {
16837
16852
  return issues.map((iss) => {
16838
16853
  var _a3;
16839
16854
  (_a3 = iss).path ?? (_a3.path = []);
16840
- iss.path.unshift(path52);
16855
+ iss.path.unshift(path53);
16841
16856
  return iss;
16842
16857
  });
16843
16858
  }
@@ -16984,16 +16999,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
16984
16999
  }
16985
17000
  function formatError(error2, mapper = (issue2) => issue2.message) {
16986
17001
  const fieldErrors = { _errors: [] };
16987
- const processError = (error3, path52 = []) => {
17002
+ const processError = (error3, path53 = []) => {
16988
17003
  for (const issue2 of error3.issues) {
16989
17004
  if (issue2.code === "invalid_union" && issue2.errors.length) {
16990
- issue2.errors.map((issues) => processError({ issues }, [...path52, ...issue2.path]));
17005
+ issue2.errors.map((issues) => processError({ issues }, [...path53, ...issue2.path]));
16991
17006
  } else if (issue2.code === "invalid_key") {
16992
- processError({ issues: issue2.issues }, [...path52, ...issue2.path]);
17007
+ processError({ issues: issue2.issues }, [...path53, ...issue2.path]);
16993
17008
  } else if (issue2.code === "invalid_element") {
16994
- processError({ issues: issue2.issues }, [...path52, ...issue2.path]);
17009
+ processError({ issues: issue2.issues }, [...path53, ...issue2.path]);
16995
17010
  } else {
16996
- const fullpath = [...path52, ...issue2.path];
17011
+ const fullpath = [...path53, ...issue2.path];
16997
17012
  if (fullpath.length === 0) {
16998
17013
  fieldErrors._errors.push(mapper(issue2));
16999
17014
  } else {
@@ -23210,12 +23225,12 @@ var StdioServerTransport = class {
23210
23225
  this.onclose?.();
23211
23226
  }
23212
23227
  send(message) {
23213
- return new Promise((resolve14) => {
23228
+ return new Promise((resolve15) => {
23214
23229
  const json = serializeMessage(message);
23215
23230
  if (this._stdout.write(json)) {
23216
- resolve14();
23231
+ resolve15();
23217
23232
  } else {
23218
- this._stdout.once("drain", resolve14);
23233
+ this._stdout.once("drain", resolve15);
23219
23234
  }
23220
23235
  });
23221
23236
  }
@@ -25252,7 +25267,7 @@ var Protocol = class {
25252
25267
  return;
25253
25268
  }
25254
25269
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
25255
- await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
25270
+ await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
25256
25271
  options?.signal?.throwIfAborted();
25257
25272
  }
25258
25273
  } catch (error2) {
@@ -25269,7 +25284,7 @@ var Protocol = class {
25269
25284
  */
25270
25285
  request(request2, resultSchema, options) {
25271
25286
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
25272
- return new Promise((resolve14, reject2) => {
25287
+ return new Promise((resolve15, reject2) => {
25273
25288
  const earlyReject = (error2) => {
25274
25289
  reject2(error2);
25275
25290
  };
@@ -25347,7 +25362,7 @@ var Protocol = class {
25347
25362
  if (!parseResult.success) {
25348
25363
  reject2(parseResult.error);
25349
25364
  } else {
25350
- resolve14(parseResult.data);
25365
+ resolve15(parseResult.data);
25351
25366
  }
25352
25367
  } catch (error2) {
25353
25368
  reject2(error2);
@@ -25608,12 +25623,12 @@ var Protocol = class {
25608
25623
  }
25609
25624
  } catch {
25610
25625
  }
25611
- return new Promise((resolve14, reject2) => {
25626
+ return new Promise((resolve15, reject2) => {
25612
25627
  if (signal.aborted) {
25613
25628
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
25614
25629
  return;
25615
25630
  }
25616
- const timeoutId = setTimeout(resolve14, interval);
25631
+ const timeoutId = setTimeout(resolve15, interval);
25617
25632
  signal.addEventListener("abort", () => {
25618
25633
  clearTimeout(timeoutId);
25619
25634
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -26935,7 +26950,7 @@ var McpServer = class {
26935
26950
  let task = createTaskResult.task;
26936
26951
  const pollInterval = task.pollInterval ?? 5e3;
26937
26952
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
26938
- await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
26953
+ await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
26939
26954
  const updatedTask = await extra.taskStore.getTask(taskId);
26940
26955
  if (!updatedTask) {
26941
26956
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -27527,6 +27542,59 @@ var EMPTY_COMPLETION_RESULT = {
27527
27542
  }
27528
27543
  };
27529
27544
 
27545
+ // ../mcp-server/src/tool-filter.ts
27546
+ function getToolFilterContextFromEnv() {
27547
+ const raw = process.env.OLAM_ALLOWED_TOOLS;
27548
+ const worldId = process.env.OLAM_WORLD_ID;
27549
+ const context = {};
27550
+ if (worldId && worldId.trim() !== "") {
27551
+ context.worldId = worldId;
27552
+ }
27553
+ if (raw && raw.trim() !== "") {
27554
+ const allowedTools = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
27555
+ if (allowedTools.length > 0) {
27556
+ context.allowedTools = allowedTools;
27557
+ }
27558
+ }
27559
+ return context;
27560
+ }
27561
+ function withFilteredTools(server, context) {
27562
+ const allowed = context.allowedTools;
27563
+ if (!allowed || allowed.length === 0) {
27564
+ return { server, finalize: () => {
27565
+ } };
27566
+ }
27567
+ const allowedSet = new Set(allowed);
27568
+ const registered = /* @__PURE__ */ new Set();
27569
+ const host = server;
27570
+ const original = host.tool;
27571
+ const filtered = function(name, ...rest) {
27572
+ if (typeof name === "string" && allowedSet.has(name)) {
27573
+ registered.add(name);
27574
+ return original.apply(
27575
+ server,
27576
+ [name, ...rest]
27577
+ );
27578
+ }
27579
+ return void 0;
27580
+ };
27581
+ host.tool = filtered;
27582
+ return {
27583
+ server,
27584
+ finalize: () => {
27585
+ host.tool = original;
27586
+ for (const name of allowedSet) {
27587
+ if (!registered.has(name)) {
27588
+ process.stderr.write(
27589
+ `[tool-filter] warning: unknown tool name in OLAM_ALLOWED_TOOLS: "${name}"
27590
+ `
27591
+ );
27592
+ }
27593
+ }
27594
+ }
27595
+ };
27596
+ }
27597
+
27530
27598
  // ../mcp-server/src/tools/init.ts
27531
27599
  var init_exports = {};
27532
27600
  __export(init_exports, {
@@ -27728,6 +27796,7 @@ To reinitialize, delete .olam/ first.`
27728
27796
  // ../mcp-server/src/tools/auth.ts
27729
27797
  var auth_exports = {};
27730
27798
  __export(auth_exports, {
27799
+ formatAccountFlag: () => formatAccountFlag,
27731
27800
  register: () => register2
27732
27801
  });
27733
27802
  init_v3();
@@ -27878,8 +27947,8 @@ var AuthClient = class {
27878
27947
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
27879
27948
  }
27880
27949
  }
27881
- async request(method, path52, body, attempt = 0) {
27882
- const url2 = `${this.baseUrl}${path52}`;
27950
+ async request(method, path53, body, attempt = 0) {
27951
+ const url2 = `${this.baseUrl}${path53}`;
27883
27952
  const controller = new AbortController();
27884
27953
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
27885
27954
  const headers = {};
@@ -27897,7 +27966,7 @@ var AuthClient = class {
27897
27966
  } catch (err) {
27898
27967
  if (attempt < RETRY_COUNT && isTransient(err)) {
27899
27968
  await sleep(RETRY_BACKOFF_MS * (attempt + 1));
27900
- return this.request(method, path52, body, attempt + 1);
27969
+ return this.request(method, path53, body, attempt + 1);
27901
27970
  }
27902
27971
  throw err;
27903
27972
  } finally {
@@ -27924,7 +27993,7 @@ async function safeText(res) {
27924
27993
  }
27925
27994
  }
27926
27995
  function sleep(ms) {
27927
- return new Promise((resolve14) => setTimeout(resolve14, ms));
27996
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
27928
27997
  }
27929
27998
 
27930
27999
  // ../core/dist/auth/container.js
@@ -28056,7 +28125,7 @@ function resolveAuthServicePath() {
28056
28125
  return path3.join(pkgsDir, "auth-service");
28057
28126
  }
28058
28127
  function sleep2(ms) {
28059
- return new Promise((resolve14) => setTimeout(resolve14, ms));
28128
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
28060
28129
  }
28061
28130
 
28062
28131
  // ../core/dist/auth/preflight.js
@@ -28134,6 +28203,21 @@ function describe2(err) {
28134
28203
  }
28135
28204
 
28136
28205
  // ../mcp-server/src/tools/auth.ts
28206
+ function formatAccountFlag(a, now = Date.now()) {
28207
+ if (a.state === "disabled") return "disabled";
28208
+ if (a.state === "usage-capped") {
28209
+ if (a.weeklyResetsAt && new Date(a.weeklyResetsAt).getTime() > now) {
28210
+ return "weekly limit";
28211
+ }
28212
+ return "usage cap";
28213
+ }
28214
+ if (a.state === "cooldown") return "rate-limited";
28215
+ if (a.state === "expired") return "expired";
28216
+ if (a.state === "active") return "valid";
28217
+ if (a.rateLimited) return "rate-limited";
28218
+ if (!a.tokenValid) return "expired";
28219
+ return "valid";
28220
+ }
28137
28221
  function register2(server, _ctx, _initError) {
28138
28222
  server.tool(
28139
28223
  "olam_auth_status",
@@ -28156,7 +28240,7 @@ function register2(server, _ctx, _initError) {
28156
28240
  lines.push(" (none \u2014 run olam_auth_login)");
28157
28241
  } else {
28158
28242
  for (const a of status2.accounts) {
28159
- const flag = a.tokenValid ? "valid" : a.rateLimited ? "rate-limited" : "expired";
28243
+ const flag = formatAccountFlag(a);
28160
28244
  lines.push(` - ${a.id.padEnd(20)} ${flag.padEnd(14)} expires in ${a.expiresIn}`);
28161
28245
  }
28162
28246
  }
@@ -28347,7 +28431,8 @@ function rowToMetadata(row) {
28347
28431
  ...expectedServices !== void 0 ? { expectedServices } : {},
28348
28432
  ...appPortUrls !== void 0 ? { appPortUrls } : {},
28349
28433
  ...worldDbNames !== void 0 ? { worldDbNames } : {},
28350
- ...row.world_role_name ? { worldRoleName: row.world_role_name } : {}
28434
+ ...row.world_role_name ? { worldRoleName: row.world_role_name } : {},
28435
+ ...row.claude_home ? { claudeHome: row.claude_home } : {}
28351
28436
  };
28352
28437
  }
28353
28438
  var SCHEMA_VERSION = "1";
@@ -28402,7 +28487,9 @@ var WorldRegistry = class {
28402
28487
  // world_db_names (SQLite has no native array; matches repos column shape).
28403
28488
  // TEXT[] would fail at DDL time (closes OQ13/OQ22 / FS-03).
28404
28489
  "world_db_names TEXT",
28405
- "world_role_name TEXT"
28490
+ "world_role_name TEXT",
28491
+ // ADR 045 — per-world Claude Code HOME path. Additive migration.
28492
+ "claude_home TEXT"
28406
28493
  ]) {
28407
28494
  try {
28408
28495
  this.db.exec(`ALTER TABLE worlds ADD COLUMN ${col}`);
@@ -28433,8 +28520,8 @@ var WorldRegistry = class {
28433
28520
  compute_provider, total_cost_usd, thought_count, created_at, updated_at,
28434
28521
  pr_url, pr_number, pr_repo, pr_created_at, pr_state, pr_merged_at, auto_destroy_on_merge,
28435
28522
  readiness_chain, expected_services, app_port_urls,
28436
- world_db_names, world_role_name)
28437
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(world.id, world.name, world.status, JSON.stringify(world.repos), world.branch, world.portOffset, world.workspacePath, world.computeProvider, world.totalCostUsd, world.thoughtCount, world.createdAt, world.updatedAt, world.prUrl ?? null, world.prNumber ?? null, world.prRepo ?? null, world.prCreatedAt ?? null, world.prState ?? "none", world.prMergedAt ?? null, world.autoDestroyOnMerge === false ? 0 : 1, world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null, world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null, world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null, world.worldDbNames !== void 0 ? JSON.stringify(world.worldDbNames) : null, world.worldRoleName ?? null);
28523
+ world_db_names, world_role_name, claude_home)
28524
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(world.id, world.name, world.status, JSON.stringify(world.repos), world.branch, world.portOffset, world.workspacePath, world.computeProvider, world.totalCostUsd, world.thoughtCount, world.createdAt, world.updatedAt, world.prUrl ?? null, world.prNumber ?? null, world.prRepo ?? null, world.prCreatedAt ?? null, world.prState ?? "none", world.prMergedAt ?? null, world.autoDestroyOnMerge === false ? 0 : 1, world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null, world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null, world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null, world.worldDbNames !== void 0 ? JSON.stringify(world.worldDbNames) : null, world.worldRoleName ?? null, world.claudeHome ?? null);
28438
28525
  }
28439
28526
  update(worldId, updates) {
28440
28527
  const setClauses = [];
@@ -28462,7 +28549,9 @@ var WorldRegistry = class {
28462
28549
  appPortUrls: "app_port_urls",
28463
28550
  // olam-hybrid-shared-postgres Phase A task A7.
28464
28551
  worldDbNames: "world_db_names",
28465
- worldRoleName: "world_role_name"
28552
+ worldRoleName: "world_role_name",
28553
+ // ADR 045 — per-world Claude Code HOME (multi-account isolation).
28554
+ claudeHome: "claude_home"
28466
28555
  };
28467
28556
  const jsonColumns = /* @__PURE__ */ new Set(["repos", "readinessChain", "expectedServices", "appPortUrls", "worldDbNames"]);
28468
28557
  for (const [key, col] of Object.entries(columnMap)) {
@@ -28751,12 +28840,12 @@ function register3(server, _ctx, _initError) {
28751
28840
  registry2.close();
28752
28841
  }
28753
28842
  try {
28754
- const { default: fs51 } = await import("node:fs");
28843
+ const { default: fs52 } = await import("node:fs");
28755
28844
  const { default: os31 } = await import("node:os");
28756
- const { default: path52 } = await import("node:path");
28757
- const tokenPath = path52.join(os31.homedir(), ".olam", "host-cp.token");
28758
- if (fs51.existsSync(tokenPath)) {
28759
- const token = fs51.readFileSync(tokenPath, "utf-8").trim();
28845
+ const { default: path53 } = await import("node:path");
28846
+ const tokenPath = path53.join(os31.homedir(), ".olam", "host-cp.token");
28847
+ if (fs52.existsSync(tokenPath)) {
28848
+ const token = fs52.readFileSync(tokenPath, "utf-8").trim();
28760
28849
  await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
28761
28850
  method: "POST",
28762
28851
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
@@ -29176,10 +29265,10 @@ function extractMcpConfig(claudeJsonPath) {
29176
29265
  }
29177
29266
  return { mcpServers, secrets };
29178
29267
  }
29179
- function readOptional(path52) {
29180
- if (!existsSync6(path52)) return null;
29268
+ function readOptional(path53) {
29269
+ if (!existsSync6(path53)) return null;
29181
29270
  try {
29182
- return readFileSync5(path52, "utf8");
29271
+ return readFileSync5(path53, "utf8");
29183
29272
  } catch {
29184
29273
  return null;
29185
29274
  }
@@ -29304,7 +29393,7 @@ var realDocker = {
29304
29393
  }
29305
29394
  };
29306
29395
  function spawnAsync(cmd, args, opts = {}) {
29307
- return new Promise((resolve14) => {
29396
+ return new Promise((resolve15) => {
29308
29397
  const child = spawn(cmd, [...args], {
29309
29398
  stdio: ["ignore", "pipe", "pipe"],
29310
29399
  signal: opts.signal
@@ -29318,10 +29407,10 @@ function spawnAsync(cmd, args, opts = {}) {
29318
29407
  stderr += chunk.toString();
29319
29408
  });
29320
29409
  child.on("error", (err) => {
29321
- resolve14({ exitCode: -1, stdout, stderr: stderr + err.message });
29410
+ resolve15({ exitCode: -1, stdout, stderr: stderr + err.message });
29322
29411
  });
29323
29412
  child.on("close", (code) => {
29324
- resolve14({ exitCode: code ?? -1, stdout, stderr });
29413
+ resolve15({ exitCode: code ?? -1, stdout, stderr });
29325
29414
  });
29326
29415
  });
29327
29416
  }
@@ -29772,7 +29861,7 @@ var stopAndRemove = async (container) => {
29772
29861
 
29773
29862
  // ../adapters/dist/docker/exec.js
29774
29863
  import { PassThrough } from "node:stream";
29775
- var demuxStream = (stream) => new Promise((resolve14, reject2) => {
29864
+ var demuxStream = (stream) => new Promise((resolve15, reject2) => {
29776
29865
  const stdoutChunks = [];
29777
29866
  const stderrChunks = [];
29778
29867
  const stdout = new PassThrough();
@@ -29786,7 +29875,7 @@ var demuxStream = (stream) => new Promise((resolve14, reject2) => {
29786
29875
  stream.pipe(stdout);
29787
29876
  }
29788
29877
  stream.on("end", () => {
29789
- resolve14({
29878
+ resolve15({
29790
29879
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
29791
29880
  stderr: Buffer.concat(stderrChunks).toString("utf-8")
29792
29881
  });
@@ -30159,7 +30248,7 @@ var SSHConnectionPool = class {
30159
30248
  // -----------------------------------------------------------------------
30160
30249
  async exec(host, command) {
30161
30250
  const client = await this.getConnection(host);
30162
- return new Promise((resolve14, reject2) => {
30251
+ return new Promise((resolve15, reject2) => {
30163
30252
  client.exec(command, (err, stream) => {
30164
30253
  if (err) {
30165
30254
  reject2(new Error(`SSH exec failed on ${host}: ${err.message}`));
@@ -30174,7 +30263,7 @@ var SSHConnectionPool = class {
30174
30263
  stderr += data.toString();
30175
30264
  });
30176
30265
  stream.on("close", (code) => {
30177
- resolve14({
30266
+ resolve15({
30178
30267
  exitCode: code ?? 0,
30179
30268
  stdout: stdout.trimEnd(),
30180
30269
  stderr: stderr.trimEnd()
@@ -30205,10 +30294,10 @@ var SSHConnectionPool = class {
30205
30294
  throw new Error(`No SSH configuration found for host: ${host}`);
30206
30295
  }
30207
30296
  const client = new SSHClient();
30208
- return new Promise((resolve14, reject2) => {
30297
+ return new Promise((resolve15, reject2) => {
30209
30298
  client.on("ready", () => {
30210
30299
  this.connections.set(host, client);
30211
- resolve14(client);
30300
+ resolve15(client);
30212
30301
  }).on("error", (err) => {
30213
30302
  this.connections.delete(host);
30214
30303
  reject2(new Error(`SSH connection to ${host} failed: ${err.message}`));
@@ -30625,8 +30714,8 @@ var CloudflareProvider = class extends ComputeProvider {
30625
30714
  // -----------------------------------------------------------------------
30626
30715
  // Internal fetch helper
30627
30716
  // -----------------------------------------------------------------------
30628
- async request(path52, method, body) {
30629
- const url2 = `${this.config.workerUrl}${path52}`;
30717
+ async request(path53, method, body) {
30718
+ const url2 = `${this.config.workerUrl}${path53}`;
30630
30719
  const bearer = await this.config.mintToken();
30631
30720
  const headers = {
30632
30721
  Authorization: `Bearer ${bearer}`
@@ -30902,6 +30991,10 @@ function selectComputeProvider(config2, env) {
30902
30991
  throw new Error(
30903
30992
  "Compute provider 'e2b' is not implemented. Use 'docker', 'ssh', or 'cloudflare'."
30904
30993
  );
30994
+ case "cloudflare-isolate":
30995
+ throw new Error(
30996
+ "Compute provider 'cloudflare-isolate' is not yet wired for world dispatch. v1 ships the substrate (@olam/worker-runner-cloudflare-isolate) for direct POST /lookup invocation; per-world tier selection arrives in a follow-up PR (see docs/decisions/022-v8-isolate-runtime-tier.md \xA7Consequences)."
30997
+ );
30905
30998
  case "docker":
30906
30999
  return new DockerProvider(resolveDockerHostOptions());
30907
31000
  default: {
@@ -31188,7 +31281,7 @@ function register6(server, ctx, initError) {
31188
31281
  }
31189
31282
  } catch {
31190
31283
  }
31191
- await new Promise((resolve14) => setTimeout(resolve14, POLL_INTERVAL_MS));
31284
+ await new Promise((resolve15) => setTimeout(resolve15, POLL_INTERVAL_MS));
31192
31285
  }
31193
31286
  }
31194
31287
  if (authenticated) {
@@ -31318,6 +31411,8 @@ function formatAge(createdAt) {
31318
31411
  // ../mcp-server/src/tools/world-dispatch.ts
31319
31412
  var world_dispatch_exports = {};
31320
31413
  __export(world_dispatch_exports, {
31414
+ dispatchInputObject: () => dispatchInputObject,
31415
+ dispatchInputSchema: () => dispatchInputSchema,
31321
31416
  register: () => register9
31322
31417
  });
31323
31418
  init_v3();
@@ -31905,17 +32000,17 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
31905
32000
  const srcPath = path10.join(src, name);
31906
32001
  const destPath = path10.join(dest, name);
31907
32002
  if (entry.isSymbolicLink()) {
31908
- let stat;
32003
+ let stat2;
31909
32004
  try {
31910
- stat = fs8.statSync(srcPath);
32005
+ stat2 = fs8.statSync(srcPath);
31911
32006
  } catch {
31912
32007
  continue;
31913
32008
  }
31914
- if (stat.isDirectory()) {
32009
+ if (stat2.isDirectory()) {
31915
32010
  if (SKIP_DIRS_ANYWHERE.has(name))
31916
32011
  continue;
31917
32012
  copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
31918
- } else if (stat.isFile()) {
32013
+ } else if (stat2.isFile()) {
31919
32014
  fs8.copyFileSync(srcPath, destPath);
31920
32015
  }
31921
32016
  } else if (entry.isDirectory()) {
@@ -32078,9 +32173,9 @@ function buildRepoEnvBundle(repoName, serviceEnv, crossRepoEnv, envOverrides) {
32078
32173
  const merged = { ...serviceEnv, ...injectables };
32079
32174
  return { merged, injectables };
32080
32175
  }
32081
- function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, configCtx) {
32176
+ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, configCtx, claudeHomeOverride) {
32082
32177
  try {
32083
- copyClaudeConfig(workspacePath, void 0, configCtx);
32178
+ copyClaudeConfig(workspacePath, claudeHomeOverride, configCtx);
32084
32179
  } catch {
32085
32180
  }
32086
32181
  if (configCtx) {
@@ -32173,19 +32268,278 @@ function applyEnvOverrides(repoPath, overrides) {
32173
32268
  }
32174
32269
  }
32175
32270
 
32271
+ // ../mcp-server/src/dispatch/goal-verifier.ts
32272
+ init_v3();
32273
+ import * as fs9 from "node:fs/promises";
32274
+ import * as path11 from "node:path";
32275
+ import { spawn as spawn2 } from "node:child_process";
32276
+ var GoalSpecSchema = external_exports.object({
32277
+ type: external_exports.enum([
32278
+ "pr-merged",
32279
+ "pr-green",
32280
+ "file-exists",
32281
+ "test-passes",
32282
+ "comment-posted"
32283
+ ]),
32284
+ spec: external_exports.string().min(1).describe(
32285
+ "Type-specific spec: PR number, file path, test name, or comment marker"
32286
+ ),
32287
+ timeoutMinutes: external_exports.number().int().min(1).max(720).default(90)
32288
+ }).describe(
32289
+ "Optional structured completion condition; when set, the world loops between turns checking this until met or timeout"
32290
+ );
32291
+ async function defaultExecGh(args) {
32292
+ return new Promise((resolve15) => {
32293
+ const child = spawn2("gh", [...args], {
32294
+ stdio: ["ignore", "pipe", "pipe"]
32295
+ });
32296
+ let stdout = "";
32297
+ let stderr = "";
32298
+ child.stdout.on("data", (chunk) => {
32299
+ stdout += chunk.toString("utf8");
32300
+ });
32301
+ child.stderr.on("data", (chunk) => {
32302
+ stderr += chunk.toString("utf8");
32303
+ });
32304
+ child.on("close", (code) => {
32305
+ resolve15({ stdout, stderr, exitCode: code ?? 1 });
32306
+ });
32307
+ child.on("error", (err) => {
32308
+ resolve15({
32309
+ stdout: "",
32310
+ stderr: err instanceof Error ? err.message : String(err),
32311
+ exitCode: 1
32312
+ });
32313
+ });
32314
+ });
32315
+ }
32316
+ async function defaultExecVitest(testNamePattern, cwd) {
32317
+ return new Promise((resolve15) => {
32318
+ const child = spawn2(
32319
+ "npx",
32320
+ [
32321
+ "vitest",
32322
+ "run",
32323
+ "--reporter=basic",
32324
+ "--testNamePattern",
32325
+ testNamePattern
32326
+ ],
32327
+ { cwd, stdio: ["ignore", "pipe", "pipe"] }
32328
+ );
32329
+ child.on("close", (code) => {
32330
+ resolve15({ exitCode: code ?? 1 });
32331
+ });
32332
+ child.on("error", () => {
32333
+ resolve15({ exitCode: 1 });
32334
+ });
32335
+ });
32336
+ }
32337
+ async function verifyGoal(goal, worldId, opts = {}) {
32338
+ const execGh = opts.execGh ?? defaultExecGh;
32339
+ const execVitest = opts.execVitest ?? defaultExecVitest;
32340
+ const statFn = opts.fsStat ?? fs9.stat;
32341
+ const workspaceRoot = opts.workspaceRoot ?? process.cwd();
32342
+ try {
32343
+ switch (goal.type) {
32344
+ case "pr-merged":
32345
+ return await verifyPrMerged(goal.spec, execGh);
32346
+ case "pr-green":
32347
+ return await verifyPrGreen(goal.spec, execGh);
32348
+ case "file-exists":
32349
+ return await verifyFileExists(goal.spec, workspaceRoot, statFn);
32350
+ case "test-passes":
32351
+ return await verifyTestPasses(goal.spec, workspaceRoot, execVitest);
32352
+ case "comment-posted":
32353
+ return await verifyCommentPosted(goal.spec, worldId, execGh);
32354
+ default: {
32355
+ const _exhaustive = goal.type;
32356
+ return {
32357
+ met: false,
32358
+ details: `unknown goal type: ${String(_exhaustive)}`
32359
+ };
32360
+ }
32361
+ }
32362
+ } catch (err) {
32363
+ const msg = err instanceof Error ? err.message : String(err);
32364
+ return { met: false, details: `verifier error: ${msg}` };
32365
+ }
32366
+ }
32367
+ async function verifyPrMerged(spec, execGh) {
32368
+ const { stdout, exitCode } = await execGh([
32369
+ "pr",
32370
+ "view",
32371
+ spec,
32372
+ "--json",
32373
+ "state"
32374
+ ]);
32375
+ if (exitCode !== 0) {
32376
+ return { met: false, details: `gh pr view failed: exit ${exitCode}` };
32377
+ }
32378
+ let parsed;
32379
+ try {
32380
+ parsed = JSON.parse(stdout);
32381
+ } catch {
32382
+ return { met: false, details: `gh pr view returned non-JSON` };
32383
+ }
32384
+ if (parsed.state === "MERGED") {
32385
+ return { met: true, details: `PR ${spec} merged` };
32386
+ }
32387
+ return {
32388
+ met: false,
32389
+ details: `PR ${spec} state=${parsed.state ?? "unknown"}`
32390
+ };
32391
+ }
32392
+ async function verifyPrGreen(spec, execGh) {
32393
+ const { stdout, exitCode } = await execGh([
32394
+ "pr",
32395
+ "checks",
32396
+ spec,
32397
+ "--json",
32398
+ "name,state"
32399
+ ]);
32400
+ if (exitCode !== 0) {
32401
+ return { met: false, details: `gh pr checks failed: exit ${exitCode}` };
32402
+ }
32403
+ let checks;
32404
+ try {
32405
+ checks = JSON.parse(stdout);
32406
+ } catch {
32407
+ return { met: false, details: `gh pr checks returned non-JSON` };
32408
+ }
32409
+ if (!Array.isArray(checks) || checks.length === 0) {
32410
+ return { met: false, details: "no checks reported" };
32411
+ }
32412
+ const PASSING = /* @__PURE__ */ new Set([
32413
+ "SUCCESS",
32414
+ "PASS",
32415
+ "PASSING",
32416
+ "SKIPPING",
32417
+ "SKIPPED",
32418
+ "NEUTRAL"
32419
+ ]);
32420
+ const failing = checks.filter(
32421
+ (c) => !PASSING.has(String(c.state ?? "").toUpperCase())
32422
+ );
32423
+ if (failing.length === 0) {
32424
+ return { met: true, details: `all ${checks.length} checks pass/skip` };
32425
+ }
32426
+ const detail = failing.map((c) => `${c.name}=${c.state}`).slice(0, 5).join(", ");
32427
+ return {
32428
+ met: false,
32429
+ details: `${failing.length}/${checks.length} non-passing: ${detail}`
32430
+ };
32431
+ }
32432
+ async function verifyFileExists(spec, workspaceRoot, statFn) {
32433
+ const target = path11.resolve(workspaceRoot, spec);
32434
+ try {
32435
+ await statFn(target);
32436
+ return { met: true, details: `${target} exists` };
32437
+ } catch {
32438
+ return { met: false, details: `${target} not found` };
32439
+ }
32440
+ }
32441
+ async function verifyTestPasses(spec, workspaceRoot, execVitest) {
32442
+ const { exitCode } = await execVitest(spec, workspaceRoot);
32443
+ if (exitCode === 0) {
32444
+ return { met: true, details: `test "${spec}" passed` };
32445
+ }
32446
+ return { met: false, details: `test "${spec}" exit=${exitCode}` };
32447
+ }
32448
+ async function verifyCommentPosted(spec, worldId, execGh) {
32449
+ let prNum;
32450
+ let marker;
32451
+ const colon = spec.indexOf(":");
32452
+ if (colon > 0) {
32453
+ prNum = spec.slice(0, colon);
32454
+ marker = spec.slice(colon + 1);
32455
+ } else {
32456
+ const lookup = await execGh([
32457
+ "pr",
32458
+ "list",
32459
+ "--search",
32460
+ worldId,
32461
+ "--json",
32462
+ "number",
32463
+ "--limit",
32464
+ "1"
32465
+ ]);
32466
+ if (lookup.exitCode !== 0) {
32467
+ return {
32468
+ met: false,
32469
+ details: `pr lookup failed for world ${worldId}: exit ${lookup.exitCode}`
32470
+ };
32471
+ }
32472
+ let arr;
32473
+ try {
32474
+ arr = JSON.parse(lookup.stdout);
32475
+ } catch {
32476
+ return { met: false, details: `pr lookup returned non-JSON` };
32477
+ }
32478
+ if (!Array.isArray(arr) || arr.length === 0 || arr[0] === void 0) {
32479
+ return { met: false, details: `no PR found for world ${worldId}` };
32480
+ }
32481
+ prNum = String(arr[0].number);
32482
+ marker = spec;
32483
+ }
32484
+ if (marker.length === 0) {
32485
+ return { met: false, details: "marker is empty" };
32486
+ }
32487
+ const { stdout, exitCode } = await execGh([
32488
+ "pr",
32489
+ "view",
32490
+ prNum,
32491
+ "--json",
32492
+ "comments"
32493
+ ]);
32494
+ if (exitCode !== 0) {
32495
+ return {
32496
+ met: false,
32497
+ details: `gh pr view comments failed: exit ${exitCode}`
32498
+ };
32499
+ }
32500
+ let parsed;
32501
+ try {
32502
+ parsed = JSON.parse(stdout);
32503
+ } catch {
32504
+ return { met: false, details: `gh pr view comments returned non-JSON` };
32505
+ }
32506
+ const found = (parsed.comments ?? []).some(
32507
+ (c) => (c.body ?? "").includes(marker)
32508
+ );
32509
+ if (found) {
32510
+ return {
32511
+ met: true,
32512
+ details: `marker "${marker}" found in PR ${prNum} comments`
32513
+ };
32514
+ }
32515
+ return {
32516
+ met: false,
32517
+ details: `marker "${marker}" not found in PR ${prNum} comments`
32518
+ };
32519
+ }
32520
+
32176
32521
  // ../mcp-server/src/tools/world-dispatch.ts
32177
- function register9(server, ctx, initError) {
32522
+ var dispatchInputSchema = {
32523
+ worldId: external_exports.string(),
32524
+ prompt: external_exports.string(),
32525
+ maxTurns: external_exports.number().optional(),
32526
+ mode: external_exports.enum(["deep", "fast", "auto"]).optional().describe(
32527
+ "Execution mode: 'deep' appends ultrathink + sub-agent instructions for complex/generative tasks, 'fast' for simple chores, 'auto' (default) detects from prompt complexity"
32528
+ ),
32529
+ goal: GoalSpecSchema.optional().describe(
32530
+ "Optional structured completion condition. When set, the world's dispatch loop checks this condition after each turn until met or the timeout window closes. v1 ships a single post-dispatch check; v2 will close the loop. /goal-mode parity with Claude Code 2.1.139."
32531
+ ),
32532
+ escalationTiers: external_exports.array(external_exports.enum(["haiku", "sonnet", "opus"])).optional().default(["sonnet"]).describe(
32533
+ "Ordered model-tier escalation chain for dispatch retries. On each retry, host-cp advances to the next tier instead of repeating the failed model. Default ['sonnet'] = no escalation (current behaviour, no cost surprise). Operators opt in via e.g. ['sonnet','opus'] or ['haiku','sonnet','opus']."
32534
+ )
32535
+ };
32536
+ var dispatchInputObject = external_exports.object(dispatchInputSchema);
32537
+ function register9(server, ctx, initError, deps) {
32538
+ const verify = deps?.verifyGoal ?? verifyGoal;
32178
32539
  server.tool(
32179
32540
  "olam_dispatch",
32180
32541
  "Send a task prompt to a world for autonomous execution.",
32181
- {
32182
- worldId: external_exports.string(),
32183
- prompt: external_exports.string(),
32184
- maxTurns: external_exports.number().optional(),
32185
- mode: external_exports.enum(["deep", "fast", "auto"]).optional().describe(
32186
- "Execution mode: 'deep' appends ultrathink + sub-agent instructions for complex/generative tasks, 'fast' for simple chores, 'auto' (default) detects from prompt complexity"
32187
- )
32188
- },
32542
+ dispatchInputSchema,
32189
32543
  async (params) => {
32190
32544
  if (!ctx) {
32191
32545
  const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
@@ -32283,6 +32637,31 @@ function register9(server, ctx, initError) {
32283
32637
  ` full context between dispatches. Watch live in browser terminal`,
32284
32638
  ` or via: docker exec -it olam-${params.worldId}-devbox tmux attach -t ${claudeSession} -r`
32285
32639
  ];
32640
+ if (params.goal) {
32641
+ try {
32642
+ const result = await verify(params.goal, params.worldId, {
32643
+ workspaceRoot: worldMeta.workspacePath
32644
+ });
32645
+ lines.push(
32646
+ ``,
32647
+ ` goal: ${params.goal.type} (${params.goal.spec})`,
32648
+ ` goal-met: ${result.met}`,
32649
+ ` goal-info: ${result.details}`
32650
+ );
32651
+ } catch (goalErr) {
32652
+ const msg = goalErr instanceof Error ? goalErr.message : String(goalErr);
32653
+ logger.warn("Goal verifier threw unexpectedly", {
32654
+ worldId: params.worldId,
32655
+ error: msg
32656
+ });
32657
+ lines.push(
32658
+ ``,
32659
+ ` goal: ${params.goal.type} (${params.goal.spec})`,
32660
+ ` goal-met: false`,
32661
+ ` goal-info: verifier-exception: ${msg}`
32662
+ );
32663
+ }
32664
+ }
32286
32665
  return {
32287
32666
  content: [{ type: "text", text: lines.join("\n") }]
32288
32667
  };
@@ -32428,7 +32807,7 @@ __export(world_crystallize_exports, {
32428
32807
  });
32429
32808
  init_v3();
32430
32809
  import "node:path";
32431
- import * as fs9 from "node:fs";
32810
+ import * as fs10 from "node:fs";
32432
32811
 
32433
32812
  // ../core/dist/crystallize/checksum.js
32434
32813
  import { createHash as createHash2 } from "node:crypto";
@@ -32484,7 +32863,7 @@ function register12(server, ctx, initError) {
32484
32863
  }
32485
32864
  try {
32486
32865
  const thoughtDbPath = getWorldDbPath(world.workspacePath);
32487
- if (!fs9.existsSync(thoughtDbPath)) {
32866
+ if (!fs10.existsSync(thoughtDbPath)) {
32488
32867
  return {
32489
32868
  content: [{
32490
32869
  type: "text",
@@ -32571,10 +32950,139 @@ __export(world_status_exports, {
32571
32950
  register: () => register13
32572
32951
  });
32573
32952
  init_v3();
32953
+
32954
+ // ../skill-runtime/dist/skills/olam-status.js
32955
+ init_v3();
32956
+
32957
+ // ../skill-runtime/dist/define-skill.js
32958
+ var KEBAB_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
32959
+ function defineSkill(spec) {
32960
+ if (!KEBAB_RE.test(spec.name)) {
32961
+ throw new Error(`defineSkill: name "${spec.name}" must be kebab-case (lowercase letters, digits, and hyphens only; no leading/trailing/double hyphens).`);
32962
+ }
32963
+ return {
32964
+ asMcpTool() {
32965
+ return {
32966
+ name: spec.name,
32967
+ description: spec.description,
32968
+ inputSchema: spec.inputSchema,
32969
+ async handler(params) {
32970
+ try {
32971
+ const parsed = spec.inputSchema.safeParse(params);
32972
+ if (!parsed.success) {
32973
+ return {
32974
+ content: [
32975
+ {
32976
+ type: "text",
32977
+ text: `Invalid input: ${parsed.error.message}`
32978
+ }
32979
+ ],
32980
+ isError: true
32981
+ };
32982
+ }
32983
+ const output = await spec.handler(parsed.data);
32984
+ return {
32985
+ content: [
32986
+ {
32987
+ type: "text",
32988
+ text: typeof output === "string" ? output : JSON.stringify(output)
32989
+ }
32990
+ ]
32991
+ };
32992
+ } catch (err) {
32993
+ const message = err instanceof Error ? err.message : String(err);
32994
+ return {
32995
+ content: [{ type: "text", text: `Error: ${message}` }],
32996
+ isError: true
32997
+ };
32998
+ }
32999
+ }
33000
+ };
33001
+ },
33002
+ asHttpHandler() {
33003
+ return async (req, res) => {
33004
+ const parsed = spec.inputSchema.safeParse(req.body);
33005
+ if (!parsed.success) {
33006
+ res.status(400).json({
33007
+ error: "Invalid input",
33008
+ issues: parsed.error.issues
33009
+ });
33010
+ return;
33011
+ }
33012
+ try {
33013
+ const output = await spec.handler(parsed.data);
33014
+ res.status(200).json({ result: output });
33015
+ } catch (err) {
33016
+ const message = err instanceof Error ? err.message : String(err);
33017
+ res.status(500).json({ error: message });
33018
+ }
33019
+ };
33020
+ },
33021
+ toJsonSchema() {
33022
+ return zodToJsonSchema(spec.inputSchema, { target: "openApi3" });
33023
+ }
33024
+ };
33025
+ }
33026
+
33027
+ // ../skill-runtime/dist/skills/olam-status.js
33028
+ var olamStatusInputSchema = external_exports.object({
33029
+ world: external_exports.object({
33030
+ id: external_exports.string(),
33031
+ name: external_exports.string(),
33032
+ status: external_exports.string(),
33033
+ repos: external_exports.array(external_exports.string()),
33034
+ branch: external_exports.string(),
33035
+ computeProvider: external_exports.string(),
33036
+ portOffset: external_exports.number(),
33037
+ workspacePath: external_exports.string(),
33038
+ thoughtCount: external_exports.number(),
33039
+ createdAt: external_exports.string(),
33040
+ updatedAt: external_exports.string(),
33041
+ cost: external_exports.number()
33042
+ })
33043
+ });
33044
+ function formatUptime(createdAt) {
33045
+ const ms = Date.now() - new Date(createdAt).getTime();
33046
+ const seconds = Math.floor(ms / 1e3);
33047
+ const minutes = Math.floor(seconds / 60);
33048
+ const hours = Math.floor(minutes / 60);
33049
+ const days = Math.floor(hours / 24);
33050
+ if (days > 0)
33051
+ return `${days}d ${hours % 24}h ${minutes % 60}m`;
33052
+ if (hours > 0)
33053
+ return `${hours}h ${minutes % 60}m`;
33054
+ return `${minutes}m`;
33055
+ }
33056
+ var olamStatusSkill = defineSkill({
33057
+ name: "olam-status",
33058
+ description: "Get detailed status information for a specific world.",
33059
+ inputSchema: olamStatusInputSchema,
33060
+ handler: ({ world }) => {
33061
+ const uptime = formatUptime(world.createdAt);
33062
+ const lines = [
33063
+ `World: ${world.name} (${world.id})`,
33064
+ ``,
33065
+ ` Status: ${world.status}`,
33066
+ ` Repos: ${world.repos.join(", ")}`,
33067
+ ` Branch: ${world.branch}`,
33068
+ ` Provider: ${world.computeProvider}`,
33069
+ ` Port Offset: ${world.portOffset}`,
33070
+ ` Workspace: ${world.workspacePath}`,
33071
+ ` Total Cost: $${world.cost.toFixed(4)}`,
33072
+ ` Thought Count: ${world.thoughtCount}`,
33073
+ ` Created: ${world.createdAt}`,
33074
+ ` Uptime: ${uptime}`,
33075
+ ` Last Updated: ${world.updatedAt}`
33076
+ ];
33077
+ return lines.join("\n");
33078
+ }
33079
+ });
33080
+
33081
+ // ../mcp-server/src/tools/world-status.ts
32574
33082
  function register13(server, ctx, initError) {
32575
33083
  server.tool(
32576
33084
  "olam_status",
32577
- "Get detailed status information for a specific world.",
33085
+ olamStatusSkill.asMcpTool().description,
32578
33086
  {
32579
33087
  worldId: external_exports.string()
32580
33088
  },
@@ -32594,26 +33102,23 @@ function register13(server, ctx, initError) {
32594
33102
  isError: true
32595
33103
  };
32596
33104
  }
32597
- const uptime = formatUptime(world.createdAt);
32598
33105
  const cost = ctx.costTracker.getWorldCost(params.worldId);
32599
- const lines = [
32600
- `World: ${world.name} (${world.id})`,
32601
- ``,
32602
- ` Status: ${world.status}`,
32603
- ` Repos: ${world.repos.join(", ")}`,
32604
- ` Branch: ${world.branch}`,
32605
- ` Provider: ${world.computeProvider}`,
32606
- ` Port Offset: ${world.portOffset}`,
32607
- ` Workspace: ${world.workspacePath}`,
32608
- ` Total Cost: $${cost.toFixed(4)}`,
32609
- ` Thought Count: ${world.thoughtCount}`,
32610
- ` Created: ${world.createdAt}`,
32611
- ` Uptime: ${uptime}`,
32612
- ` Last Updated: ${world.updatedAt}`
32613
- ];
32614
- return {
32615
- content: [{ type: "text", text: lines.join("\n") }]
32616
- };
33106
+ return olamStatusSkill.asMcpTool().handler({
33107
+ world: {
33108
+ id: world.id,
33109
+ name: world.name,
33110
+ status: world.status,
33111
+ repos: [...world.repos],
33112
+ branch: world.branch,
33113
+ computeProvider: world.computeProvider,
33114
+ portOffset: world.portOffset,
33115
+ workspacePath: world.workspacePath,
33116
+ thoughtCount: world.thoughtCount,
33117
+ createdAt: world.createdAt,
33118
+ updatedAt: world.updatedAt,
33119
+ cost
33120
+ }
33121
+ });
32617
33122
  } catch (err) {
32618
33123
  const message = err instanceof Error ? err.message : String(err);
32619
33124
  return {
@@ -32624,16 +33129,6 @@ function register13(server, ctx, initError) {
32624
33129
  }
32625
33130
  );
32626
33131
  }
32627
- function formatUptime(createdAt) {
32628
- const ms = Date.now() - new Date(createdAt).getTime();
32629
- const seconds = Math.floor(ms / 1e3);
32630
- const minutes = Math.floor(seconds / 60);
32631
- const hours = Math.floor(minutes / 60);
32632
- const days = Math.floor(hours / 24);
32633
- if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`;
32634
- if (hours > 0) return `${hours}h ${minutes % 60}m`;
32635
- return `${minutes}m`;
32636
- }
32637
33132
 
32638
33133
  // ../mcp-server/src/tools/control-plane.ts
32639
33134
  var control_plane_exports = {};
@@ -33077,10 +33572,10 @@ async function writeManifest(args) {
33077
33572
  capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
33078
33573
  shots: entries
33079
33574
  };
33080
- const path52 = join13(args.outDir, "manifest.json");
33081
- await writeFile(path52, `${JSON.stringify(manifest, null, 2)}
33575
+ const path53 = join13(args.outDir, "manifest.json");
33576
+ await writeFile(path53, `${JSON.stringify(manifest, null, 2)}
33082
33577
  `, "utf8");
33083
- return { path: path52, manifest };
33578
+ return { path: path53, manifest };
33084
33579
  }
33085
33580
 
33086
33581
  // ../mcp-server/src/tools/_capture/proxy.ts
@@ -33334,9 +33829,9 @@ async function startProxy(opts) {
33334
33829
  const liveCompiled = verified.allowedPaths.map(compileGlob);
33335
33830
  const target = parseRequestTarget(req);
33336
33831
  if (!target) return httpReject(400, "invalid_target");
33337
- const path52 = target.pathname;
33338
- if (!liveCompiled.some((re) => re.test(path52))) {
33339
- return httpReject(403, "outside_allow_list", { path: path52 });
33832
+ const path53 = target.pathname;
33833
+ if (!liveCompiled.some((re) => re.test(path53))) {
33834
+ return httpReject(403, "outside_allow_list", { path: path53 });
33340
33835
  }
33341
33836
  const headerWorld = req.headers[WORLD_ASSERT_HEADER];
33342
33837
  const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
@@ -33440,15 +33935,15 @@ ${JSON.stringify({ error: reason })}`
33440
33935
  unlinkSync2(udsPath);
33441
33936
  } catch {
33442
33937
  }
33443
- await new Promise((resolve14, reject2) => {
33444
- server.listen(udsPath, () => resolve14());
33938
+ await new Promise((resolve15, reject2) => {
33939
+ server.listen(udsPath, () => resolve15());
33445
33940
  server.once("error", reject2);
33446
33941
  });
33447
33942
  chmodSync3(udsPath, 384);
33448
33943
  port2 = 0;
33449
33944
  } else {
33450
- await new Promise((resolve14, reject2) => {
33451
- server.listen(opts.port ?? 0, "127.0.0.1", () => resolve14());
33945
+ await new Promise((resolve15, reject2) => {
33946
+ server.listen(opts.port ?? 0, "127.0.0.1", () => resolve15());
33452
33947
  server.once("error", reject2);
33453
33948
  });
33454
33949
  const addr = server.address();
@@ -33464,10 +33959,10 @@ ${JSON.stringify({ error: reason })}`
33464
33959
  } catch {
33465
33960
  }
33466
33961
  await Promise.race([
33467
- new Promise((resolve14, reject2) => {
33468
- server.close((err) => err ? reject2(err) : resolve14());
33962
+ new Promise((resolve15, reject2) => {
33963
+ server.close((err) => err ? reject2(err) : resolve15());
33469
33964
  }),
33470
- new Promise((resolve14) => setTimeout(resolve14, 5e3))
33965
+ new Promise((resolve15) => setTimeout(resolve15, 5e3))
33471
33966
  ]);
33472
33967
  if (udsPath) {
33473
33968
  try {
@@ -33497,9 +33992,9 @@ function ensureUdsParentDirSafe(udsPath) {
33497
33992
  `uds_parent_path_invalid: bindUdsPath "${udsPath}" has no manageable parent directory`
33498
33993
  );
33499
33994
  }
33500
- let stat = null;
33995
+ let stat2 = null;
33501
33996
  try {
33502
- stat = statSync3(parent);
33997
+ stat2 = statSync3(parent);
33503
33998
  } catch (err) {
33504
33999
  if (err.code !== "ENOENT") {
33505
34000
  throw new Error(
@@ -33507,25 +34002,25 @@ function ensureUdsParentDirSafe(udsPath) {
33507
34002
  );
33508
34003
  }
33509
34004
  }
33510
- if (!stat) {
34005
+ if (!stat2) {
33511
34006
  mkdirSync7(parent, { recursive: true, mode: 448 });
33512
34007
  return;
33513
34008
  }
33514
- if (!stat.isDirectory()) {
34009
+ if (!stat2.isDirectory()) {
33515
34010
  throw new Error(
33516
34011
  `uds_parent_dir_unsafe: "${parent}" exists but is not a directory`
33517
34012
  );
33518
34013
  }
33519
- const mode = stat.mode & 511;
34014
+ const mode = stat2.mode & 511;
33520
34015
  if (process.platform !== "win32" && mode !== 448) {
33521
34016
  throw new Error(
33522
34017
  `uds_parent_dir_unsafe: "${parent}" mode is 0o${mode.toString(8)}, expected 0o700 (other local UIDs could traverse the dir and access the socket)`
33523
34018
  );
33524
34019
  }
33525
34020
  const me = userInfo().uid;
33526
- if (process.platform !== "win32" && stat.uid !== me) {
34021
+ if (process.platform !== "win32" && stat2.uid !== me) {
33527
34022
  throw new Error(
33528
- `uds_parent_dir_unsafe: "${parent}" owned by uid=${stat.uid}, current process uid=${me}`
34023
+ `uds_parent_dir_unsafe: "${parent}" owned by uid=${stat2.uid}, current process uid=${me}`
33529
34024
  );
33530
34025
  }
33531
34026
  }
@@ -33799,10 +34294,10 @@ async function acquireLaunchSlot() {
33799
34294
  _inFlightLaunches++;
33800
34295
  return releaseLaunchSlot;
33801
34296
  }
33802
- return new Promise((resolve14) => {
34297
+ return new Promise((resolve15) => {
33803
34298
  _launchQueue.push(() => {
33804
34299
  _inFlightLaunches++;
33805
- resolve14(releaseLaunchSlot);
34300
+ resolve15(releaseLaunchSlot);
33806
34301
  });
33807
34302
  });
33808
34303
  }
@@ -34115,14 +34610,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
34115
34610
  await page.waitForTimeout(shot.afterLoadMs);
34116
34611
  }
34117
34612
  const ext = format === "jpeg" ? "jpg" : "png";
34118
- const path52 = join14(outDir, `${shot.name}.${ext}`);
34613
+ const path53 = join14(outDir, `${shot.name}.${ext}`);
34119
34614
  await page.screenshot({
34120
- path: path52,
34615
+ path: path53,
34121
34616
  type: format,
34122
34617
  ...format === "jpeg" ? { quality: jpegQuality } : {},
34123
34618
  fullPage: false
34124
34619
  });
34125
- return { name: shot.name, path: path52, urlRedacted: redactUrl(shot.url), viewport };
34620
+ return { name: shot.name, path: path53, urlRedacted: redactUrl(shot.url), viewport };
34126
34621
  } finally {
34127
34622
  await context.close();
34128
34623
  }
@@ -34566,12 +35061,12 @@ function openUrl(url2) {
34566
35061
  var HOST_CP_URL = "http://127.0.0.1:19000";
34567
35062
  async function readHostCpToken2() {
34568
35063
  try {
34569
- const { default: fs51 } = await import("node:fs");
35064
+ const { default: fs52 } = await import("node:fs");
34570
35065
  const { default: os31 } = await import("node:os");
34571
- const { default: path52 } = await import("node:path");
34572
- const tp = path52.join(os31.homedir(), ".olam", "host-cp.token");
34573
- if (!fs51.existsSync(tp)) return { token: null };
34574
- return { token: fs51.readFileSync(tp, "utf-8").trim() };
35066
+ const { default: path53 } = await import("node:path");
35067
+ const tp = path53.join(os31.homedir(), ".olam", "host-cp.token");
35068
+ if (!fs52.existsSync(tp)) return { token: null };
35069
+ return { token: fs52.readFileSync(tp, "utf-8").trim() };
34575
35070
  } catch {
34576
35071
  return { token: null };
34577
35072
  }
@@ -34831,9 +35326,9 @@ function register22(server, _ctx, _initError) {
34831
35326
  description: external_exports.string().optional().describe("Optional human-readable description."),
34832
35327
  defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
34833
35328
  },
34834
- async ({ name, path: path52, description, defaultBranch }) => {
35329
+ async ({ name, path: path53, description, defaultBranch }) => {
34835
35330
  try {
34836
- const entry = addRepo({ name, path: path52, description, defaultBranch });
35331
+ const entry = addRepo({ name, path: path53, description, defaultBranch });
34837
35332
  return {
34838
35333
  content: [{
34839
35334
  type: "text",
@@ -34874,9 +35369,9 @@ function register22(server, _ctx, _initError) {
34874
35369
  description: external_exports.string().optional().describe("New description."),
34875
35370
  defaultBranch: external_exports.string().optional().describe("New default branch.")
34876
35371
  },
34877
- async ({ name, path: path52, description, defaultBranch }) => {
35372
+ async ({ name, path: path53, description, defaultBranch }) => {
34878
35373
  try {
34879
- const entry = updateRepo(name, { path: path52, description, defaultBranch });
35374
+ const entry = updateRepo(name, { path: path53, description, defaultBranch });
34880
35375
  return {
34881
35376
  content: [{
34882
35377
  type: "text",
@@ -34897,15 +35392,15 @@ __export(process_port_exports, {
34897
35392
  resolveHostCpToken: () => resolveHostCpToken
34898
35393
  });
34899
35394
  init_v3();
34900
- import fs34 from "node:fs";
35395
+ import fs35 from "node:fs";
34901
35396
  import os20 from "node:os";
34902
- import path33 from "node:path";
35397
+ import path34 from "node:path";
34903
35398
  var HOST_CP_BASE = "http://127.0.0.1:19000";
34904
35399
  function resolveHostCpToken() {
34905
35400
  const envToken = process.env["OLAM_HOST_CP_TOKEN"];
34906
35401
  if (envToken) return envToken;
34907
- const tokenPath = path33.join(os20.homedir(), ".olam", "host-cp.token");
34908
- if (fs34.existsSync(tokenPath)) return fs34.readFileSync(tokenPath, "utf-8").trim();
35402
+ const tokenPath = path34.join(os20.homedir(), ".olam", "host-cp.token");
35403
+ if (fs35.existsSync(tokenPath)) return fs35.readFileSync(tokenPath, "utf-8").trim();
34909
35404
  return null;
34910
35405
  }
34911
35406
  function tokenMissingError() {
@@ -35337,8 +35832,8 @@ __export(skills_exports, {
35337
35832
  });
35338
35833
  init_v3();
35339
35834
  init_skill_sources();
35340
- import * as fs35 from "node:fs";
35341
- import * as path34 from "node:path";
35835
+ import * as fs36 from "node:fs";
35836
+ import * as path35 from "node:path";
35342
35837
  function asMessage8(err) {
35343
35838
  return err instanceof Error ? err.message : String(err);
35344
35839
  }
@@ -35361,14 +35856,14 @@ function listDeployed() {
35361
35856
  );
35362
35857
  const entries = [];
35363
35858
  for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
35364
- const bucketDir = path34.join(dir, bucket);
35365
- if (!fs35.existsSync(bucketDir)) continue;
35366
- for (const name of fs35.readdirSync(bucketDir)) {
35367
- const full = path34.join(bucketDir, name);
35859
+ const bucketDir = path35.join(dir, bucket);
35860
+ if (!fs36.existsSync(bucketDir)) continue;
35861
+ for (const name of fs36.readdirSync(bucketDir)) {
35862
+ const full = path35.join(bucketDir, name);
35368
35863
  try {
35369
- const stat = fs35.lstatSync(full);
35370
- if (!stat.isSymbolicLink()) continue;
35371
- const target = fs35.readlinkSync(full);
35864
+ const stat2 = fs36.lstatSync(full);
35865
+ if (!stat2.isSymbolicLink()) continue;
35866
+ const target = fs36.readlinkSync(full);
35372
35867
  let sourceId;
35373
35868
  for (const [clonePath, id] of sourcePaths.entries()) {
35374
35869
  if (target.startsWith(clonePath)) {
@@ -35454,13 +35949,13 @@ __export(skills_search_exports, {
35454
35949
  register: () => register27
35455
35950
  });
35456
35951
  init_v3();
35457
- import * as path36 from "node:path";
35952
+ import * as path37 from "node:path";
35458
35953
  import * as os22 from "node:os";
35459
35954
 
35460
35955
  // ../mcp-server/src/lib/skills-index.mjs
35461
35956
  import { createRequire as createRequire4 } from "node:module";
35462
- import * as fs36 from "node:fs";
35463
- import * as path35 from "node:path";
35957
+ import * as fs37 from "node:fs";
35958
+ import * as path36 from "node:path";
35464
35959
  import * as os21 from "node:os";
35465
35960
  var VECTOR_DIM = 256;
35466
35961
  var SCHEMA_VERSION3 = "1";
@@ -35550,7 +36045,7 @@ function bufferToVector(buf) {
35550
36045
  return vec;
35551
36046
  }
35552
36047
  function openIndex(dbPath) {
35553
- if (!fs36.existsSync(dbPath)) {
36048
+ if (!fs37.existsSync(dbPath)) {
35554
36049
  throw new Error(
35555
36050
  `skills index not found at ${dbPath}. Run \`node scripts/skills-index-build.mjs --out ${dbPath}\` first.`
35556
36051
  );
@@ -35592,14 +36087,14 @@ function searchIndex(dbPath, query, k = 5) {
35592
36087
  db.close();
35593
36088
  }
35594
36089
  }
35595
- var DEFAULT_DB_PATH = path35.join(os21.homedir(), ".olam", "skills.vec.db");
35596
- var DEFAULT_SOURCE_DIR = path35.join(os21.homedir(), ".claude", "skills");
36090
+ var DEFAULT_DB_PATH = path36.join(os21.homedir(), ".olam", "skills.vec.db");
36091
+ var DEFAULT_SOURCE_DIR = path36.join(os21.homedir(), ".claude", "skills");
35597
36092
 
35598
36093
  // ../mcp-server/src/tools/skills-search.ts
35599
36094
  function defaultDbPath() {
35600
36095
  const override = process.env["SKILLS_INDEX_PATH"];
35601
36096
  if (override) return override;
35602
- return path36.join(os22.homedir(), ".olam", "skills.vec.db");
36097
+ return path37.join(os22.homedir(), ".olam", "skills.vec.db");
35603
36098
  }
35604
36099
  function asMessage9(err) {
35605
36100
  return err instanceof Error ? err.message : String(err);
@@ -35650,8 +36145,8 @@ function port() {
35650
36145
  const n = Number.parseInt(env, 10);
35651
36146
  return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
35652
36147
  }
35653
- function url(path52) {
35654
- return `http://127.0.0.1:${port()}${path52}`;
36148
+ function url(path53) {
36149
+ return `http://127.0.0.1:${port()}${path53}`;
35655
36150
  }
35656
36151
  function kgServiceHealthUrl() {
35657
36152
  return url("/health");
@@ -35850,8 +36345,8 @@ __export(kg_install_hook_exports, {
35850
36345
  });
35851
36346
  init_v3();
35852
36347
  init_merge_settings();
35853
- import * as fs37 from "node:fs";
35854
- import * as path37 from "node:path";
36348
+ import * as fs38 from "node:fs";
36349
+ import * as path38 from "node:path";
35855
36350
  import * as os23 from "node:os";
35856
36351
 
35857
36352
  // ../core/dist/kg/hook-template.js
@@ -35902,10 +36397,10 @@ function buildHookMatcherEntry(opts) {
35902
36397
  // ../mcp-server/src/tools/kg-install-hook.ts
35903
36398
  function settingsPathFor2(scope, projectPath) {
35904
36399
  if (scope === "user") {
35905
- return path37.join(os23.homedir(), ".claude", "settings.json");
36400
+ return path38.join(os23.homedir(), ".claude", "settings.json");
35906
36401
  }
35907
36402
  const root = projectPath ?? process.cwd();
35908
- return path37.join(root, ".claude", "settings.json");
36403
+ return path38.join(root, ".claude", "settings.json");
35909
36404
  }
35910
36405
  function register30(server, _ctx, _initError) {
35911
36406
  server.tool(
@@ -35919,12 +36414,12 @@ function register30(server, _ctx, _initError) {
35919
36414
  const scope = params.scope === "user" ? "user" : "project";
35920
36415
  const filePath = settingsPathFor2(scope, params.projectPath);
35921
36416
  try {
35922
- fs37.mkdirSync(path37.dirname(filePath), { recursive: true });
36417
+ fs38.mkdirSync(path38.dirname(filePath), { recursive: true });
35923
36418
  let backupPath = null;
35924
- if (fs37.existsSync(filePath)) {
36419
+ if (fs38.existsSync(filePath)) {
35925
36420
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
35926
36421
  backupPath = `${filePath}.olam-bak.${ts}`;
35927
- fs37.copyFileSync(filePath, backupPath);
36422
+ fs38.copyFileSync(filePath, backupPath);
35928
36423
  }
35929
36424
  const result = mergeHomeSettingsJson(filePath, {
35930
36425
  ensureHook: {
@@ -35935,7 +36430,7 @@ function register30(server, _ctx, _initError) {
35935
36430
  });
35936
36431
  if (result.status === "already-present" && backupPath) {
35937
36432
  try {
35938
- fs37.unlinkSync(backupPath);
36433
+ fs38.unlinkSync(backupPath);
35939
36434
  } catch {
35940
36435
  }
35941
36436
  }
@@ -35979,15 +36474,15 @@ __export(kg_uninstall_hook_exports, {
35979
36474
  register: () => register31
35980
36475
  });
35981
36476
  init_v3();
35982
- import * as fs38 from "node:fs";
35983
- import * as path38 from "node:path";
36477
+ import * as fs39 from "node:fs";
36478
+ import * as path39 from "node:path";
35984
36479
  import * as os24 from "node:os";
35985
36480
  function settingsPathFor3(scope, projectPath) {
35986
36481
  if (scope === "user") {
35987
- return path38.join(os24.homedir(), ".claude", "settings.json");
36482
+ return path39.join(os24.homedir(), ".claude", "settings.json");
35988
36483
  }
35989
36484
  const root = projectPath ?? process.cwd();
35990
- return path38.join(root, ".claude", "settings.json");
36485
+ return path39.join(root, ".claude", "settings.json");
35991
36486
  }
35992
36487
  function dropSentinel(matchers) {
35993
36488
  let changed = false;
@@ -36021,7 +36516,7 @@ function register31(server, _ctx, _initError) {
36021
36516
  const scope = params.scope === "user" ? "user" : "project";
36022
36517
  const filePath = settingsPathFor3(scope, params.projectPath);
36023
36518
  try {
36024
- if (!fs38.existsSync(filePath)) {
36519
+ if (!fs39.existsSync(filePath)) {
36025
36520
  return {
36026
36521
  content: [
36027
36522
  {
@@ -36035,7 +36530,7 @@ function register31(server, _ctx, _initError) {
36035
36530
  ]
36036
36531
  };
36037
36532
  }
36038
- const raw = fs38.readFileSync(filePath, "utf-8");
36533
+ const raw = fs39.readFileSync(filePath, "utf-8");
36039
36534
  const settings = raw.trim() ? JSON.parse(raw) : {};
36040
36535
  const preToolUse = settings.hooks?.PreToolUse;
36041
36536
  if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
@@ -36070,7 +36565,7 @@ function register31(server, _ctx, _initError) {
36070
36565
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
36071
36566
  const backupPath = `${filePath}.olam-bak.${ts}`;
36072
36567
  try {
36073
- fs38.copyFileSync(filePath, backupPath);
36568
+ fs39.copyFileSync(filePath, backupPath);
36074
36569
  } catch {
36075
36570
  }
36076
36571
  const next = {
@@ -36082,7 +36577,7 @@ function register31(server, _ctx, _initError) {
36082
36577
  if (otherStages.length === 0) delete next.hooks;
36083
36578
  else delete next.hooks.PreToolUse;
36084
36579
  }
36085
- fs38.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
36580
+ fs39.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
36086
36581
  return {
36087
36582
  content: [
36088
36583
  {
@@ -36151,17 +36646,23 @@ var toolModules = [
36151
36646
  kg_uninstall_hook_exports
36152
36647
  ];
36153
36648
  function registerAllTools(server, ctx, initError) {
36154
- for (const mod of toolModules) {
36155
- mod.register(server, ctx, initError);
36649
+ const filterContext = getToolFilterContextFromEnv();
36650
+ const { server: filtered, finalize: finalize2 } = withFilteredTools(server, filterContext);
36651
+ try {
36652
+ for (const mod of toolModules) {
36653
+ mod.register(filtered, ctx, initError);
36654
+ }
36655
+ } finally {
36656
+ finalize2();
36156
36657
  }
36157
36658
  }
36158
36659
 
36159
36660
  // ../mcp-server/src/resources/chunks.ts
36160
- import fs39 from "node:fs";
36661
+ import fs40 from "node:fs";
36161
36662
  import os25 from "node:os";
36162
- import path39 from "node:path";
36663
+ import path40 from "node:path";
36163
36664
  var DEFAULT_HOST_CP_URL = "http://127.0.0.1:19000";
36164
- var DEFAULT_PLAN_CHAT_SECRET_PATH = path39.join(
36665
+ var DEFAULT_PLAN_CHAT_SECRET_PATH = path40.join(
36165
36666
  os25.homedir(),
36166
36667
  ".olam",
36167
36668
  "plan-chat-secret"
@@ -36176,7 +36677,7 @@ function loadBearer(bearerOpt, secretPath) {
36176
36677
  const envBearer = process.env.OLAM_PLAN_CHAT_BEARER?.trim();
36177
36678
  if (envBearer && envBearer.length > 0) return envBearer;
36178
36679
  try {
36179
- const onDisk = fs39.readFileSync(secretPath, "utf8").trim();
36680
+ const onDisk = fs40.readFileSync(secretPath, "utf8").trim();
36180
36681
  return onDisk.length > 0 ? onDisk : null;
36181
36682
  } catch (err) {
36182
36683
  if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
@@ -36500,9 +37001,9 @@ init_loader();
36500
37001
  // ../core/dist/world/manager.js
36501
37002
  import * as crypto8 from "node:crypto";
36502
37003
  import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
36503
- import * as fs48 from "node:fs";
37004
+ import * as fs49 from "node:fs";
36504
37005
  import * as os29 from "node:os";
36505
- import * as path49 from "node:path";
37006
+ import * as path50 from "node:path";
36506
37007
 
36507
37008
  // ../core/dist/world/state.js
36508
37009
  var VALID_TRANSITIONS = {
@@ -36598,8 +37099,8 @@ function resolveDevboxImage(config2, tag) {
36598
37099
 
36599
37100
  // ../core/dist/world/worktree.js
36600
37101
  import { execFileSync as execFileSync4 } from "node:child_process";
36601
- import * as fs40 from "node:fs";
36602
- import * as path40 from "node:path";
37102
+ import * as fs41 from "node:fs";
37103
+ import * as path41 from "node:path";
36603
37104
  function resolveGitDir(repo) {
36604
37105
  if (repo.path) {
36605
37106
  return repo.path;
@@ -36609,11 +37110,11 @@ function resolveGitDir(repo) {
36609
37110
  async function createWorktrees(repos, worldId, workspacePath, branch) {
36610
37111
  const created = [];
36611
37112
  for (const repo of repos) {
36612
- const worktreePath = path40.join(workspacePath, repo.name);
37113
+ const worktreePath = path41.join(workspacePath, repo.name);
36613
37114
  const gitDir = resolveGitDir(repo);
36614
37115
  const branchName = branch || `olam/${worldId}`;
36615
37116
  try {
36616
- fs40.mkdirSync(path40.dirname(worktreePath), { recursive: true });
37117
+ fs41.mkdirSync(path41.dirname(worktreePath), { recursive: true });
36617
37118
  execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
36618
37119
  cwd: gitDir,
36619
37120
  stdio: "pipe"
@@ -36646,7 +37147,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
36646
37147
  }
36647
37148
  async function removeWorktrees(repos, workspacePath) {
36648
37149
  for (const repo of repos) {
36649
- const worktreePath = path40.join(workspacePath, repo.name);
37150
+ const worktreePath = path41.join(workspacePath, repo.name);
36650
37151
  let gitDir;
36651
37152
  try {
36652
37153
  gitDir = resolveGitDir(repo);
@@ -36721,12 +37222,12 @@ function removeBranch(repo, branch) {
36721
37222
 
36722
37223
  // ../core/dist/world/kg-overlay.js
36723
37224
  import { execFileSync as execFileSync5 } from "node:child_process";
36724
- import * as fs41 from "node:fs";
36725
- import * as path41 from "node:path";
37225
+ import * as fs42 from "node:fs";
37226
+ import * as path42 from "node:path";
36726
37227
 
36727
37228
  // ../core/dist/kg/storage-paths.js
36728
37229
  import { homedir as homedir24 } from "node:os";
36729
- import { join as join41, resolve as resolve9 } from "node:path";
37230
+ import { join as join41, resolve as resolve10 } from "node:path";
36730
37231
 
36731
37232
  // ../core/dist/world/workspace-name.js
36732
37233
  var InvalidWorkspaceNameError = class extends Error {
@@ -36755,17 +37256,17 @@ function kgRoot() {
36755
37256
  function worldsRoot() {
36756
37257
  return join41(olamHome(), "worlds");
36757
37258
  }
36758
- function assertWithinPrefix(path52, prefix, label) {
36759
- if (!path52.startsWith(prefix + "/")) {
36760
- throw new Error(`${label} escape: ${path52} not under ${prefix}/`);
37259
+ function assertWithinPrefix(path53, prefix, label) {
37260
+ if (!path53.startsWith(prefix + "/")) {
37261
+ throw new Error(`${label} escape: ${path53} not under ${prefix}/`);
36761
37262
  }
36762
37263
  }
36763
37264
  function kgPristinePath(workspace) {
36764
37265
  validateWorkspaceName(workspace);
36765
37266
  const root = kgRoot();
36766
- const path52 = resolve9(join41(root, workspace));
36767
- assertWithinPrefix(path52, root, "kgPristinePath");
36768
- return path52;
37267
+ const path53 = resolve10(join41(root, workspace));
37268
+ assertWithinPrefix(path53, root, "kgPristinePath");
37269
+ return path53;
36769
37270
  }
36770
37271
  var KG_PATHS_INTERNALS = Object.freeze({
36771
37272
  olamHome,
@@ -36781,10 +37282,10 @@ var KgOverlayError = class extends Error {
36781
37282
  }
36782
37283
  };
36783
37284
  function ensureGitignoreEntry(worldClonePath) {
36784
- const gitignorePath = path41.join(worldClonePath, ".gitignore");
36785
- if (!fs41.existsSync(gitignorePath))
37285
+ const gitignorePath = path42.join(worldClonePath, ".gitignore");
37286
+ if (!fs42.existsSync(gitignorePath))
36786
37287
  return "no-gitignore";
36787
- const content = fs41.readFileSync(gitignorePath, "utf-8");
37288
+ const content = fs42.readFileSync(gitignorePath, "utf-8");
36788
37289
  const lines = content.split("\n").map((l) => l.trim());
36789
37290
  const recognised = /* @__PURE__ */ new Set([
36790
37291
  "graphify-out",
@@ -36799,24 +37300,24 @@ function ensureGitignoreEntry(worldClonePath) {
36799
37300
  const eol = content.includes("\r\n") ? "\r\n" : "\n";
36800
37301
  const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
36801
37302
  const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
36802
- fs41.appendFileSync(gitignorePath, block, "utf-8");
37303
+ fs42.appendFileSync(gitignorePath, block, "utf-8");
36803
37304
  return "appended";
36804
37305
  }
36805
37306
  function createWorldOverlay(opts) {
36806
37307
  const pristineRoot = kgPristinePath(opts.workspace);
36807
- const pristinePath = path41.join(pristineRoot, "graphify-out");
36808
- if (!fs41.existsSync(pristinePath)) {
37308
+ const pristinePath = path42.join(pristineRoot, "graphify-out");
37309
+ if (!fs42.existsSync(pristinePath)) {
36809
37310
  throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
36810
37311
  }
36811
- if (!path41.isAbsolute(opts.worldClonePath)) {
37312
+ if (!path42.isAbsolute(opts.worldClonePath)) {
36812
37313
  throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
36813
37314
  }
36814
- if (!fs41.existsSync(opts.worldClonePath)) {
37315
+ if (!fs42.existsSync(opts.worldClonePath)) {
36815
37316
  throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
36816
37317
  }
36817
- const overlayPath = path41.join(opts.worldClonePath, "graphify-out");
36818
- if (fs41.existsSync(overlayPath)) {
36819
- fs41.rmSync(overlayPath, { recursive: true, force: true });
37318
+ const overlayPath = path42.join(opts.worldClonePath, "graphify-out");
37319
+ if (fs42.existsSync(overlayPath)) {
37320
+ fs42.rmSync(overlayPath, { recursive: true, force: true });
36820
37321
  }
36821
37322
  const useReflink = process.platform === "darwin";
36822
37323
  let strategy;
@@ -36834,7 +37335,7 @@ function createWorldOverlay(opts) {
36834
37335
  } else {
36835
37336
  strategy = "cp-r";
36836
37337
  }
36837
- if (strategy === "cp-r" || !fs41.existsSync(overlayPath)) {
37338
+ if (strategy === "cp-r" || !fs42.existsSync(overlayPath)) {
36838
37339
  try {
36839
37340
  execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
36840
37341
  stdio: ["ignore", "ignore", "pipe"]
@@ -36846,7 +37347,7 @@ function createWorldOverlay(opts) {
36846
37347
  throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
36847
37348
  }
36848
37349
  }
36849
- if (!fs41.existsSync(overlayPath)) {
37350
+ if (!fs42.existsSync(overlayPath)) {
36850
37351
  throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
36851
37352
  }
36852
37353
  const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
@@ -36860,9 +37361,9 @@ function createWorldOverlay(opts) {
36860
37361
 
36861
37362
  // ../core/dist/world/baseline-diff.js
36862
37363
  import { execFileSync as execFileSync6 } from "node:child_process";
36863
- import * as fs42 from "node:fs";
37364
+ import * as fs43 from "node:fs";
36864
37365
  import * as os26 from "node:os";
36865
- import * as path42 from "node:path";
37366
+ import * as path43 from "node:path";
36866
37367
  var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
36867
37368
  function expandHome2(p, homedir30) {
36868
37369
  return p.replace(/^~(?=$|\/|\\)/, homedir30());
@@ -36889,9 +37390,9 @@ ${stderr}`;
36889
37390
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
36890
37391
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
36891
37392
  const homedir30 = deps.homedir ?? (() => os26.homedir());
36892
- const baselineDir = path42.join(workspacePath, ".olam", "baseline");
37393
+ const baselineDir = path43.join(workspacePath, ".olam", "baseline");
36893
37394
  try {
36894
- fs42.mkdirSync(baselineDir, { recursive: true });
37395
+ fs43.mkdirSync(baselineDir, { recursive: true });
36895
37396
  } catch (err) {
36896
37397
  const msg = err instanceof Error ? err.message : String(err);
36897
37398
  console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
@@ -36903,9 +37404,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
36903
37404
  if (!repo.path)
36904
37405
  continue;
36905
37406
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
36906
- const outPath = path42.join(baselineDir, filename);
37407
+ const outPath = path43.join(baselineDir, filename);
36907
37408
  const repoPath = expandHome2(repo.path, homedir30);
36908
- if (!fs42.existsSync(repoPath)) {
37409
+ if (!fs43.existsSync(repoPath)) {
36909
37410
  writeBaselineFile(outPath, `# repo: ${repo.name}
36910
37411
  # (skipped: path ${repoPath} does not exist)
36911
37412
  `);
@@ -36972,7 +37473,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
36972
37473
  }
36973
37474
  function writeBaselineFile(outPath, content) {
36974
37475
  try {
36975
- fs42.writeFileSync(outPath, content);
37476
+ fs43.writeFileSync(outPath, content);
36976
37477
  } catch (err) {
36977
37478
  const msg = err instanceof Error ? err.message : String(err);
36978
37479
  console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
@@ -36980,8 +37481,8 @@ function writeBaselineFile(outPath, content) {
36980
37481
  }
36981
37482
  function stripWorktreeEdits(repos, workspacePath) {
36982
37483
  for (const repo of repos) {
36983
- const worktreePath = path42.join(workspacePath, repo.name);
36984
- if (!fs42.existsSync(worktreePath))
37484
+ const worktreePath = path43.join(workspacePath, repo.name);
37485
+ if (!fs43.existsSync(worktreePath))
36985
37486
  continue;
36986
37487
  try {
36987
37488
  execFileSync6("git", ["checkout", "--", "."], {
@@ -37041,17 +37542,17 @@ function extractStderr(err) {
37041
37542
  function carryUncommittedEdits(repos, workspacePath, deps = {}) {
37042
37543
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
37043
37544
  const homedir30 = deps.homedir ?? (() => os26.homedir());
37044
- const existsSync48 = deps.existsSync ?? ((p) => fs42.existsSync(p));
37045
- const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs42.copyFileSync(src, dest));
37545
+ const existsSync48 = deps.existsSync ?? ((p) => fs43.existsSync(p));
37546
+ const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs43.copyFileSync(src, dest));
37046
37547
  const mkdirSync30 = deps.mkdirSync ?? ((dirPath, opts) => {
37047
- fs42.mkdirSync(dirPath, opts);
37548
+ fs43.mkdirSync(dirPath, opts);
37048
37549
  });
37049
37550
  const plans = [];
37050
37551
  for (const repo of repos) {
37051
37552
  if (!repo.path)
37052
37553
  continue;
37053
37554
  const repoPath = expandHome2(repo.path, homedir30);
37054
- const worktreePath = path42.join(workspacePath, repo.name);
37555
+ const worktreePath = path43.join(workspacePath, repo.name);
37055
37556
  if (!existsSync48(repoPath))
37056
37557
  continue;
37057
37558
  if (!existsSync48(worktreePath)) {
@@ -37112,12 +37613,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
37112
37613
  }
37113
37614
  }
37114
37615
  for (const rel of plan.diff.untracked) {
37115
- const src = path42.join(plan.repoPath, rel);
37116
- const dest = path42.join(plan.worktreePath, rel);
37616
+ const src = path43.join(plan.repoPath, rel);
37617
+ const dest = path43.join(plan.worktreePath, rel);
37117
37618
  if (!existsSync48(src))
37118
37619
  continue;
37119
37620
  try {
37120
- mkdirSync30(path42.dirname(dest), { recursive: true });
37621
+ mkdirSync30(path43.dirname(dest), { recursive: true });
37121
37622
  copyFileSync9(src, dest);
37122
37623
  } catch (err) {
37123
37624
  const msg = err instanceof Error ? err.message : String(err);
@@ -37143,8 +37644,8 @@ function formatBaselineSummary(result) {
37143
37644
  }
37144
37645
 
37145
37646
  // ../core/dist/world/context-injection.js
37146
- import * as fs43 from "node:fs";
37147
- import * as path43 from "node:path";
37647
+ import * as fs44 from "node:fs";
37648
+ import * as path44 from "node:path";
37148
37649
 
37149
37650
  // ../core/dist/world/templates/_generated.js
37150
37651
  var GH_PR_CREATE = '# Creating PRs from inside an Olam world\n\n## The problem\n\nCalling `gh pr create` directly inside an Olam container **hangs forever** on a\nTTY confirmation prompt that the agent cannot answer. This is a known, reproduced issue.\n\n## The fix\n\nAlways use this exact pattern:\n\n```bash\necho y | timeout 30 gh pr create \\\n --base main \\\n --head <branch> \\\n --title "<title>" \\\n --body-file /tmp/pr-body.md\n```\n\n## Why each part matters\n\n- **`echo y |`** \u2014 answers the "Submit?" confirmation prompt up front so `gh` never pauses.\n- **`timeout 30`** \u2014 hard deadline. If `gh` hangs anyway, the command exits non-zero so the\n agent can react instead of stalling the world indefinitely.\n- **`--body-file /tmp/pr-body.md`** \u2014 write the PR body to a temp file first. Avoids\n shell-escaping bugs that occur with `--body "..."` for long or multi-line bodies.\n- **`--head` and `--base` explicitly** \u2014 removes all interactive prompts; `gh` has nothing to ask.\n\n## Troubleshooting\n\n**"no commits" or "branch not found" error:**\n\n```bash\ngit push -u origin <branch>\n# then retry:\necho y | timeout 30 gh pr create --base main --head <branch> --title "..." --body-file /tmp/pr-body.md\n```\n\n**Timeout exceeded (command exits 124):**\n\n- Check if the branch was pushed: `git log origin/<branch> --oneline -1`\n- Check GitHub CLI auth: `gh auth status`\n- Retry once; if it hangs again, open the PR via the GitHub web UI.\n';
@@ -37154,10 +37655,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
37154
37655
  // ../core/dist/world/context-injection.js
37155
37656
  function injectWorldContext(opts) {
37156
37657
  const { world } = opts;
37157
- const claudeDir2 = path43.join(world.workspacePath, ".claude");
37158
- fs43.mkdirSync(claudeDir2, { recursive: true });
37658
+ const claudeDir2 = path44.join(world.workspacePath, ".claude");
37659
+ fs44.mkdirSync(claudeDir2, { recursive: true });
37159
37660
  const content = WORLD_CLAUDE_MD.replace("{{worldName}}", world.name).replace("{{worldId}}", world.id).replace("{{branch}}", world.branch).replace("{{taskBlock}}", buildTaskBlock(opts)).replace("{{reposList}}", buildReposList(world)).replace("{{servicesLine}}", buildServicesLine(opts.services)).replace("{{pleriPlaneLine}}", buildPleriPlaneLine(opts.pleriPlaneUrl)).replace("{{planFileBlock}}", buildPlanFileBlock(world)).replace("{{extraContextBlock}}", buildExtraContextBlock(opts.claudeMdExtra));
37160
- fs43.writeFileSync(path43.join(claudeDir2, "CLAUDE.md"), content);
37661
+ fs44.writeFileSync(path44.join(claudeDir2, "CLAUDE.md"), content);
37161
37662
  writeOlamDocs(world.workspacePath);
37162
37663
  }
37163
37664
  function buildTaskBlock(opts) {
@@ -37231,10 +37732,10 @@ function buildExtraContextBlock(extra) {
37231
37732
  ${extra}`;
37232
37733
  }
37233
37734
  function writeOlamDocs(workspacePath) {
37234
- const docsDir = path43.join(workspacePath, ".olam", "docs");
37235
- fs43.mkdirSync(docsDir, { recursive: true });
37236
- fs43.writeFileSync(path43.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
37237
- fs43.writeFileSync(path43.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
37735
+ const docsDir = path44.join(workspacePath, ".olam", "docs");
37736
+ fs44.mkdirSync(docsDir, { recursive: true });
37737
+ fs44.writeFileSync(path44.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
37738
+ fs44.writeFileSync(path44.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
37238
37739
  }
37239
37740
  function formatTaskSource(ctx) {
37240
37741
  if (ctx.source === "linear" && ctx.ticketId) {
@@ -37248,9 +37749,9 @@ function formatTaskSource(ctx) {
37248
37749
  function hasPlanFile(world) {
37249
37750
  if (world.repos.length === 0)
37250
37751
  return false;
37251
- const plansDir = path43.join(world.workspacePath, world.repos[0], "docs", "plans");
37752
+ const plansDir = path44.join(world.workspacePath, world.repos[0], "docs", "plans");
37252
37753
  try {
37253
- return fs43.existsSync(plansDir) && fs43.readdirSync(plansDir).length > 0;
37754
+ return fs44.existsSync(plansDir) && fs44.readdirSync(plansDir).length > 0;
37254
37755
  } catch {
37255
37756
  return false;
37256
37757
  }
@@ -37822,25 +38323,25 @@ init_repo_manifest();
37822
38323
 
37823
38324
  // ../core/dist/world/snapshot.js
37824
38325
  import * as crypto7 from "node:crypto";
37825
- import * as fs44 from "node:fs";
38326
+ import * as fs45 from "node:fs";
37826
38327
  import * as os27 from "node:os";
37827
- import * as path44 from "node:path";
37828
- import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
38328
+ import * as path45 from "node:path";
38329
+ import { execFileSync as execFileSync7, spawn as spawn3 } from "node:child_process";
37829
38330
  import { gunzipSync } from "node:zlib";
37830
38331
  function snapshotsDir() {
37831
- return process.env["OLAM_SNAPSHOTS_DIR"] ?? path44.join(os27.homedir(), ".olam", "snapshots");
38332
+ return process.env["OLAM_SNAPSHOTS_DIR"] ?? path45.join(os27.homedir(), ".olam", "snapshots");
37832
38333
  }
37833
38334
  function snapshotKindDirByWorkspace(workspace, arch, kind) {
37834
- return path44.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
38335
+ return path45.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
37835
38336
  }
37836
38337
  function cleanupLegacyByWorldDir(worldId) {
37837
- const legacyDir = path44.join(snapshotsDir(), worldId);
38338
+ const legacyDir = path45.join(snapshotsDir(), worldId);
37838
38339
  if (worldId === "by-workspace")
37839
38340
  return;
37840
- if (!fs44.existsSync(legacyDir))
38341
+ if (!fs45.existsSync(legacyDir))
37841
38342
  return;
37842
38343
  try {
37843
- fs44.rmSync(legacyDir, { recursive: true, force: true });
38344
+ fs45.rmSync(legacyDir, { recursive: true, force: true });
37844
38345
  } catch {
37845
38346
  }
37846
38347
  }
@@ -37859,11 +38360,11 @@ function hashBuffers(entries) {
37859
38360
  return hash.digest("hex").slice(0, 12);
37860
38361
  }
37861
38362
  function computeGemsFingerprint(repoDir, imageDigest) {
37862
- const lockfile = path44.join(repoDir, "Gemfile.lock");
37863
- if (!fs44.existsSync(lockfile))
38363
+ const lockfile = path45.join(repoDir, "Gemfile.lock");
38364
+ if (!fs45.existsSync(lockfile))
37864
38365
  return null;
37865
38366
  const entries = [
37866
- { path: "Gemfile.lock", content: fs44.readFileSync(lockfile) }
38367
+ { path: "Gemfile.lock", content: fs45.readFileSync(lockfile) }
37867
38368
  ];
37868
38369
  if (imageDigest) {
37869
38370
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -37873,10 +38374,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
37873
38374
  function computeNodeFingerprint(repoDir, imageDigest) {
37874
38375
  const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
37875
38376
  for (const name of candidates) {
37876
- const lockfile = path44.join(repoDir, name);
37877
- if (fs44.existsSync(lockfile)) {
38377
+ const lockfile = path45.join(repoDir, name);
38378
+ if (fs45.existsSync(lockfile)) {
37878
38379
  const entries = [
37879
- { path: name, content: fs44.readFileSync(lockfile) }
38380
+ { path: name, content: fs45.readFileSync(lockfile) }
37880
38381
  ];
37881
38382
  if (imageDigest) {
37882
38383
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -37895,18 +38396,18 @@ function unpackTarballAtomic(srcPath, destDir) {
37895
38396
  detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
37896
38397
  };
37897
38398
  }
37898
- const parent = path44.dirname(destDir);
37899
- fs44.mkdirSync(parent, { recursive: true });
38399
+ const parent = path45.dirname(destDir);
38400
+ fs45.mkdirSync(parent, { recursive: true });
37900
38401
  const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
37901
38402
  const tmpDir = `${destDir}${tmpSuffix}`;
37902
38403
  try {
37903
- fs44.mkdirSync(tmpDir, { recursive: true });
38404
+ fs45.mkdirSync(tmpDir, { recursive: true });
37904
38405
  execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
37905
- fs44.renameSync(tmpDir, destDir);
38406
+ fs45.renameSync(tmpDir, destDir);
37906
38407
  return { ok: true, entryCount: validation.entries.length };
37907
38408
  } catch (err) {
37908
38409
  try {
37909
- fs44.rmSync(tmpDir, { recursive: true, force: true });
38410
+ fs45.rmSync(tmpDir, { recursive: true, force: true });
37910
38411
  } catch {
37911
38412
  }
37912
38413
  return {
@@ -37917,12 +38418,12 @@ function unpackTarballAtomic(srcPath, destDir) {
37917
38418
  }
37918
38419
  }
37919
38420
  function resolvesWithin(base, target) {
37920
- const resolved = path44.resolve(base, target);
37921
- const baseResolved = path44.resolve(base);
37922
- const rel = path44.relative(baseResolved, resolved);
38421
+ const resolved = path45.resolve(base, target);
38422
+ const baseResolved = path45.resolve(base);
38423
+ const rel = path45.relative(baseResolved, resolved);
37923
38424
  if (rel === "")
37924
38425
  return true;
37925
- return !rel.startsWith("..") && !path44.isAbsolute(rel);
38426
+ return !rel.startsWith("..") && !path45.isAbsolute(rel);
37926
38427
  }
37927
38428
  var TYPE_CHAR_TO_TYPE = {
37928
38429
  "-": "file",
@@ -37972,7 +38473,7 @@ function parseTarListLine(line) {
37972
38473
  function validateHardlinksBinary(tarPath, targetDir) {
37973
38474
  let raw;
37974
38475
  try {
37975
- raw = gunzipSync(fs44.readFileSync(tarPath));
38476
+ raw = gunzipSync(fs45.readFileSync(tarPath));
37976
38477
  } catch {
37977
38478
  return null;
37978
38479
  }
@@ -37987,7 +38488,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
37987
38488
  const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
37988
38489
  const linkNull = block.indexOf(0, 157);
37989
38490
  const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
37990
- if (linkname && (path44.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
38491
+ if (linkname && (path45.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
37991
38492
  return {
37992
38493
  valid: false,
37993
38494
  reason: "hardlink-escape",
@@ -38025,7 +38526,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
38025
38526
  const entry = parseTarListLine(line);
38026
38527
  if (!entry)
38027
38528
  continue;
38028
- if (path44.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
38529
+ if (path45.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
38029
38530
  return {
38030
38531
  valid: false,
38031
38532
  reason: "path-traversal",
@@ -38033,8 +38534,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
38033
38534
  };
38034
38535
  }
38035
38536
  if (entry.type === "symlink" && entry.linkname !== void 0) {
38036
- const symlinkParent = path44.join(targetDir, path44.dirname(entry.name));
38037
- if (path44.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path44.join(path44.dirname(entry.name), entry.linkname))) {
38537
+ const symlinkParent = path45.join(targetDir, path45.dirname(entry.name));
38538
+ if (path45.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path45.join(path45.dirname(entry.name), entry.linkname))) {
38038
38539
  return {
38039
38540
  valid: false,
38040
38541
  reason: "symlink-escape",
@@ -38044,7 +38545,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
38044
38545
  }
38045
38546
  }
38046
38547
  if (entry.type === "hardlink" && entry.linkname !== void 0) {
38047
- if (path44.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
38548
+ if (path45.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
38048
38549
  return {
38049
38550
  valid: false,
38050
38551
  reason: "hardlink-escape",
@@ -38077,8 +38578,8 @@ function restoreSnapshotsForRepos(input) {
38077
38578
  }
38078
38579
  const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
38079
38580
  const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
38080
- const tarPath = path44.join(archDir, tarFilename);
38081
- if (!fs44.existsSync(tarPath)) {
38581
+ const tarPath = path45.join(archDir, tarFilename);
38582
+ if (!fs45.existsSync(tarPath)) {
38082
38583
  outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
38083
38584
  continue;
38084
38585
  }
@@ -38093,9 +38594,9 @@ function restoreSnapshotsForRepos(input) {
38093
38594
  });
38094
38595
  continue;
38095
38596
  }
38096
- const targetDir = path44.join(repo.worktreeDir, targetSubpath);
38597
+ const targetDir = path45.join(repo.worktreeDir, targetSubpath);
38097
38598
  try {
38098
- fs44.rmSync(targetDir, { recursive: true, force: true });
38599
+ fs45.rmSync(targetDir, { recursive: true, force: true });
38099
38600
  } catch {
38100
38601
  }
38101
38602
  const result = unpackTarballAtomic(tarPath, targetDir);
@@ -38108,8 +38609,8 @@ function restoreSnapshotsForRepos(input) {
38108
38609
  fingerprint
38109
38610
  });
38110
38611
  try {
38111
- fs44.rmSync(tarPath, { force: true });
38112
- fs44.rmSync(manifestPath(tarPath), { force: true });
38612
+ fs45.rmSync(tarPath, { force: true });
38613
+ fs45.rmSync(manifestPath(tarPath), { force: true });
38113
38614
  } catch {
38114
38615
  }
38115
38616
  continue;
@@ -38125,10 +38626,10 @@ function restoreSnapshotsForRepos(input) {
38125
38626
  }
38126
38627
  function readManifest(tarPath) {
38127
38628
  const mPath = manifestPath(tarPath);
38128
- if (!fs44.existsSync(mPath))
38629
+ if (!fs45.existsSync(mPath))
38129
38630
  return null;
38130
38631
  try {
38131
- return JSON.parse(fs44.readFileSync(mPath, "utf-8"));
38632
+ return JSON.parse(fs45.readFileSync(mPath, "utf-8"));
38132
38633
  } catch {
38133
38634
  return null;
38134
38635
  }
@@ -38143,17 +38644,17 @@ function isPidAlive(pid) {
38143
38644
  }
38144
38645
  }
38145
38646
  function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
38146
- fs44.mkdirSync(dir, { recursive: true });
38147
- const lockPath = path44.join(dir, EVICT_LOCK_FILENAME);
38647
+ fs45.mkdirSync(dir, { recursive: true });
38648
+ const lockPath = path45.join(dir, EVICT_LOCK_FILENAME);
38148
38649
  let fd;
38149
38650
  try {
38150
- fd = fs44.openSync(lockPath, fs44.constants.O_WRONLY | fs44.constants.O_CREAT | fs44.constants.O_EXCL, 384);
38651
+ fd = fs45.openSync(lockPath, fs45.constants.O_WRONLY | fs45.constants.O_CREAT | fs45.constants.O_EXCL, 384);
38151
38652
  } catch (err) {
38152
38653
  if (err.code !== "EEXIST")
38153
38654
  return 0;
38154
38655
  let holderPid = null;
38155
38656
  try {
38156
- holderPid = parseInt(fs44.readFileSync(lockPath, "utf-8").trim(), 10);
38657
+ holderPid = parseInt(fs45.readFileSync(lockPath, "utf-8").trim(), 10);
38157
38658
  } catch {
38158
38659
  holderPid = null;
38159
38660
  }
@@ -38161,23 +38662,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
38161
38662
  return 0;
38162
38663
  }
38163
38664
  try {
38164
- fs44.unlinkSync(lockPath);
38165
- fd = fs44.openSync(lockPath, fs44.constants.O_WRONLY | fs44.constants.O_CREAT | fs44.constants.O_EXCL, 384);
38665
+ fs45.unlinkSync(lockPath);
38666
+ fd = fs45.openSync(lockPath, fs45.constants.O_WRONLY | fs45.constants.O_CREAT | fs45.constants.O_EXCL, 384);
38166
38667
  } catch {
38167
38668
  return 0;
38168
38669
  }
38169
38670
  }
38170
38671
  try {
38171
- fs44.writeSync(fd, `${process.pid}
38672
+ fs45.writeSync(fd, `${process.pid}
38172
38673
  `);
38173
38674
  } finally {
38174
- fs44.closeSync(fd);
38675
+ fs45.closeSync(fd);
38175
38676
  }
38176
38677
  try {
38177
38678
  return evictOldSnapshots(maxBytes, dir);
38178
38679
  } finally {
38179
38680
  try {
38180
- fs44.unlinkSync(lockPath);
38681
+ fs45.unlinkSync(lockPath);
38181
38682
  } catch {
38182
38683
  }
38183
38684
  }
@@ -38188,7 +38689,7 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
38188
38689
  if (!/^[a-zA-Z0-9_\-.]+$/.test(worldId))
38189
38690
  return null;
38190
38691
  try {
38191
- const child = spawn2(olamBin, ["world", "snapshot", "create", worldId, "--kind", "all"], {
38692
+ const child = spawn3(olamBin, ["world", "snapshot", "create", worldId, "--kind", "all"], {
38192
38693
  detached: true,
38193
38694
  stdio: "ignore",
38194
38695
  // OLAM_INTERNAL_SNAPSHOT=1 sentinel — Phase D D1's deprecation
@@ -38210,17 +38711,17 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
38210
38711
  }
38211
38712
  }
38212
38713
  function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
38213
- if (!fs44.existsSync(dir))
38714
+ if (!fs45.existsSync(dir))
38214
38715
  return 0;
38215
38716
  const allTars = [];
38216
38717
  const walk = (d) => {
38217
- for (const entry of fs44.readdirSync(d, { withFileTypes: true })) {
38218
- const full = path44.join(d, entry.name);
38718
+ for (const entry of fs45.readdirSync(d, { withFileTypes: true })) {
38719
+ const full = path45.join(d, entry.name);
38219
38720
  if (entry.isDirectory()) {
38220
38721
  walk(full);
38221
38722
  } else if (entry.name.endsWith(".tar.gz")) {
38222
- const stat = fs44.statSync(full);
38223
- allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
38723
+ const stat2 = fs45.statSync(full);
38724
+ allTars.push({ path: full, size: stat2.size, mtime: stat2.mtimeMs });
38224
38725
  }
38225
38726
  }
38226
38727
  };
@@ -38234,8 +38735,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
38234
38735
  for (const tar of allTars) {
38235
38736
  if (remaining <= maxBytes)
38236
38737
  break;
38237
- fs44.rmSync(tar.path, { force: true });
38238
- fs44.rmSync(manifestPath(tar.path), { force: true });
38738
+ fs45.rmSync(tar.path, { force: true });
38739
+ fs45.rmSync(manifestPath(tar.path), { force: true });
38239
38740
  freed += tar.size;
38240
38741
  remaining -= tar.size;
38241
38742
  }
@@ -38352,14 +38853,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
38352
38853
 
38353
38854
  // ../core/dist/world/olam-yaml.js
38354
38855
  init_repo_manifest();
38355
- import * as path45 from "node:path";
38856
+ import * as path46 from "node:path";
38356
38857
  import YAML2 from "yaml";
38357
38858
  function enrichReposWithManifests(repos, workspacePath) {
38358
38859
  return repos.map((repo) => {
38359
38860
  if (repo.manifest !== void 0 && repo.manifest !== null) {
38360
38861
  return repo;
38361
38862
  }
38362
- const repoDir = path45.join(workspacePath, repo.name);
38863
+ const repoDir = path46.join(workspacePath, repo.name);
38363
38864
  let manifest = null;
38364
38865
  try {
38365
38866
  manifest = loadRepoManifest(repoDir);
@@ -38374,8 +38875,8 @@ function enrichReposWithManifests(repos, workspacePath) {
38374
38875
  }
38375
38876
 
38376
38877
  // ../core/dist/policies/loader.js
38377
- import * as fs45 from "node:fs";
38378
- import * as path46 from "node:path";
38878
+ import * as fs46 from "node:fs";
38879
+ import * as path47 from "node:path";
38379
38880
  import { parse as parseYaml5 } from "yaml";
38380
38881
  function parseFrontmatter2(content) {
38381
38882
  const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
@@ -38395,20 +38896,20 @@ function toStringArray(v) {
38395
38896
  return v.filter((x) => typeof x === "string");
38396
38897
  }
38397
38898
  function loadPolicies(workspaceRoot) {
38398
- const policiesDir = path46.join(workspaceRoot, ".olam", "policies");
38399
- if (!fs45.existsSync(policiesDir))
38899
+ const policiesDir = path47.join(workspaceRoot, ".olam", "policies");
38900
+ if (!fs46.existsSync(policiesDir))
38400
38901
  return [];
38401
38902
  let files;
38402
38903
  try {
38403
- files = fs45.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
38904
+ files = fs46.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
38404
38905
  } catch {
38405
38906
  return [];
38406
38907
  }
38407
38908
  const policies = [];
38408
38909
  for (const file of files) {
38409
- const filePath = path46.join(policiesDir, file);
38910
+ const filePath = path47.join(policiesDir, file);
38410
38911
  try {
38411
- const content = fs45.readFileSync(filePath, "utf8");
38912
+ const content = fs46.readFileSync(filePath, "utf8");
38412
38913
  const parsed = parseFrontmatter2(content);
38413
38914
  if (!parsed) {
38414
38915
  console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
@@ -38491,7 +38992,7 @@ var TaskDispatchError = class extends Error {
38491
38992
  this.name = "TaskDispatchError";
38492
38993
  }
38493
38994
  };
38494
- var DEFAULT_SLEEP = (ms) => new Promise((resolve14) => setTimeout(resolve14, ms));
38995
+ var DEFAULT_SLEEP = (ms) => new Promise((resolve15) => setTimeout(resolve15, ms));
38495
38996
  async function probeHealth(containerName, dockerExec, budgetMs, sleep5) {
38496
38997
  const deadline = Date.now() + budgetMs;
38497
38998
  const cadenceMs = 100;
@@ -38555,12 +39056,12 @@ init_store();
38555
39056
  init_bridge();
38556
39057
 
38557
39058
  // ../core/dist/global-config/runbook-resolver.js
38558
- import * as fs46 from "node:fs";
39059
+ import * as fs47 from "node:fs";
38559
39060
  import * as os28 from "node:os";
38560
- import * as path47 from "node:path";
39061
+ import * as path48 from "node:path";
38561
39062
  function expandTilde(p) {
38562
39063
  if (p === "~" || p.startsWith("~/")) {
38563
- return path47.join(os28.homedir(), p.slice(1));
39064
+ return path48.join(os28.homedir(), p.slice(1));
38564
39065
  }
38565
39066
  return p;
38566
39067
  }
@@ -38572,7 +39073,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
38572
39073
  throw new Error(`repo "${repoName}" is referenced by runbook "${runbook.name}" but is not in the registry. Run "olam repos add ${repoName} --path <path>" to register it.`);
38573
39074
  }
38574
39075
  const resolvedPath = expandTilde(entry.path);
38575
- if (!fs46.existsSync(resolvedPath)) {
39076
+ if (!fs47.existsSync(resolvedPath)) {
38576
39077
  throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
38577
39078
  }
38578
39079
  }
@@ -38588,19 +39089,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
38588
39089
  init_port_validator();
38589
39090
 
38590
39091
  // ../core/dist/world/bootstrap-hooks.js
38591
- import * as fs47 from "node:fs";
38592
- import * as path48 from "node:path";
39092
+ import * as fs48 from "node:fs";
39093
+ import * as path49 from "node:path";
38593
39094
  function runFixtureCopySeeds(seeds, workspacePath) {
38594
39095
  if (!seeds)
38595
39096
  return;
38596
39097
  for (const seed of seeds) {
38597
39098
  if (seed.type !== "fixture-copy")
38598
39099
  continue;
38599
- const srcAbs = path48.resolve(workspacePath, seed.repo, seed.src);
38600
- const destAbs = path48.resolve(workspacePath, seed.repo, seed.dest);
38601
- const destDir = path48.dirname(destAbs);
38602
- fs47.mkdirSync(destDir, { recursive: true });
38603
- fs47.cpSync(srcAbs, destAbs, { recursive: true, force: true });
39100
+ const srcAbs = path49.resolve(workspacePath, seed.repo, seed.src);
39101
+ const destAbs = path49.resolve(workspacePath, seed.repo, seed.dest);
39102
+ const destDir = path49.dirname(destAbs);
39103
+ fs48.mkdirSync(destDir, { recursive: true });
39104
+ fs48.cpSync(srcAbs, destAbs, { recursive: true, force: true });
38604
39105
  }
38605
39106
  }
38606
39107
  async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
@@ -39236,7 +39737,7 @@ ${detail}`);
39236
39737
  runbookSeeds = resolved.seeds;
39237
39738
  }
39238
39739
  const worldId = generateWorldId();
39239
- const workspacePath = path49.join(os29.homedir(), ".olam", "worlds", worldId);
39740
+ const workspacePath = path50.join(os29.homedir(), ".olam", "worlds", worldId);
39240
39741
  const portOffset = this.registry.getNextPortOffset();
39241
39742
  const branch = opts.branchName ?? `olam/${worldId}`;
39242
39743
  const repos = this.resolveReposWithWorkspace(opts);
@@ -39257,7 +39758,8 @@ ${detail}`);
39257
39758
  createdAt: now,
39258
39759
  updatedAt: now,
39259
39760
  readinessChain,
39260
- expectedServices
39761
+ expectedServices,
39762
+ ...opts.claudeHome ? { claudeHome: opts.claudeHome } : {}
39261
39763
  };
39262
39764
  const sm = new WorldStateMachine(worldId, "creating");
39263
39765
  this.registry.register(metadata);
@@ -39318,37 +39820,37 @@ ${detail}`);
39318
39820
  if (!repo.path)
39319
39821
  continue;
39320
39822
  const sourceRoot = repo.path.replace(/^~/, os29.homedir());
39321
- const worktreeRoot = path49.join(workspacePath, repo.name);
39322
- if (!fs48.existsSync(sourceRoot) || !fs48.existsSync(worktreeRoot))
39823
+ const worktreeRoot = path50.join(workspacePath, repo.name);
39824
+ if (!fs49.existsSync(sourceRoot) || !fs49.existsSync(worktreeRoot))
39323
39825
  continue;
39324
39826
  let copied = 0;
39325
39827
  for (const pattern of RUNTIME_FILE_PATTERNS) {
39326
39828
  const matches2 = [];
39327
39829
  if (pattern.includes("*")) {
39328
- const [dir, glob] = [path49.dirname(pattern), path49.basename(pattern)];
39329
- const sourceDir = path49.join(sourceRoot, dir);
39330
- if (fs48.existsSync(sourceDir)) {
39830
+ const [dir, glob] = [path50.dirname(pattern), path50.basename(pattern)];
39831
+ const sourceDir = path50.join(sourceRoot, dir);
39832
+ if (fs49.existsSync(sourceDir)) {
39331
39833
  const ext = glob.replace(/^\*+/, "");
39332
39834
  try {
39333
- for (const entry of fs48.readdirSync(sourceDir)) {
39835
+ for (const entry of fs49.readdirSync(sourceDir)) {
39334
39836
  if (ext === "" || entry.endsWith(ext))
39335
- matches2.push(path49.join(dir, entry));
39837
+ matches2.push(path50.join(dir, entry));
39336
39838
  }
39337
39839
  } catch {
39338
39840
  }
39339
39841
  }
39340
- } else if (fs48.existsSync(path49.join(sourceRoot, pattern))) {
39842
+ } else if (fs49.existsSync(path50.join(sourceRoot, pattern))) {
39341
39843
  matches2.push(pattern);
39342
39844
  }
39343
39845
  for (const rel of matches2) {
39344
- const src = path49.join(sourceRoot, rel);
39345
- const dst = path49.join(worktreeRoot, rel);
39846
+ const src = path50.join(sourceRoot, rel);
39847
+ const dst = path50.join(worktreeRoot, rel);
39346
39848
  try {
39347
- const st = fs48.statSync(src);
39849
+ const st = fs49.statSync(src);
39348
39850
  if (!st.isFile())
39349
39851
  continue;
39350
- fs48.mkdirSync(path49.dirname(dst), { recursive: true });
39351
- fs48.copyFileSync(src, dst);
39852
+ fs49.mkdirSync(path50.dirname(dst), { recursive: true });
39853
+ fs49.copyFileSync(src, dst);
39352
39854
  copied++;
39353
39855
  } catch {
39354
39856
  }
@@ -39395,7 +39897,7 @@ ${detail}`);
39395
39897
  worlds_default: this.config.worlds_default,
39396
39898
  repos: enrichedRepos
39397
39899
  };
39398
- setupWorldEnv(enrichedRepos, workspacePath, serviceEnv, crossRepoEnv, configCtx);
39900
+ setupWorldEnv(enrichedRepos, workspacePath, serviceEnv, crossRepoEnv, configCtx, opts.claudeHome);
39399
39901
  } catch (err) {
39400
39902
  const msg = err instanceof Error ? err.message : String(err);
39401
39903
  console.warn(`[WorldManager] env setup failed: ${msg}`);
@@ -39434,7 +39936,7 @@ ${detail}`);
39434
39936
  }
39435
39937
  const overlayAttachments = [];
39436
39938
  for (const repo of repos) {
39437
- const worldClonePath = path49.join(workspacePath, repo.name);
39939
+ const worldClonePath = path50.join(workspacePath, repo.name);
39438
39940
  try {
39439
39941
  const result = createWorldOverlay({
39440
39942
  workspace: repo.name,
@@ -39489,7 +39991,7 @@ ${detail}`);
39489
39991
  try {
39490
39992
  const hostExec = makeHostExecFn();
39491
39993
  for (const repo of repos) {
39492
- const repoDir = path49.join(workspacePath, repo.name);
39994
+ const repoDir = path50.join(workspacePath, repo.name);
39493
39995
  if (repo.stack && Object.keys(repo.stack).length > 0) {
39494
39996
  preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
39495
39997
  } else {
@@ -39533,10 +40035,10 @@ ${detail}`);
39533
40035
  const worldEnv = {};
39534
40036
  if (opts.task)
39535
40037
  worldEnv.OLAM_TASK = opts.task;
39536
- const r2CredsPath = path49.join(os29.homedir(), ".olam", "r2-credentials.json");
39537
- if (fs48.existsSync(r2CredsPath)) {
40038
+ const r2CredsPath = path50.join(os29.homedir(), ".olam", "r2-credentials.json");
40039
+ if (fs49.existsSync(r2CredsPath)) {
39538
40040
  try {
39539
- const r2Raw = fs48.readFileSync(r2CredsPath, "utf-8").trim();
40041
+ const r2Raw = fs49.readFileSync(r2CredsPath, "utf-8").trim();
39540
40042
  if (r2Raw.length > 0) {
39541
40043
  const r2 = JSON.parse(r2Raw);
39542
40044
  if (typeof r2.account_id === "string")
@@ -39553,10 +40055,10 @@ ${detail}`);
39553
40055
  } catch {
39554
40056
  }
39555
40057
  }
39556
- const keysYamlPath = path49.join(os29.homedir(), ".olam", "keys.yaml");
39557
- if (fs48.existsSync(keysYamlPath)) {
40058
+ const keysYamlPath = path50.join(os29.homedir(), ".olam", "keys.yaml");
40059
+ if (fs49.existsSync(keysYamlPath)) {
39558
40060
  try {
39559
- const keysRaw = fs48.readFileSync(keysYamlPath, "utf-8").trim();
40061
+ const keysRaw = fs49.readFileSync(keysYamlPath, "utf-8").trim();
39560
40062
  if (keysRaw.length > 0) {
39561
40063
  const parsed = YAML3.parse(keysRaw);
39562
40064
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
@@ -39615,10 +40117,10 @@ ${detail}`);
39615
40117
  worldEnv[k] = v;
39616
40118
  }
39617
40119
  for (const { repoName, relativePath, content } of fileWrites) {
39618
- const absPath = path49.join(workspacePath, repoName, relativePath);
40120
+ const absPath = path50.join(workspacePath, repoName, relativePath);
39619
40121
  try {
39620
- fs48.mkdirSync(path49.dirname(absPath), { recursive: true });
39621
- fs48.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
40122
+ fs49.mkdirSync(path50.dirname(absPath), { recursive: true });
40123
+ fs49.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
39622
40124
  mode: 384
39623
40125
  });
39624
40126
  console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
@@ -39795,7 +40297,7 @@ ${detail}`);
39795
40297
  imageDigest: void 0,
39796
40298
  repos: enrichedRepos.map((r) => ({
39797
40299
  name: r.name,
39798
- worktreeDir: path49.join(workspacePath, r.name)
40300
+ worktreeDir: path50.join(workspacePath, r.name)
39799
40301
  }))
39800
40302
  });
39801
40303
  for (const out of restoreResult.outcomes) {
@@ -39901,7 +40403,7 @@ ${detail}`);
39901
40403
  }
39902
40404
  if (opts.task) {
39903
40405
  const allPolicies = repos.flatMap((repo) => {
39904
- const repoWorktree = path49.join(workspacePath, repo.name);
40406
+ const repoWorktree = path50.join(workspacePath, repo.name);
39905
40407
  try {
39906
40408
  return loadPolicies(repoWorktree);
39907
40409
  } catch (err) {
@@ -39914,8 +40416,8 @@ ${detail}`);
39914
40416
  try {
39915
40417
  execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
39916
40418
  for (const repo of repos) {
39917
- const policiesDir = path49.join(workspacePath, repo.name, ".olam", "policies");
39918
- if (fs48.existsSync(policiesDir)) {
40419
+ const policiesDir = path50.join(workspacePath, repo.name, ".olam", "policies");
40420
+ if (fs49.existsSync(policiesDir)) {
39919
40421
  execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
39920
40422
  }
39921
40423
  }
@@ -40023,8 +40525,8 @@ ${detail}`);
40023
40525
  } catch {
40024
40526
  }
40025
40527
  try {
40026
- fs48.rmSync(world.workspacePath, { recursive: true, force: true });
40027
- if (fs48.existsSync(world.workspacePath)) {
40528
+ fs49.rmSync(world.workspacePath, { recursive: true, force: true });
40529
+ if (fs49.existsSync(world.workspacePath)) {
40028
40530
  console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
40029
40531
  }
40030
40532
  } catch (err) {
@@ -40133,14 +40635,14 @@ ${detail}`);
40133
40635
  }).filter((r) => r !== void 0);
40134
40636
  }
40135
40637
  transportPlanFile(planFilePath, workspacePath, repoNames) {
40136
- const planContent = fs48.readFileSync(planFilePath, "utf-8");
40137
- const planFileName = path49.basename(planFilePath);
40638
+ const planContent = fs49.readFileSync(planFilePath, "utf-8");
40639
+ const planFileName = path50.basename(planFilePath);
40138
40640
  const targetRepo = repoNames[0];
40139
40641
  if (!targetRepo)
40140
40642
  return;
40141
- const plansDir = path49.join(workspacePath, targetRepo, "docs", "plans");
40142
- fs48.mkdirSync(plansDir, { recursive: true });
40143
- fs48.writeFileSync(path49.join(plansDir, planFileName), planContent);
40643
+ const plansDir = path50.join(workspacePath, targetRepo, "docs", "plans");
40644
+ fs49.mkdirSync(plansDir, { recursive: true });
40645
+ fs49.writeFileSync(path50.join(plansDir, planFileName), planContent);
40144
40646
  }
40145
40647
  resolveServices(repos) {
40146
40648
  const services = [];
@@ -40272,7 +40774,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
40272
40774
  if (seedTemplates.length === 0) {
40273
40775
  return { worldDbNames: [] };
40274
40776
  }
40275
- const spawn4 = options.spawn ?? spawnSync4;
40777
+ const spawn5 = options.spawn ?? spawnSync4;
40276
40778
  const seedToWorldDb = /* @__PURE__ */ new Map();
40277
40779
  for (const seed of seedTemplates) {
40278
40780
  seedToWorldDb.set(seed, deriveWorldDbName(seed, worldId));
@@ -40280,7 +40782,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
40280
40782
  const created = [];
40281
40783
  for (const seed of seedTemplates) {
40282
40784
  const worldDb = seedToWorldDb.get(seed);
40283
- const exists = spawn4("docker", [
40785
+ const exists = spawn5("docker", [
40284
40786
  "exec",
40285
40787
  container,
40286
40788
  "psql",
@@ -40292,7 +40794,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
40292
40794
  const dbAlreadyExists = exists.status === 0 && (exists.stdout || "").trim() === "1";
40293
40795
  if (!dbAlreadyExists) {
40294
40796
  const sql = `CREATE DATABASE "${worldDb}" TEMPLATE "${seed}"`;
40295
- const create = spawn4("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", sql], { encoding: "utf-8" });
40797
+ const create = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", sql], { encoding: "utf-8" });
40296
40798
  if (create.status !== 0) {
40297
40799
  throw new Error(`failed to CREATE DATABASE "${worldDb}" TEMPLATE "${seed}": ${(create.stderr || "").trim()}`);
40298
40800
  }
@@ -40302,7 +40804,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
40302
40804
  if (stmts !== void 0 && stmts.length > 0) {
40303
40805
  for (const rawStmt of stmts) {
40304
40806
  const stmt = interpolatePostCloneSql(rawStmt, worldId, seedToWorldDb);
40305
- const fixup = spawn4("docker", ["exec", container, "psql", "-U", user, "-d", worldDb, "-v", "ON_ERROR_STOP=1", "-c", stmt], { encoding: "utf-8" });
40807
+ const fixup = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", worldDb, "-v", "ON_ERROR_STOP=1", "-c", stmt], { encoding: "utf-8" });
40306
40808
  if (fixup.status !== 0) {
40307
40809
  throw new Error(`post_clone_sql against "${worldDb}" failed (statement: ${truncate(stmt, 120)}): ${(fixup.stderr || "").trim()}`);
40308
40810
  }
@@ -40330,11 +40832,11 @@ function applyPostgresTestTemplateClone(worldId, enrichedRepos, options = {}) {
40330
40832
  if (testTemplates.length === 0) {
40331
40833
  return { worldTestDbNames: [] };
40332
40834
  }
40333
- const spawn4 = options.spawn ?? spawnSync4;
40835
+ const spawn5 = options.spawn ?? spawnSync4;
40334
40836
  const created = [];
40335
40837
  for (const seed of testTemplates) {
40336
40838
  const worldDb = deriveWorldDbName(seed, worldId);
40337
- const exists = spawn4("docker", [
40839
+ const exists = spawn5("docker", [
40338
40840
  "exec",
40339
40841
  container,
40340
40842
  "psql",
@@ -40346,7 +40848,7 @@ function applyPostgresTestTemplateClone(worldId, enrichedRepos, options = {}) {
40346
40848
  const dbAlreadyExists = exists.status === 0 && (exists.stdout || "").trim() === "1";
40347
40849
  if (!dbAlreadyExists) {
40348
40850
  const sql = `CREATE DATABASE "${worldDb}" TEMPLATE "${seed}"`;
40349
- const create = spawn4("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", sql], { encoding: "utf-8" });
40851
+ const create = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", sql], { encoding: "utf-8" });
40350
40852
  if (create.status !== 0) {
40351
40853
  throw new Error(`failed to CREATE DATABASE "${worldDb}" TEMPLATE "${seed}": ${(create.stderr || "").trim()}`);
40352
40854
  }
@@ -40387,13 +40889,13 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
40387
40889
  if (worldDbNames.length === 0) {
40388
40890
  throw new Error(`applyPostgresWorldRole called with empty worldDbNames for "${worldId}" \u2014 should only run when applyPostgresTemplateClone produced clones`);
40389
40891
  }
40390
- const spawn4 = options.spawn ?? spawnSync4;
40892
+ const spawn5 = options.spawn ?? spawnSync4;
40391
40893
  const container = options.singletonContainer ?? "olam-postgres";
40392
40894
  const user = options.postgresUser ?? "development";
40393
40895
  const genPassword = options.generatePassword ?? defaultPasswordGenerator;
40394
40896
  const worldRoleName = deriveWorldRoleName(worldId);
40395
40897
  const password = genPassword();
40396
- const exists = spawn4("docker", [
40898
+ const exists = spawn5("docker", [
40397
40899
  "exec",
40398
40900
  container,
40399
40901
  "psql",
@@ -40405,12 +40907,12 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
40405
40907
  const roleExists = exists.status === 0 && (exists.stdout || "").trim() === "1";
40406
40908
  const escapedPassword = escapeSqlLiteral(password);
40407
40909
  const roleDdl = roleExists ? `ALTER ROLE "${worldRoleName}" WITH LOGIN PASSWORD '${escapedPassword}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION` : `CREATE ROLE "${worldRoleName}" WITH LOGIN PASSWORD '${escapedPassword}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION`;
40408
- const dml = spawn4("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", roleDdl], { encoding: "utf-8" });
40910
+ const dml = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", roleDdl], { encoding: "utf-8" });
40409
40911
  if (dml.status !== 0) {
40410
40912
  throw new Error(`failed to ${roleExists ? "ALTER" : "CREATE"} ROLE "${worldRoleName}": ` + redactCreateRolePassword((dml.stderr || "").trim()));
40411
40913
  }
40412
40914
  for (const worldDb of worldDbNames) {
40413
- const grantConnect = spawn4("docker", [
40915
+ const grantConnect = spawn5("docker", [
40414
40916
  "exec",
40415
40917
  container,
40416
40918
  "psql",
@@ -40435,7 +40937,7 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
40435
40937
  `ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "${worldRoleName}"`,
40436
40938
  `ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO "${worldRoleName}"`
40437
40939
  ].join("; ");
40438
- const grantResult = spawn4("docker", ["exec", container, "psql", "-U", user, "-d", worldDb, "-v", "ON_ERROR_STOP=1", "-c", perDbGrants], { encoding: "utf-8" });
40940
+ const grantResult = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", worldDb, "-v", "ON_ERROR_STOP=1", "-c", perDbGrants], { encoding: "utf-8" });
40439
40941
  if (grantResult.status !== 0) {
40440
40942
  throw new Error(`failed to GRANT privileges on "${worldDb}" to "${worldRoleName}": ${(grantResult.stderr || "").trim()}`);
40441
40943
  }
@@ -40455,11 +40957,11 @@ function dropPostgresWorldDbs(worldId, worldDbNames, options = {}) {
40455
40957
  if (worldDbNames.length === 0)
40456
40958
  return;
40457
40959
  assertSafeWorldId(worldId);
40458
- const spawn4 = options.spawn ?? spawnSync4;
40960
+ const spawn5 = options.spawn ?? spawnSync4;
40459
40961
  const container = options.container ?? "olam-postgres";
40460
40962
  const user = options.user ?? "development";
40461
40963
  for (const db of worldDbNames) {
40462
- const drop = spawn4("docker", [
40964
+ const drop = spawn5("docker", [
40463
40965
  "exec",
40464
40966
  container,
40465
40967
  "psql",
@@ -40479,10 +40981,10 @@ function dropPostgresWorldRole(worldId, worldRoleName, options = {}) {
40479
40981
  if (!worldRoleName)
40480
40982
  return;
40481
40983
  assertSafeWorldId(worldId);
40482
- const spawn4 = options.spawn ?? spawnSync4;
40984
+ const spawn5 = options.spawn ?? spawnSync4;
40483
40985
  const container = options.container ?? "olam-postgres";
40484
40986
  const user = options.user ?? "development";
40485
- const cleanup = spawn4("docker", [
40987
+ const cleanup = spawn5("docker", [
40486
40988
  "exec",
40487
40989
  container,
40488
40990
  "psql",
@@ -40574,8 +41076,8 @@ import * as http2 from "node:http";
40574
41076
 
40575
41077
  // ../core/dist/dashboard/server.js
40576
41078
  import * as http from "node:http";
40577
- import * as fs49 from "node:fs";
40578
- import * as path50 from "node:path";
41079
+ import * as fs50 from "node:fs";
41080
+ import * as path51 from "node:path";
40579
41081
  import { fileURLToPath as fileURLToPath3 } from "node:url";
40580
41082
 
40581
41083
  // ../core/dist/dashboard/serialize.js
@@ -40634,15 +41136,15 @@ function parsePsAux(stdout) {
40634
41136
  continue;
40635
41137
  const cpuPercent = parseFloat(parts[2]) || 0;
40636
41138
  const rssKb = parseInt(parts[5], 10) || 0;
40637
- const stat = parts[7] ?? "";
41139
+ const stat2 = parts[7] ?? "";
40638
41140
  const command = parts.slice(10).join(" ");
40639
41141
  const name = command.split(/\s/)[0]?.split("/").pop() ?? command;
40640
41142
  let status2 = "running";
40641
- if (stat.startsWith("T"))
41143
+ if (stat2.startsWith("T"))
40642
41144
  status2 = "stopped";
40643
- else if (stat.startsWith("Z"))
41145
+ else if (stat2.startsWith("Z"))
40644
41146
  status2 = "error";
40645
- else if (stat.startsWith("S") && cpuPercent === 0)
41147
+ else if (stat2.startsWith("S") && cpuPercent === 0)
40646
41148
  status2 = "idle";
40647
41149
  result.push({
40648
41150
  pid,
@@ -40910,7 +41412,7 @@ function notFound(res) {
40910
41412
  }
40911
41413
  function openThoughtStore(workspacePath) {
40912
41414
  const dbPath = getWorldDbPath(workspacePath);
40913
- if (!fs49.existsSync(dbPath))
41415
+ if (!fs50.existsSync(dbPath))
40914
41416
  return null;
40915
41417
  return new ThoughtLocalStore(dbPath);
40916
41418
  }
@@ -41081,13 +41583,13 @@ function findSessionInWorld(registry2, sessionId) {
41081
41583
  }
41082
41584
  function createDashboardServer(opts) {
41083
41585
  const { port: port2, registry: registry2 } = opts;
41084
- const thisDir = path50.dirname(fileURLToPath3(import.meta.url));
41085
- const defaultPublicDir = path50.resolve(thisDir, "../../../control-plane/public");
41586
+ const thisDir = path51.dirname(fileURLToPath3(import.meta.url));
41587
+ const defaultPublicDir = path51.resolve(thisDir, "../../../control-plane/public");
41086
41588
  const publicDir = opts.publicDir ?? defaultPublicDir;
41087
- let hasPublicDir = fs49.existsSync(publicDir);
41589
+ let hasPublicDir = fs50.existsSync(publicDir);
41088
41590
  const server = http.createServer((req, res) => {
41089
41591
  if (!hasPublicDir) {
41090
- hasPublicDir = fs49.existsSync(publicDir);
41592
+ hasPublicDir = fs50.existsSync(publicDir);
41091
41593
  }
41092
41594
  const host = req.headers.host ?? `localhost:${port2}`;
41093
41595
  const url2 = new URL(req.url ?? "/", `http://${host}`);
@@ -41361,22 +41863,22 @@ function createDashboardServer(opts) {
41361
41863
  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>`);
41362
41864
  return;
41363
41865
  }
41364
- let filePath = path50.join(publicDir, pathname === "/" ? "index.html" : pathname);
41866
+ let filePath = path51.join(publicDir, pathname === "/" ? "index.html" : pathname);
41365
41867
  if (!filePath.startsWith(publicDir)) {
41366
41868
  notFound(res);
41367
41869
  return;
41368
41870
  }
41369
- if (fs49.existsSync(filePath) && fs49.statSync(filePath).isFile()) {
41370
- const ext = path50.extname(filePath);
41871
+ if (fs50.existsSync(filePath) && fs50.statSync(filePath).isFile()) {
41872
+ const ext = path51.extname(filePath);
41371
41873
  const contentType = MIME[ext] ?? "application/octet-stream";
41372
41874
  res.writeHead(200, { "Content-Type": contentType });
41373
- fs49.createReadStream(filePath).pipe(res);
41875
+ fs50.createReadStream(filePath).pipe(res);
41374
41876
  return;
41375
41877
  }
41376
- filePath = path50.join(publicDir, "index.html");
41377
- if (fs49.existsSync(filePath)) {
41878
+ filePath = path51.join(publicDir, "index.html");
41879
+ if (fs50.existsSync(filePath)) {
41378
41880
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
41379
- fs49.createReadStream(filePath).pipe(res);
41881
+ fs50.createReadStream(filePath).pipe(res);
41380
41882
  return;
41381
41883
  }
41382
41884
  notFound(res);
@@ -41386,17 +41888,17 @@ function createDashboardServer(opts) {
41386
41888
  }
41387
41889
 
41388
41890
  // ../core/dist/dashboard/state.js
41389
- import * as fs50 from "node:fs";
41891
+ import * as fs51 from "node:fs";
41390
41892
  import * as os30 from "node:os";
41391
- import * as path51 from "node:path";
41392
- var STATE_PATH = path51.join(os30.homedir(), ".olam", "dashboard.json");
41893
+ import * as path52 from "node:path";
41894
+ var STATE_PATH = path52.join(os30.homedir(), ".olam", "dashboard.json");
41393
41895
  function saveDashboardState(state) {
41394
- fs50.mkdirSync(path51.dirname(STATE_PATH), { recursive: true });
41395
- fs50.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
41896
+ fs51.mkdirSync(path52.dirname(STATE_PATH), { recursive: true });
41897
+ fs51.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
41396
41898
  }
41397
41899
  function loadDashboardState() {
41398
41900
  try {
41399
- const raw = fs50.readFileSync(STATE_PATH, "utf-8");
41901
+ const raw = fs51.readFileSync(STATE_PATH, "utf-8");
41400
41902
  return JSON.parse(raw);
41401
41903
  } catch {
41402
41904
  return null;
@@ -41404,7 +41906,7 @@ function loadDashboardState() {
41404
41906
  }
41405
41907
  function clearDashboardState() {
41406
41908
  try {
41407
- fs50.unlinkSync(STATE_PATH);
41909
+ fs51.unlinkSync(STATE_PATH);
41408
41910
  } catch {
41409
41911
  }
41410
41912
  }
@@ -41422,7 +41924,7 @@ function isDashboardRunning() {
41422
41924
  }
41423
41925
 
41424
41926
  // ../core/dist/dashboard/tunnel.js
41425
- import { spawn as spawn3, execSync as execSync6 } from "node:child_process";
41927
+ import { spawn as spawn4, execSync as execSync6 } from "node:child_process";
41426
41928
  var tunnelProcess = null;
41427
41929
  function isCloudflaredAvailable() {
41428
41930
  try {
@@ -41433,8 +41935,8 @@ function isCloudflaredAvailable() {
41433
41935
  }
41434
41936
  }
41435
41937
  function startTunnel(port2) {
41436
- return new Promise((resolve14, reject2) => {
41437
- const child = spawn3("cloudflared", ["tunnel", "--url", `http://localhost:${port2}`], {
41938
+ return new Promise((resolve15, reject2) => {
41939
+ const child = spawn4("cloudflared", ["tunnel", "--url", `http://localhost:${port2}`], {
41438
41940
  stdio: ["ignore", "pipe", "pipe"],
41439
41941
  detached: false
41440
41942
  });
@@ -41455,7 +41957,7 @@ function startTunnel(port2) {
41455
41957
  if (match) {
41456
41958
  resolved = true;
41457
41959
  clearTimeout(timeout);
41458
- resolve14(match[0]);
41960
+ resolve15(match[0]);
41459
41961
  }
41460
41962
  }
41461
41963
  child.stdout?.on("data", scan);
@@ -41523,8 +42025,8 @@ var DashboardManager = class {
41523
42025
  }
41524
42026
  throw err;
41525
42027
  }
41526
- await new Promise((resolve14, reject2) => {
41527
- this.server.on("listening", resolve14);
42028
+ await new Promise((resolve15, reject2) => {
42029
+ this.server.on("listening", resolve15);
41528
42030
  this.server.on("error", reject2);
41529
42031
  });
41530
42032
  this.info = { localUrl: `http://localhost:${port2}` };
@@ -41570,8 +42072,8 @@ var DashboardManager = class {
41570
42072
  async stop() {
41571
42073
  stopTunnel();
41572
42074
  if (this.server) {
41573
- await new Promise((resolve14) => {
41574
- this.server.close(() => resolve14());
42075
+ await new Promise((resolve15) => {
42076
+ this.server.close(() => resolve15());
41575
42077
  });
41576
42078
  this.server = null;
41577
42079
  }
@@ -41685,7 +42187,7 @@ var PleriClient = class {
41685
42187
 
41686
42188
  // ../mcp-server/src/env-loader.ts
41687
42189
  import { readFileSync as readFileSync39, existsSync as existsSync47, statSync as statSync14 } from "node:fs";
41688
- import { join as join52, dirname as dirname29, resolve as resolve13 } from "node:path";
42190
+ import { join as join52, dirname as dirname29, resolve as resolve14 } from "node:path";
41689
42191
  var PROJECT_MARKERS = [
41690
42192
  ".olam/config.yaml",
41691
42193
  ".olam/config.yml",
@@ -41693,8 +42195,8 @@ var PROJECT_MARKERS = [
41693
42195
  "olam.yml"
41694
42196
  ];
41695
42197
  function findProjectRoot2(startDir) {
41696
- let dir = resolve13(startDir);
41697
- const root = resolve13("/");
42198
+ let dir = resolve14(startDir);
42199
+ const root = resolve14("/");
41698
42200
  while (true) {
41699
42201
  for (const marker of PROJECT_MARKERS) {
41700
42202
  if (existsSync47(join52(dir, marker))) return dir;
@@ -41714,9 +42216,9 @@ function findProjectRoot2(startDir) {
41714
42216
  dir = parent;
41715
42217
  }
41716
42218
  }
41717
- function parseEnvFile(path52) {
42219
+ function parseEnvFile(path53) {
41718
42220
  const out = {};
41719
- const raw = readFileSync39(path52, "utf8");
42221
+ const raw = readFileSync39(path53, "utf8");
41720
42222
  for (const line of raw.split(/\r?\n/)) {
41721
42223
  const trimmed = line.trim();
41722
42224
  if (!trimmed || trimmed.startsWith("#")) continue;