@pleri/olam-cli 0.1.159 → 0.1.160

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 (72) hide show
  1. package/dist/agent-stream/agent-sdk-to-chunks.js +3 -0
  2. package/dist/agent-stream/driver-runner.js +9 -4
  3. package/dist/agent-stream/host-driver-launch.js +48 -0
  4. package/dist/commands/flywheel/check-persona-skeleton.d.ts +30 -2
  5. package/dist/commands/flywheel/check-persona-skeleton.d.ts.map +1 -1
  6. package/dist/commands/flywheel/check-persona-skeleton.js +143 -6
  7. package/dist/commands/flywheel/check-persona-skeleton.js.map +1 -1
  8. package/dist/commands/flywheel/diversity-check.d.ts +12 -2
  9. package/dist/commands/flywheel/diversity-check.d.ts.map +1 -1
  10. package/dist/commands/flywheel/diversity-check.js +56 -6
  11. package/dist/commands/flywheel/diversity-check.js.map +1 -1
  12. package/dist/commands/flywheel/index.d.ts.map +1 -1
  13. package/dist/commands/flywheel/index.js +2 -0
  14. package/dist/commands/flywheel/index.js.map +1 -1
  15. package/dist/commands/flywheel/install-shims.d.ts +36 -3
  16. package/dist/commands/flywheel/install-shims.d.ts.map +1 -1
  17. package/dist/commands/flywheel/install-shims.js +118 -7
  18. package/dist/commands/flywheel/install-shims.js.map +1 -1
  19. package/dist/commands/flywheel/k10-measure.d.ts +12 -2
  20. package/dist/commands/flywheel/k10-measure.d.ts.map +1 -1
  21. package/dist/commands/flywheel/k10-measure.js +55 -6
  22. package/dist/commands/flywheel/k10-measure.js.map +1 -1
  23. package/dist/commands/flywheel/migrate-overlays.d.ts +115 -0
  24. package/dist/commands/flywheel/migrate-overlays.d.ts.map +1 -0
  25. package/dist/commands/flywheel/migrate-overlays.js +766 -0
  26. package/dist/commands/flywheel/migrate-overlays.js.map +1 -0
  27. package/dist/commands/flywheel/sanitize-persona-output.d.ts +33 -2
  28. package/dist/commands/flywheel/sanitize-persona-output.d.ts.map +1 -1
  29. package/dist/commands/flywheel/sanitize-persona-output.js +94 -6
  30. package/dist/commands/flywheel/sanitize-persona-output.js.map +1 -1
  31. package/dist/commands/memory/index.d.ts.map +1 -1
  32. package/dist/commands/memory/index.js +2 -0
  33. package/dist/commands/memory/index.js.map +1 -1
  34. package/dist/commands/memory/install-hooks.d.ts +22 -0
  35. package/dist/commands/memory/install-hooks.d.ts.map +1 -0
  36. package/dist/commands/memory/install-hooks.js +156 -0
  37. package/dist/commands/memory/install-hooks.js.map +1 -0
  38. package/dist/commands/skills-doctor.js +2 -2
  39. package/dist/commands/skills-doctor.js.map +1 -1
  40. package/dist/commands/skills-source.d.ts.map +1 -1
  41. package/dist/commands/skills-source.js +10 -0
  42. package/dist/commands/skills-source.js.map +1 -1
  43. package/dist/commands/skills.d.ts.map +1 -1
  44. package/dist/commands/skills.js +169 -1
  45. package/dist/commands/skills.js.map +1 -1
  46. package/dist/image-digests.json +7 -7
  47. package/dist/index.js +3046 -718
  48. package/dist/lib/flywheel-probes.d.ts +58 -0
  49. package/dist/lib/flywheel-probes.d.ts.map +1 -0
  50. package/dist/lib/flywheel-probes.js +163 -0
  51. package/dist/lib/flywheel-probes.js.map +1 -0
  52. package/dist/lib/shim-generator.d.ts +51 -0
  53. package/dist/lib/shim-generator.d.ts.map +1 -0
  54. package/dist/lib/shim-generator.js +88 -0
  55. package/dist/lib/shim-generator.js.map +1 -0
  56. package/dist/lib/skills-apply-overlays.d.ts +35 -0
  57. package/dist/lib/skills-apply-overlays.d.ts.map +1 -0
  58. package/dist/lib/skills-apply-overlays.js +243 -0
  59. package/dist/lib/skills-apply-overlays.js.map +1 -0
  60. package/dist/mcp-server.js +1106 -453
  61. package/hermes-bundle/version.json +1 -1
  62. package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
  63. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
  64. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
  65. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
  66. package/host-cp/k8s/manifests/memory-service/30-configmap.yaml +11 -0
  67. package/host-cp/k8s/manifests/memory-service/35-configmap-iii-config.yaml +76 -0
  68. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +11 -1
  69. package/host-cp/src/crystallize-planning.mjs +261 -0
  70. package/host-cp/src/plan-chat-service.mjs +84 -2
  71. package/host-cp/src/planning-sessions.mjs +270 -0
  72. 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: path46, errorMaps, issueData } = params;
449
- const fullPath = [...path46, ...issueData.path || []];
448
+ const { data, path: path48, errorMaps, issueData } = params;
449
+ const fullPath = [...path48, ...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, path46, key) {
757
+ constructor(parent, value, path48, key) {
758
758
  this._cachedPath = [];
759
759
  this.parent = parent;
760
760
  this.data = value;
761
- this._path = path46;
761
+ this._path = path48;
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 = resolve13.call(this, root, ref);
7093
+ let _sch = resolve14.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 resolve13(root, ref) {
7120
+ function resolve14(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(path46) {
7336
- let input = path46;
7335
+ function removeDotSegments(path48) {
7336
+ let input = path48;
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 [path46, query] = wsComponent.resourceName.split("?");
7536
- wsComponent.path = path46 && path46 !== "/" ? path46 : void 0;
7535
+ const [path48, query] = wsComponent.resourceName.split("?");
7536
+ wsComponent.path = path48 && path48 !== "/" ? path48 : void 0;
7537
7537
  wsComponent.query = query;
7538
7538
  wsComponent.resourceName = void 0;
7539
7539
  }
@@ -7692,55 +7692,55 @@ var require_fast_uri = __commonJS({
7692
7692
  }
7693
7693
  return uri;
7694
7694
  }
7695
- function resolve13(baseURI, relativeURI, options) {
7695
+ function resolve14(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;
7699
7699
  return serialize(resolved, schemelessOptions);
7700
7700
  }
7701
- function resolveComponent(base, relative3, options, skipNormalization) {
7701
+ function resolveComponent(base, relative5, options, skipNormalization) {
7702
7702
  const target = {};
7703
7703
  if (!skipNormalization) {
7704
7704
  base = parse4(serialize(base, options), options);
7705
- relative3 = parse4(serialize(relative3, options), options);
7705
+ relative5 = parse4(serialize(relative5, options), options);
7706
7706
  }
7707
7707
  options = options || {};
7708
- if (!options.tolerant && relative3.scheme) {
7709
- target.scheme = relative3.scheme;
7710
- target.userinfo = relative3.userinfo;
7711
- target.host = relative3.host;
7712
- target.port = relative3.port;
7713
- target.path = removeDotSegments(relative3.path || "");
7714
- target.query = relative3.query;
7708
+ if (!options.tolerant && relative5.scheme) {
7709
+ target.scheme = relative5.scheme;
7710
+ target.userinfo = relative5.userinfo;
7711
+ target.host = relative5.host;
7712
+ target.port = relative5.port;
7713
+ target.path = removeDotSegments(relative5.path || "");
7714
+ target.query = relative5.query;
7715
7715
  } else {
7716
- if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
7717
- target.userinfo = relative3.userinfo;
7718
- target.host = relative3.host;
7719
- target.port = relative3.port;
7720
- target.path = removeDotSegments(relative3.path || "");
7721
- target.query = relative3.query;
7716
+ if (relative5.userinfo !== void 0 || relative5.host !== void 0 || relative5.port !== void 0) {
7717
+ target.userinfo = relative5.userinfo;
7718
+ target.host = relative5.host;
7719
+ target.port = relative5.port;
7720
+ target.path = removeDotSegments(relative5.path || "");
7721
+ target.query = relative5.query;
7722
7722
  } else {
7723
- if (!relative3.path) {
7723
+ if (!relative5.path) {
7724
7724
  target.path = base.path;
7725
- if (relative3.query !== void 0) {
7726
- target.query = relative3.query;
7725
+ if (relative5.query !== void 0) {
7726
+ target.query = relative5.query;
7727
7727
  } else {
7728
7728
  target.query = base.query;
7729
7729
  }
7730
7730
  } else {
7731
- if (relative3.path[0] === "/") {
7732
- target.path = removeDotSegments(relative3.path);
7731
+ if (relative5.path[0] === "/") {
7732
+ target.path = removeDotSegments(relative5.path);
7733
7733
  } else {
7734
7734
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
7735
- target.path = "/" + relative3.path;
7735
+ target.path = "/" + relative5.path;
7736
7736
  } else if (!base.path) {
7737
- target.path = relative3.path;
7737
+ target.path = relative5.path;
7738
7738
  } else {
7739
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
7739
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative5.path;
7740
7740
  }
7741
7741
  target.path = removeDotSegments(target.path);
7742
7742
  }
7743
- target.query = relative3.query;
7743
+ target.query = relative5.query;
7744
7744
  }
7745
7745
  target.userinfo = base.userinfo;
7746
7746
  target.host = base.host;
@@ -7748,7 +7748,7 @@ var require_fast_uri = __commonJS({
7748
7748
  }
7749
7749
  target.scheme = base.scheme;
7750
7750
  }
7751
- target.fragment = relative3.fragment;
7751
+ target.fragment = relative5.fragment;
7752
7752
  return target;
7753
7753
  }
7754
7754
  function equal(uriA, uriB, options) {
@@ -7919,7 +7919,7 @@ var require_fast_uri = __commonJS({
7919
7919
  var fastUri = {
7920
7920
  SCHEMES,
7921
7921
  normalize,
7922
- resolve: resolve13,
7922
+ resolve: resolve14,
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, fs46, exportName) {
10898
+ function addFormats(ajv, list, fs48, 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, fs46[f]);
10903
+ ajv.addFormat(f, fs48[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, path46, ctx, rejectSource) {
11011
+ function refineForbiddenKeys(value, path48, 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, path46, ctx, rejectSource) {
11016
11016
  if (FORBIDDEN_KEYS.has(key)) {
11017
11017
  ctx.addIssue({
11018
11018
  code: external_exports.ZodIssueCode.custom,
11019
- path: [...path46, key],
11019
+ path: [...path48, key],
11020
11020
  message: `forbidden key "${key}" (prototype-pollution surface)`
11021
11021
  });
11022
11022
  continue;
11023
11023
  }
11024
- if (rejectSource && path46.length === 0 && key === "source") {
11024
+ if (rejectSource && path48.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, path46, ctx, rejectSource) {
11029
11029
  });
11030
11030
  continue;
11031
11031
  }
11032
- refineForbiddenKeys(value[key], [...path46, key], ctx, false);
11032
+ refineForbiddenKeys(value[key], [...path48, key], ctx, false);
11033
11033
  }
11034
11034
  }
11035
- function rejectForbiddenKeys(value, path46, rejectSource) {
11035
+ function rejectForbiddenKeys(value, path48, 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] ${path46}: forbidden key "${key}" (prototype-pollution surface)`);
11041
+ throw new Error(`[manifest] ${path48}: forbidden key "${key}" (prototype-pollution surface)`);
11042
11042
  }
11043
11043
  if (rejectSource && key === "source") {
11044
- throw new Error(`[manifest] ${path46}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11044
+ throw new Error(`[manifest] ${path48}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11045
11045
  }
11046
- rejectForbiddenKeys(value[key], `${path46}.${key}`, false);
11046
+ rejectForbiddenKeys(value[key], `${path48}.${key}`, false);
11047
11047
  }
11048
11048
  }
11049
11049
  function unknownTopLevelKeys(parsed) {
@@ -12462,6 +12462,9 @@ function listSkillSources() {
12462
12462
  function getSkillSource(id) {
12463
12463
  return readGlobalConfig().skillSources.find((s) => s.id === id);
12464
12464
  }
12465
+ function getSkillSourceByName(name) {
12466
+ return readGlobalConfig().skillSources.find((s) => s.name === name) ?? null;
12467
+ }
12465
12468
  function addSkillSource(entry) {
12466
12469
  const config2 = readGlobalConfig();
12467
12470
  const id = deriveSkillSourceId(entry.gitUrl);
@@ -13184,6 +13187,26 @@ function resolveJsonDir(opts) {
13184
13187
  }
13185
13188
  return out;
13186
13189
  }
13190
+ function resolveOverlaysDir(opts) {
13191
+ const { sourceId, baseDir, targetKind } = opts;
13192
+ const out = [];
13193
+ for (const name of listDirSafe(baseDir)) {
13194
+ if (!name.endsWith(".md"))
13195
+ continue;
13196
+ const full = path20.join(baseDir, name);
13197
+ if (!fs19.statSync(full).isFile())
13198
+ continue;
13199
+ const deployBasename = name.replace(/\.md$/, "");
13200
+ out.push({
13201
+ kind: "overlay",
13202
+ sourceId,
13203
+ sourcePath: full,
13204
+ deployBasename,
13205
+ targetKind
13206
+ });
13207
+ }
13208
+ return out;
13209
+ }
13187
13210
  function resolveSourceArtifacts(opts) {
13188
13211
  const { sourceId, clonePath, atlasUser } = opts;
13189
13212
  const subscription = resolveSubscriptions({ clonePath, atlasUser });
@@ -13208,6 +13231,16 @@ function resolveSourceArtifacts(opts) {
13208
13231
  artifacts.push(...resolveRulesDir({ sourceId, baseDir: path20.join(memberRoot, "rules") }));
13209
13232
  artifacts.push(...resolveJsonDir({ sourceId, baseDir: path20.join(memberRoot, "hooks"), kind: "hook" }));
13210
13233
  artifacts.push(...resolveJsonDir({ sourceId, baseDir: path20.join(memberRoot, "permissions"), kind: "permission" }));
13234
+ artifacts.push(...resolveOverlaysDir({
13235
+ sourceId,
13236
+ baseDir: path20.join(memberRoot, "skills.overrides"),
13237
+ targetKind: "skill"
13238
+ }));
13239
+ artifacts.push(...resolveOverlaysDir({
13240
+ sourceId,
13241
+ baseDir: path20.join(memberRoot, "agents.overrides"),
13242
+ targetKind: "agent"
13243
+ }));
13211
13244
  }
13212
13245
  }
13213
13246
  return { subscription, artifacts };
@@ -13218,6 +13251,57 @@ var init_artifact_resolver = __esm({
13218
13251
  }
13219
13252
  });
13220
13253
 
13254
+ // ../core/dist/lib/shim-targets.js
13255
+ function lookupShimTarget(basename6) {
13256
+ return SHIM_TARGETS.find((t) => t.basename === basename6);
13257
+ }
13258
+ function compareSemver(installed, required2) {
13259
+ const norm = (s) => {
13260
+ const clean = s.replace(/^v/, "").split(/[-+]/)[0] ?? "0";
13261
+ const parts = clean.split(".").map((p) => Number.parseInt(p, 10) || 0);
13262
+ while (parts.length < 3)
13263
+ parts.push(0);
13264
+ return parts.slice(0, 3);
13265
+ };
13266
+ const i = norm(installed);
13267
+ const r = norm(required2);
13268
+ for (let idx = 0; idx < 3; idx++) {
13269
+ const diff = (i[idx] ?? 0) - (r[idx] ?? 0);
13270
+ if (diff !== 0)
13271
+ return diff;
13272
+ }
13273
+ return 0;
13274
+ }
13275
+ function checkShimRemoval(basename6, installedOlamVersion) {
13276
+ const target = lookupShimTarget(basename6);
13277
+ if (target === void 0)
13278
+ return null;
13279
+ return {
13280
+ basename: target.basename,
13281
+ replacedBy: target.replacedBy,
13282
+ installedOlamVersion,
13283
+ minOlamVersion: target.minOlamVersion,
13284
+ safeToRemove: compareSemver(installedOlamVersion, target.minOlamVersion) >= 0
13285
+ };
13286
+ }
13287
+ var SHIM_TARGETS;
13288
+ var init_shim_targets = __esm({
13289
+ "../core/dist/lib/shim-targets.js"() {
13290
+ "use strict";
13291
+ SHIM_TARGETS = Object.freeze([
13292
+ { basename: "emit-breadcrumb.sh", minOlamVersion: "0.2.0", replacedBy: "olam flywheel emit-breadcrumb" },
13293
+ { basename: "emit-breadcrumb.py", minOlamVersion: "0.2.0", replacedBy: "olam flywheel emit-breadcrumb" },
13294
+ { basename: "sanitize-persona-output.py", minOlamVersion: "0.2.0", replacedBy: "olam flywheel sanitize-persona-output" },
13295
+ { basename: "check-persona-skeleton.py", minOlamVersion: "0.2.0", replacedBy: "olam flywheel check-persona-skeleton" },
13296
+ { basename: "k5-rubric-helper.py", minOlamVersion: "0.2.0", replacedBy: "olam flywheel k5-validate" },
13297
+ { basename: "k10_budget.py", minOlamVersion: "0.2.0", replacedBy: "olam flywheel k10-measure" },
13298
+ { basename: "diversity_check.py", minOlamVersion: "0.2.0", replacedBy: "olam flywheel diversity-check" },
13299
+ { basename: "apply-overlays.py", minOlamVersion: "0.2.0", replacedBy: "olam skills apply-overlays" },
13300
+ { basename: "sync-with-overlays.sh", minOlamVersion: "0.2.0", replacedBy: "olam skills sync --with-overlays" }
13301
+ ]);
13302
+ }
13303
+ });
13304
+
13221
13305
  // ../core/dist/skill-sync/symlink-deployer.js
13222
13306
  import * as fs20 from "node:fs";
13223
13307
  import * as os13 from "node:os";
@@ -13243,6 +13327,9 @@ function bucketFor(kind) {
13243
13327
  case "hook":
13244
13328
  case "permission":
13245
13329
  return void 0;
13330
+ // handled by settings-merger
13331
+ case "overlay":
13332
+ return void 0;
13246
13333
  }
13247
13334
  }
13248
13335
  function detectCollisions(artifacts) {
@@ -13280,22 +13367,48 @@ function detectCollisions(artifacts) {
13280
13367
  }
13281
13368
  return { winners, collisions };
13282
13369
  }
13283
- function cleanManagedSymlinks(claude) {
13370
+ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences) {
13371
+ const shadowBackups = [];
13284
13372
  for (const bucket of BUCKETS) {
13285
13373
  const dir = path21.join(claude, bucket);
13286
13374
  if (!fs20.existsSync(dir))
13287
13375
  continue;
13288
13376
  for (const name of fs20.readdirSync(dir)) {
13377
+ if (name === ".olam-merged")
13378
+ continue;
13289
13379
  const p = path21.join(dir, name);
13290
13380
  try {
13291
13381
  const stat = fs20.lstatSync(p);
13292
13382
  if (stat.isSymbolicLink()) {
13383
+ if (bucket === "scripts" && overlayReferences !== void 0) {
13384
+ const refs = overlayReferences.get(name);
13385
+ if (refs !== void 0 && refs.length > 0 && checkShimRemoval(name, "0.0.0") !== null) {
13386
+ const firstRef = refs[0];
13387
+ const extraCount = refs.length - 1;
13388
+ const refDisplay = extraCount > 0 ? `${firstRef} (+${extraCount} more)` : firstRef;
13389
+ const nameNoExt = name.replace(/\.[^.]+$/, "");
13390
+ process.stderr.write(`[shim-preserved] ~/.claude/scripts/${name} \u2014 referenced by overlay ${refDisplay}; run \`olam flywheel migrate-overlays\` to update the overlay path, then \`olam flywheel ${nameNoExt}\` to install the replacement.
13391
+ `);
13392
+ continue;
13393
+ }
13394
+ }
13395
+ if (bucket === "scripts" && installedOlamVersion !== void 0) {
13396
+ const check = checkShimRemoval(name, installedOlamVersion);
13397
+ if (check !== null && !check.safeToRemove) {
13398
+ process.stderr.write(`[shim-removal-warn] ~/.claude/scripts/${name} is being removed but operator olam ${check.installedOlamVersion} < flywheel min ${check.minOlamVersion}. After atlas-toolbox stops shipping this script, chain skills hardcoding the path will break. Upgrade to olam \u2265${check.minOlamVersion} + run \`olam flywheel install-shims\` to install the replacement (${check.replacedBy}).
13399
+ `);
13400
+ }
13401
+ }
13293
13402
  fs20.unlinkSync(p);
13403
+ } else if (bucket === "agents" && stat.isFile() && !name.includes(".shadow-backup-")) {
13404
+ const backup = shadowBackup(p);
13405
+ shadowBackups.push(backup);
13294
13406
  }
13295
13407
  } catch {
13296
13408
  }
13297
13409
  }
13298
13410
  }
13411
+ return shadowBackups;
13299
13412
  }
13300
13413
  function shadowBackup(link) {
13301
13414
  const epoch = Math.floor(Date.now() / 1e3);
@@ -13324,19 +13437,26 @@ function linkIfNeeded(target, link) {
13324
13437
  fs20.symlinkSync(target, link);
13325
13438
  return { created: true, shadowBackup: backup };
13326
13439
  }
13327
- function deployArtifacts(artifacts) {
13440
+ function deployArtifacts(artifacts, opts) {
13328
13441
  const claude = claudeDir();
13329
13442
  for (const bucket of BUCKETS) {
13330
13443
  fs20.mkdirSync(path21.join(claude, bucket), { recursive: true });
13331
13444
  }
13332
- cleanManagedSymlinks(claude);
13445
+ const sweepShadowBackups = cleanManagedSymlinks(claude, opts?.installedOlamVersion, opts?.overlayReferences);
13333
13446
  const { winners, collisions } = detectCollisions(artifacts);
13334
- const result = { linked: 0, shadowBackups: [], collisions };
13447
+ const result = { linked: 0, shadowBackups: [...sweepShadowBackups], collisions };
13335
13448
  for (const artifact of winners) {
13336
13449
  const bucket = bucketFor(artifact.kind);
13337
13450
  if (!bucket)
13338
13451
  continue;
13339
13452
  const linkPath = path21.join(claude, bucket, artifact.deployBasename);
13453
+ if (artifact.kind === "agent" && artifact.resolvedContent !== void 0) {
13454
+ const tmpPath = `${linkPath}.tmp-${process.pid}-${Date.now()}`;
13455
+ fs20.writeFileSync(tmpPath, artifact.resolvedContent);
13456
+ fs20.renameSync(tmpPath, linkPath);
13457
+ result.linked += 1;
13458
+ continue;
13459
+ }
13340
13460
  const { created, shadowBackup: backup } = linkIfNeeded(artifact.sourcePath, linkPath);
13341
13461
  if (created)
13342
13462
  result.linked += 1;
@@ -13349,6 +13469,7 @@ var BUCKETS;
13349
13469
  var init_symlink_deployer = __esm({
13350
13470
  "../core/dist/skill-sync/symlink-deployer.js"() {
13351
13471
  "use strict";
13472
+ init_shim_targets();
13352
13473
  BUCKETS = ["commands", "agents", "skills", "scripts", "rules"];
13353
13474
  }
13354
13475
  });
@@ -13817,7 +13938,7 @@ function defaultIsPidAlive(pid) {
13817
13938
  }
13818
13939
  }
13819
13940
  function sleep3(ms) {
13820
- return new Promise((resolve13) => setTimeout(resolve13, ms));
13941
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
13821
13942
  }
13822
13943
  function readLockMeta(lockPath) {
13823
13944
  try {
@@ -13931,13 +14052,179 @@ var init_file_lock = __esm({
13931
14052
  }
13932
14053
  });
13933
14054
 
13934
- // ../core/dist/skill-sync/settings-json-lock.js
14055
+ // ../core/dist/lib/min-version-filter.js
14056
+ import { existsSync as existsSync27, readFileSync as readFileSync23 } from "node:fs";
14057
+ function readOlamMinVersion(filepath) {
14058
+ if (!existsSync27(filepath))
14059
+ return void 0;
14060
+ let text;
14061
+ try {
14062
+ text = readFileSync23(filepath, "utf8");
14063
+ } catch {
14064
+ return void 0;
14065
+ }
14066
+ const match = FM_RE.exec(text);
14067
+ if (match === null)
14068
+ return void 0;
14069
+ const fmText = match[1] ?? "";
14070
+ for (const rawLine of fmText.split("\n")) {
14071
+ const line = rawLine.trim();
14072
+ if (line === "" || line.startsWith("#"))
14073
+ continue;
14074
+ const colonIdx = line.indexOf(":");
14075
+ if (colonIdx === -1)
14076
+ continue;
14077
+ const key = line.slice(0, colonIdx).trim();
14078
+ if (key !== "olam-min-version")
14079
+ continue;
14080
+ const value = line.slice(colonIdx + 1).trim().replace(/^['"]|['"]$/g, "");
14081
+ if (value === "" || !/^v?\d+(\.\d+)*/.test(value))
14082
+ return void 0;
14083
+ return value;
14084
+ }
14085
+ return void 0;
14086
+ }
14087
+ function filterArtifactsByMinVersion(artifacts, installedOlamVersion) {
14088
+ const kept = [];
14089
+ const dropped = [];
14090
+ const warnings = [];
14091
+ for (const artifact of artifacts) {
14092
+ if (!artifact.sourcePath.endsWith(".md")) {
14093
+ kept.push(artifact);
14094
+ continue;
14095
+ }
14096
+ const required2 = readOlamMinVersion(artifact.sourcePath);
14097
+ if (required2 === void 0) {
14098
+ kept.push(artifact);
14099
+ continue;
14100
+ }
14101
+ if (compareSemver(installedOlamVersion, required2) >= 0) {
14102
+ kept.push(artifact);
14103
+ } else {
14104
+ dropped.push({ artifact, required: required2, installed: installedOlamVersion });
14105
+ warnings.push(`[olam-min-version] dropping ${artifact.deployBasename}: requires olam \u2265${required2} but installed is ${installedOlamVersion}. Upgrade olam to deploy this skill.`);
14106
+ }
14107
+ }
14108
+ return { kept, dropped, warnings };
14109
+ }
14110
+ var FM_RE;
14111
+ var init_min_version_filter = __esm({
14112
+ "../core/dist/lib/min-version-filter.js"() {
14113
+ "use strict";
14114
+ init_shim_targets();
14115
+ FM_RE = /^---\n([\s\S]*?)\n---\n?/;
14116
+ }
14117
+ });
14118
+
14119
+ // ../core/dist/skill-sync/overlay-scan.js
13935
14120
  import * as fs26 from "node:fs";
13936
- import * as os16 from "node:os";
13937
14121
  import * as path25 from "node:path";
14122
+ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
14123
+ const result = /* @__PURE__ */ new Map();
14124
+ if (!fs26.existsSync(overlayRoot)) {
14125
+ return result;
14126
+ }
14127
+ if (basenames.length === 0) {
14128
+ return result;
14129
+ }
14130
+ const mdFiles = [];
14131
+ let overlayRootReal;
14132
+ try {
14133
+ overlayRootReal = fs26.realpathSync(overlayRoot);
14134
+ } catch {
14135
+ return result;
14136
+ }
14137
+ for (const subdir of OVERRIDE_SUBDIRS) {
14138
+ const dir = path25.join(overlayRoot, subdir);
14139
+ if (!fs26.existsSync(dir))
14140
+ continue;
14141
+ walkMarkdown(dir, mdFiles, caps.maxFiles);
14142
+ }
14143
+ let totalBytes = 0;
14144
+ for (const filepath of mdFiles) {
14145
+ let realFile;
14146
+ try {
14147
+ realFile = fs26.realpathSync(filepath);
14148
+ } catch (err) {
14149
+ const code = err.code;
14150
+ if (code === "ENOENT" || code === "EACCES")
14151
+ continue;
14152
+ throw err;
14153
+ }
14154
+ const rel = path25.relative(overlayRootReal, realFile);
14155
+ if (rel.startsWith("..") || path25.isAbsolute(rel)) {
14156
+ continue;
14157
+ }
14158
+ let content;
14159
+ try {
14160
+ const stat = fs26.statSync(filepath);
14161
+ totalBytes += stat.size;
14162
+ if (totalBytes > caps.maxTotalBytes) {
14163
+ throw new Error(`[overlay-scan] aborted: overlay tree exceeds ${caps.maxTotalBytes} total bytes. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
14164
+ }
14165
+ content = fs26.readFileSync(filepath, "utf8");
14166
+ } catch (err) {
14167
+ const code = err.code;
14168
+ if (code === "ENOENT" || code === "EACCES") {
14169
+ continue;
14170
+ }
14171
+ throw err;
14172
+ }
14173
+ const relpath = path25.relative(overlayRoot, filepath).split(path25.sep).join("/");
14174
+ for (const basename6 of basenames) {
14175
+ if (content.includes(basename6)) {
14176
+ const list = result.get(basename6) ?? [];
14177
+ list.push(relpath);
14178
+ result.set(basename6, list);
14179
+ }
14180
+ }
14181
+ }
14182
+ return result;
14183
+ }
14184
+ function walkMarkdown(dir, out, cap) {
14185
+ let entries;
14186
+ try {
14187
+ entries = fs26.readdirSync(dir, { withFileTypes: true });
14188
+ } catch (err) {
14189
+ if (err.code === "ENOENT")
14190
+ return;
14191
+ throw err;
14192
+ }
14193
+ for (const entry of entries) {
14194
+ if (out.length >= cap) {
14195
+ throw new Error(`[overlay-scan] aborted: overlay tree contains > ${cap} markdown files. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
14196
+ }
14197
+ const full = path25.join(dir, entry.name);
14198
+ if (entry.isSymbolicLink())
14199
+ continue;
14200
+ if (entry.isDirectory()) {
14201
+ walkMarkdown(full, out, cap);
14202
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
14203
+ out.push(full);
14204
+ }
14205
+ }
14206
+ }
14207
+ var OVERRIDE_SUBDIRS, MAX_FILES, MAX_TOTAL_BYTES, DEFAULT_CAPS;
14208
+ var init_overlay_scan = __esm({
14209
+ "../core/dist/skill-sync/overlay-scan.js"() {
14210
+ "use strict";
14211
+ OVERRIDE_SUBDIRS = ["skills.overrides", "agents.overrides"];
14212
+ MAX_FILES = 5e3;
14213
+ MAX_TOTAL_BYTES = 10 * 1024 * 1024;
14214
+ DEFAULT_CAPS = {
14215
+ maxFiles: MAX_FILES,
14216
+ maxTotalBytes: MAX_TOTAL_BYTES
14217
+ };
14218
+ }
14219
+ });
14220
+
14221
+ // ../core/dist/skill-sync/settings-json-lock.js
14222
+ import * as fs27 from "node:fs";
14223
+ import * as os16 from "node:os";
14224
+ import * as path26 from "node:path";
13938
14225
  function defaultSettingsJsonLockPath() {
13939
- const stateDir = process.env["OLAM_STATE_DIR"] ?? path25.join(os16.homedir(), ".olam", "state");
13940
- return path25.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
14226
+ const stateDir = process.env["OLAM_STATE_DIR"] ?? path26.join(os16.homedir(), ".olam", "state");
14227
+ return path26.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
13941
14228
  }
13942
14229
  function defaultIsPidAlive2(pid) {
13943
14230
  try {
@@ -13949,11 +14236,11 @@ function defaultIsPidAlive2(pid) {
13949
14236
  }
13950
14237
  }
13951
14238
  function sleep4(ms) {
13952
- return new Promise((resolve13) => setTimeout(resolve13, ms));
14239
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
13953
14240
  }
13954
14241
  function readLockMeta2(lockPath) {
13955
14242
  try {
13956
- const raw = fs26.readFileSync(lockPath, "utf-8");
14243
+ const raw = fs27.readFileSync(lockPath, "utf-8");
13957
14244
  const parsed = JSON.parse(raw);
13958
14245
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
13959
14246
  return parsed;
@@ -13976,12 +14263,12 @@ function isLockStale2(meta2, opts) {
13976
14263
  function tryAcquireOnce2(lockPath, meta2, opts) {
13977
14264
  for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
13978
14265
  try {
13979
- fs26.mkdirSync(path25.dirname(lockPath), { recursive: true });
13980
- const fd = fs26.openSync(lockPath, "wx", 384);
14266
+ fs27.mkdirSync(path26.dirname(lockPath), { recursive: true });
14267
+ const fd = fs27.openSync(lockPath, "wx", 384);
13981
14268
  try {
13982
- fs26.writeSync(fd, JSON.stringify(meta2));
14269
+ fs27.writeSync(fd, JSON.stringify(meta2));
13983
14270
  } finally {
13984
- fs26.closeSync(fd);
14271
+ fs27.closeSync(fd);
13985
14272
  }
13986
14273
  return true;
13987
14274
  } catch (err) {
@@ -13999,9 +14286,9 @@ function tryAcquireOnce2(lockPath, meta2, opts) {
13999
14286
  }
14000
14287
  const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
14001
14288
  try {
14002
- fs26.renameSync(lockPath, victimPath);
14289
+ fs27.renameSync(lockPath, victimPath);
14003
14290
  try {
14004
- fs26.unlinkSync(victimPath);
14291
+ fs27.unlinkSync(victimPath);
14005
14292
  } catch {
14006
14293
  }
14007
14294
  } catch (err) {
@@ -14033,7 +14320,7 @@ async function acquireSettingsJsonLock(options = {}) {
14033
14320
  lockPath,
14034
14321
  release: () => {
14035
14322
  try {
14036
- fs26.unlinkSync(lockPath);
14323
+ fs27.unlinkSync(lockPath);
14037
14324
  } catch {
14038
14325
  }
14039
14326
  }
@@ -14136,14 +14423,14 @@ var init_services_status = __esm({
14136
14423
 
14137
14424
  // ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
14138
14425
  import * as crypto5 from "node:crypto";
14139
- import * as fs27 from "node:fs";
14426
+ import * as fs28 from "node:fs";
14140
14427
  import * as os17 from "node:os";
14141
- import * as path26 from "node:path";
14428
+ import * as path27 from "node:path";
14142
14429
  function migrationSnapshotsDir2() {
14143
14430
  const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
14144
14431
  if (override && override.length > 0)
14145
14432
  return override;
14146
- return path26.join(os17.homedir(), ".olam", "state", "migration-snapshots");
14433
+ return path27.join(os17.homedir(), ".olam", "state", "migration-snapshots");
14147
14434
  }
14148
14435
  function writeMetaHooksSnapshot(originalSettings) {
14149
14436
  const snapshot = {
@@ -14154,11 +14441,11 @@ function writeMetaHooksSnapshot(originalSettings) {
14154
14441
  };
14155
14442
  const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
14156
14443
  const dir = migrationSnapshotsDir2();
14157
- fs27.mkdirSync(dir, { recursive: true });
14444
+ fs28.mkdirSync(dir, { recursive: true });
14158
14445
  const stamp = validated.takenAt.replace(/[:.]/g, "-");
14159
14446
  const rand = crypto5.randomBytes(3).toString("hex");
14160
- const file = path26.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
14161
- fs27.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
14447
+ const file = path27.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
14448
+ fs28.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
14162
14449
  return file;
14163
14450
  }
14164
14451
  var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
@@ -14389,17 +14676,206 @@ var init_meta_hook_injector = __esm({
14389
14676
  }
14390
14677
  });
14391
14678
 
14679
+ // ../core/dist/lib/markdown-merger.js
14680
+ import { createHash as createHash5 } from "node:crypto";
14681
+ import { readFileSync as readFileSync27, existsSync as existsSync30, statSync as statSync8 } from "node:fs";
14682
+ function parseFrontmatter(text) {
14683
+ const match = FM_RE2.exec(text);
14684
+ if (match === null)
14685
+ return { fm: {}, body: text };
14686
+ const fmText = match[1] ?? "";
14687
+ const body = text.slice(match[0].length);
14688
+ const fm = {};
14689
+ for (const rawLine of fmText.split("\n")) {
14690
+ const line = rawLine.trim();
14691
+ if (line === "" || line.startsWith("#"))
14692
+ continue;
14693
+ const colonIdx = line.indexOf(":");
14694
+ if (colonIdx === -1)
14695
+ continue;
14696
+ const key = line.slice(0, colonIdx).trim();
14697
+ const value = line.slice(colonIdx + 1).trim();
14698
+ fm[key] = value;
14699
+ }
14700
+ return { fm, body };
14701
+ }
14702
+ function serializeFrontmatter(fm) {
14703
+ if (Object.keys(fm).length === 0)
14704
+ return "";
14705
+ const lines = ["---"];
14706
+ for (const [k, v] of Object.entries(fm)) {
14707
+ lines.push(`${k}: ${v}`);
14708
+ }
14709
+ lines.push("---");
14710
+ return lines.join("\n") + "\n";
14711
+ }
14712
+ function parseSections(body) {
14713
+ H2_RE.lastIndex = 0;
14714
+ const parts = body.split(H2_RE);
14715
+ const sections = [[null, parts[0] ?? ""]];
14716
+ for (let i = 1; i < parts.length; i += 2) {
14717
+ const heading = parts[i] ?? "";
14718
+ const content = parts[i + 1] ?? "";
14719
+ sections.push([heading, content]);
14720
+ }
14721
+ return sections;
14722
+ }
14723
+ function sectionsToBody(sections) {
14724
+ const out = [];
14725
+ for (const [heading, content] of sections) {
14726
+ if (heading === null) {
14727
+ out.push(content);
14728
+ } else {
14729
+ const current = out.join("");
14730
+ if (current !== "" && !current.endsWith("\n\n")) {
14731
+ if (current.endsWith("\n"))
14732
+ out.push("\n");
14733
+ else
14734
+ out.push("\n\n");
14735
+ }
14736
+ out.push(heading + content);
14737
+ }
14738
+ }
14739
+ return out.join("");
14740
+ }
14741
+ function mergeMarkdown(upstreamText, overlayText, labelForError, upstreamPath, overlayPath) {
14742
+ const upstream = parseFrontmatter(upstreamText);
14743
+ const overlay = parseFrontmatter(overlayText);
14744
+ const upHasName = "name" in upstream.fm;
14745
+ const ovHasName = "name" in overlay.fm;
14746
+ if (upHasName !== ovHasName) {
14747
+ return {
14748
+ error: {
14749
+ kind: "schema-mismatch",
14750
+ reason: `[schema-mismatch] ${labelForError}: upstream ${upHasName ? "has" : "lacks"} \`name:\` in frontmatter but overlay ${ovHasName ? "has" : "lacks"} it.` + (upstreamPath !== void 0 ? `
14751
+ upstream: ${upstreamPath}` : "") + (overlayPath !== void 0 ? `
14752
+ overlay: ${overlayPath}` : "")
14753
+ }
14754
+ };
14755
+ }
14756
+ const upstreamStartsFm = upstreamText.startsWith("---");
14757
+ const overlayStartsFm = overlayText.startsWith("---");
14758
+ if (upstreamStartsFm !== overlayStartsFm) {
14759
+ return {
14760
+ error: {
14761
+ kind: "schema-mismatch",
14762
+ reason: `[schema-mismatch] ${labelForError}: one file has YAML frontmatter, the other does not.` + (upstreamPath !== void 0 ? `
14763
+ upstream: ${upstreamPath}` : "") + (overlayPath !== void 0 ? `
14764
+ overlay: ${overlayPath}` : "")
14765
+ }
14766
+ };
14767
+ }
14768
+ const mergedFm = { ...upstream.fm, ...overlay.fm };
14769
+ const upSections = parseSections(upstream.body);
14770
+ const ovSections = parseSections(overlay.body);
14771
+ const ovByHeading = /* @__PURE__ */ new Map();
14772
+ const ovHeadingsOrder = [];
14773
+ for (const [heading, content] of ovSections) {
14774
+ if (heading !== null) {
14775
+ ovByHeading.set(heading, content);
14776
+ ovHeadingsOrder.push(heading);
14777
+ }
14778
+ }
14779
+ const mergedSections = [];
14780
+ const upHeadingsSeen = /* @__PURE__ */ new Set();
14781
+ for (const [heading, content] of upSections) {
14782
+ if (heading === null) {
14783
+ const preamble = content.trim() !== "" ? content : ovSections[0]?.[1] ?? content;
14784
+ mergedSections.push([null, preamble]);
14785
+ } else {
14786
+ const overrideContent = ovByHeading.get(heading);
14787
+ mergedSections.push([heading, overrideContent !== void 0 ? overrideContent : content]);
14788
+ upHeadingsSeen.add(heading);
14789
+ }
14790
+ }
14791
+ for (const heading of ovHeadingsOrder) {
14792
+ if (!upHeadingsSeen.has(heading)) {
14793
+ mergedSections.push([heading, ovByHeading.get(heading)]);
14794
+ }
14795
+ }
14796
+ const mergedBody = sectionsToBody(mergedSections);
14797
+ const fmBlock = serializeFrontmatter(mergedFm);
14798
+ return { merged: fmBlock !== "" ? fmBlock + mergedBody : mergedBody };
14799
+ }
14800
+ function sha256OfPath(p) {
14801
+ if (!existsSync30(p) || !statSync8(p).isFile())
14802
+ return "MISSING";
14803
+ return createHash5("sha256").update(readFileSync27(p)).digest("hex");
14804
+ }
14805
+ var FM_RE2, H2_RE;
14806
+ var init_markdown_merger = __esm({
14807
+ "../core/dist/lib/markdown-merger.js"() {
14808
+ "use strict";
14809
+ FM_RE2 = /^---\n([\s\S]*?)\n---\n?/;
14810
+ H2_RE = /^(## .+)$/gm;
14811
+ }
14812
+ });
14813
+
14814
+ // ../core/dist/skill-sync/managed-merge.js
14815
+ import * as fs29 from "node:fs";
14816
+ import * as path28 from "node:path";
14817
+ function materializeMergedSkill(opts) {
14818
+ const { sourceId, sourcePath, deployBasename, mergedContent, claudeDir: claudeDir2 } = opts;
14819
+ const managedDir = path28.join(claudeDir2, ".olam-merged", sourceId, deployBasename);
14820
+ const sourceRoot = path28.resolve(path28.join(claudeDir2, ".olam-merged", sourceId));
14821
+ const managedResolved = path28.resolve(managedDir);
14822
+ if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path28.sep))) {
14823
+ throw new Error(`[managed-merge] refusing to materialize: deployBasename "${deployBasename}" escapes managed root "${sourceRoot}" (resolved to "${managedResolved}")`);
14824
+ }
14825
+ fs29.mkdirSync(managedDir, { recursive: true });
14826
+ const skillMdPath = path28.join(managedDir, "SKILL.md");
14827
+ const tmpPath = `${skillMdPath}.tmp-${process.pid}-${Date.now()}`;
14828
+ fs29.writeFileSync(tmpPath, mergedContent);
14829
+ fs29.renameSync(tmpPath, skillMdPath);
14830
+ const baseEntries = fs29.readdirSync(sourcePath);
14831
+ for (const entry of baseEntries) {
14832
+ if (entry === "SKILL.md")
14833
+ continue;
14834
+ const linkPath = path28.join(managedDir, entry);
14835
+ const targetAbsolute = path28.join(sourcePath, entry);
14836
+ const targetRelative = path28.relative(managedDir, targetAbsolute);
14837
+ try {
14838
+ fs29.lstatSync(linkPath);
14839
+ fs29.rmSync(linkPath, { recursive: true, force: true });
14840
+ } catch {
14841
+ }
14842
+ fs29.symlinkSync(targetRelative, linkPath);
14843
+ }
14844
+ const managedEntries = fs29.readdirSync(managedDir);
14845
+ const baseEntrySet = new Set(baseEntries);
14846
+ for (const entry of managedEntries) {
14847
+ if (entry === "SKILL.md")
14848
+ continue;
14849
+ if (!baseEntrySet.has(entry)) {
14850
+ const stalePath = path28.join(managedDir, entry);
14851
+ try {
14852
+ fs29.rmSync(stalePath, { recursive: true, force: true });
14853
+ } catch {
14854
+ }
14855
+ }
14856
+ }
14857
+ return managedDir;
14858
+ }
14859
+ function cleanMergedDir(claudeDir2) {
14860
+ fs29.rmSync(path28.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
14861
+ }
14862
+ var init_managed_merge = __esm({
14863
+ "../core/dist/skill-sync/managed-merge.js"() {
14864
+ "use strict";
14865
+ }
14866
+ });
14867
+
14392
14868
  // ../core/dist/skill-sync/engine.js
14393
- import * as fs28 from "node:fs";
14869
+ import * as fs30 from "node:fs";
14394
14870
  import * as os18 from "node:os";
14395
- import * as path27 from "node:path";
14871
+ import * as path29 from "node:path";
14396
14872
  function resolveAtlasUser(override) {
14397
14873
  if (override)
14398
14874
  return override;
14399
- const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path27.join(os18.homedir(), ".claude");
14400
- const f = path27.join(claudeDir2, ".atlas-user");
14401
- if (fs28.existsSync(f)) {
14402
- return fs28.readFileSync(f, "utf-8").trim() || void 0;
14875
+ const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path29.join(os18.homedir(), ".claude");
14876
+ const f = path29.join(claudeDir2, ".atlas-user");
14877
+ if (fs30.existsSync(f)) {
14878
+ return fs30.readFileSync(f, "utf-8").trim() || void 0;
14403
14879
  }
14404
14880
  return void 0;
14405
14881
  }
@@ -14411,7 +14887,7 @@ async function syncSkills(opts = {}) {
14411
14887
  const perSource = [];
14412
14888
  for (const source of sources) {
14413
14889
  const clonePath = skillSourceClonePath(source.id);
14414
- if (!fs28.existsSync(clonePath))
14890
+ if (!fs30.existsSync(clonePath))
14415
14891
  continue;
14416
14892
  const { artifacts, subscription } = await withFileLock(clonePath, () => {
14417
14893
  const pinRef = projectOverride?.override.pin?.[source.id];
@@ -14438,7 +14914,57 @@ async function syncSkills(opts = {}) {
14438
14914
  fromSubscriptionsFile: subscription.fromSubscriptionsFile
14439
14915
  });
14440
14916
  }
14441
- const projectFilteredArtifacts = projectOverride ? applyOverrideToArtifacts(allArtifacts, projectOverride.override) : allArtifacts;
14917
+ const projectOverrideFilteredArtifacts = projectOverride ? applyOverrideToArtifacts(allArtifacts, projectOverride.override) : allArtifacts;
14918
+ const installedOlamVersion = opts.installedOlamVersion ?? process.env["OLAM_VERSION"] ?? "0.0.0";
14919
+ const minVersionResult = filterArtifactsByMinVersion(projectOverrideFilteredArtifacts, installedOlamVersion);
14920
+ for (const warning of minVersionResult.warnings) {
14921
+ process.stderr.write(`${warning}
14922
+ `);
14923
+ }
14924
+ const projectFilteredArtifacts = minVersionResult.kept;
14925
+ const memberOverlaysEnabled = process.env["OLAM_MEMBER_OVERLAYS"] === "1";
14926
+ const baseArtifacts = projectFilteredArtifacts.filter((a) => a.kind !== "overlay");
14927
+ const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
14928
+ if (memberOverlaysEnabled && overlayArtifacts.length > 0 && !opts.dryRun) {
14929
+ const claude = claudeDir();
14930
+ cleanMergedDir(claude);
14931
+ for (const overlay of overlayArtifacts) {
14932
+ if (!overlay.targetKind)
14933
+ continue;
14934
+ const base = baseArtifacts.find((a) => a.sourceId === overlay.sourceId && a.kind === overlay.targetKind && a.deployBasename === overlay.deployBasename);
14935
+ if (!base)
14936
+ continue;
14937
+ let baseContent;
14938
+ let basePath;
14939
+ if (overlay.targetKind === "skill") {
14940
+ basePath = path29.join(base.sourcePath, "SKILL.md");
14941
+ baseContent = fs30.readFileSync(basePath, "utf-8");
14942
+ } else {
14943
+ basePath = base.sourcePath;
14944
+ baseContent = fs30.readFileSync(basePath, "utf-8");
14945
+ }
14946
+ const overlayContent = fs30.readFileSync(overlay.sourcePath, "utf-8");
14947
+ const label = `${overlay.sourceId}/${overlay.deployBasename}`;
14948
+ const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
14949
+ if ("error" in mergeResult) {
14950
+ process.stderr.write(`[no-such-section] ${label}
14951
+ `);
14952
+ continue;
14953
+ }
14954
+ const mergedBuffer = Buffer.from(mergeResult.merged, "utf-8");
14955
+ base.resolvedContent = mergedBuffer;
14956
+ if (overlay.targetKind === "skill") {
14957
+ const managedDir = materializeMergedSkill({
14958
+ sourceId: base.sourceId,
14959
+ sourcePath: base.sourcePath,
14960
+ deployBasename: base.deployBasename,
14961
+ mergedContent: mergedBuffer,
14962
+ claudeDir: claude
14963
+ });
14964
+ base.sourcePath = managedDir;
14965
+ }
14966
+ }
14967
+ }
14442
14968
  const hookFiles = projectFilteredArtifacts.filter((a) => a.kind === "hook").map((a) => a.sourcePath);
14443
14969
  const permissionFiles = projectFilteredArtifacts.filter((a) => a.kind === "permission").map((a) => a.sourcePath);
14444
14970
  const summary = {
@@ -14454,10 +14980,15 @@ async function syncSkills(opts = {}) {
14454
14980
  perSource
14455
14981
  };
14456
14982
  if (opts.dryRun) {
14457
- summary.collisions = detectCollisions(projectFilteredArtifacts).collisions;
14983
+ summary.collisions = detectCollisions(baseArtifacts).collisions;
14458
14984
  return summary;
14459
14985
  }
14460
- summary.deploy = deployArtifacts(projectFilteredArtifacts);
14986
+ const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path29.join(os18.homedir(), ".claude");
14987
+ const overlayReferences = scanOverlayReferences(claudeDirPath, SHIM_TARGETS.map((t) => t.basename));
14988
+ summary.deploy = deployArtifacts(baseArtifacts, {
14989
+ installedOlamVersion,
14990
+ overlayReferences
14991
+ });
14461
14992
  summary.collisions = summary.deploy.collisions;
14462
14993
  summary.merge = mergeSettings({ hookFiles, permissionFiles });
14463
14994
  if (opts.metaHooks !== "never") {
@@ -14478,19 +15009,19 @@ async function injectMetaHooksIntoSettings(opts) {
14478
15009
  const result = await withSettingsJsonLock(() => {
14479
15010
  let currentSettings = {};
14480
15011
  let settingsExisted = false;
14481
- if (fs28.existsSync(settingsFile)) {
15012
+ if (fs30.existsSync(settingsFile)) {
14482
15013
  settingsExisted = true;
14483
15014
  try {
14484
- const raw = fs28.readFileSync(settingsFile, "utf-8");
15015
+ const raw = fs30.readFileSync(settingsFile, "utf-8");
14485
15016
  currentSettings = raw.trim() ? JSON.parse(raw) : {};
14486
15017
  } catch {
14487
15018
  try {
14488
- const raw = fs28.readFileSync(settingsFile);
14489
- const bakDir = path27.join(path27.dirname(settingsFile), ".malformed-backups");
14490
- fs28.mkdirSync(bakDir, { recursive: true });
15019
+ const raw = fs30.readFileSync(settingsFile);
15020
+ const bakDir = path29.join(path29.dirname(settingsFile), ".malformed-backups");
15021
+ fs30.mkdirSync(bakDir, { recursive: true });
14491
15022
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
14492
- const bakFile = path27.join(bakDir, `settings.json.malformed.${stamp}.bak`);
14493
- fs28.writeFileSync(bakFile, raw, { mode: 384 });
15023
+ const bakFile = path29.join(bakDir, `settings.json.malformed.${stamp}.bak`);
15024
+ fs30.writeFileSync(bakFile, raw, { mode: 384 });
14494
15025
  snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
14495
15026
  } catch (bakErr) {
14496
15027
  snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
@@ -14540,10 +15071,10 @@ async function injectMetaHooksIntoSettings(opts) {
14540
15071
  } catch {
14541
15072
  }
14542
15073
  }
14543
- fs28.mkdirSync(path27.dirname(settingsFile), { recursive: true });
15074
+ fs30.mkdirSync(path29.dirname(settingsFile), { recursive: true });
14544
15075
  const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
14545
- fs28.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
14546
- fs28.renameSync(tmpPath, settingsFile);
15076
+ fs30.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
15077
+ fs30.renameSync(tmpPath, settingsFile);
14547
15078
  return inject;
14548
15079
  }, { reason: `syncSkills meta-hook injection (mode=${mode})` });
14549
15080
  return {
@@ -14566,29 +15097,34 @@ var init_engine = __esm({
14566
15097
  init_settings_merger();
14567
15098
  init_per_project_override();
14568
15099
  init_file_lock();
15100
+ init_min_version_filter();
15101
+ init_shim_targets();
15102
+ init_overlay_scan();
14569
15103
  init_settings_json_lock();
14570
15104
  init_services_status();
14571
15105
  init_meta_hooks_migration_snapshot();
14572
15106
  init_trust_audit_log();
14573
15107
  init_atlas_hook_strip();
14574
15108
  init_meta_hook_injector();
15109
+ init_markdown_merger();
15110
+ init_managed_merge();
14575
15111
  }
14576
15112
  });
14577
15113
 
14578
15114
  // ../core/dist/skill-sync/shadow-backup-manager.js
14579
- import * as fs29 from "node:fs";
14580
- import * as path28 from "node:path";
15115
+ import * as fs31 from "node:fs";
15116
+ import * as path30 from "node:path";
14581
15117
  function listShadowBackups(opts = {}) {
14582
15118
  const claude = opts.claudeDirOverride ?? claudeDir();
14583
15119
  const now = opts.now ?? Date.now();
14584
15120
  const out = [];
14585
15121
  for (const bucket of SHADOW_BACKUP_BUCKETS) {
14586
- const bucketDir = path28.join(claude, bucket);
14587
- if (!fs29.existsSync(bucketDir))
15122
+ const bucketDir = path30.join(claude, bucket);
15123
+ if (!fs31.existsSync(bucketDir))
14588
15124
  continue;
14589
15125
  let entries;
14590
15126
  try {
14591
- entries = fs29.readdirSync(bucketDir);
15127
+ entries = fs31.readdirSync(bucketDir);
14592
15128
  } catch {
14593
15129
  continue;
14594
15130
  }
@@ -14599,10 +15135,10 @@ function listShadowBackups(opts = {}) {
14599
15135
  const epochSeconds = Number.parseInt(match[1], 10);
14600
15136
  if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
14601
15137
  continue;
14602
- const full = path28.join(bucketDir, name);
15138
+ const full = path30.join(bucketDir, name);
14603
15139
  let sizeBytes = 0;
14604
15140
  try {
14605
- const st = fs29.statSync(full);
15141
+ const st = fs31.statSync(full);
14606
15142
  if (st.isDirectory())
14607
15143
  continue;
14608
15144
  sizeBytes = st.size;
@@ -14615,7 +15151,7 @@ function listShadowBackups(opts = {}) {
14615
15151
  bucket,
14616
15152
  basename: name,
14617
15153
  originalBasename,
14618
- originalPath: path28.join(bucketDir, originalBasename),
15154
+ originalPath: path30.join(bucketDir, originalBasename),
14619
15155
  epochSeconds,
14620
15156
  ageMs: now - epochSeconds * 1e3,
14621
15157
  sizeBytes
@@ -14658,7 +15194,7 @@ function pruneShadowBackups(opts) {
14658
15194
  }
14659
15195
  if (!opts.dryRun) {
14660
15196
  try {
14661
- fs29.unlinkSync(b.path);
15197
+ fs31.unlinkSync(b.path);
14662
15198
  } catch {
14663
15199
  skipped.push(b);
14664
15200
  continue;
@@ -14669,24 +15205,24 @@ function pruneShadowBackups(opts) {
14669
15205
  return { deleted, skipped };
14670
15206
  }
14671
15207
  function restoreShadowBackup(opts) {
14672
- const abs = path28.resolve(opts.backupPath);
14673
- if (!fs29.existsSync(abs)) {
15208
+ const abs = path30.resolve(opts.backupPath);
15209
+ if (!fs31.existsSync(abs)) {
14674
15210
  throw new Error(`backup file not found: ${abs}`);
14675
15211
  }
14676
- const basename6 = path28.basename(abs);
15212
+ const basename6 = path30.basename(abs);
14677
15213
  const match = SHADOW_BACKUP_SUFFIX_RE.exec(basename6);
14678
15214
  if (!match) {
14679
15215
  throw new Error(`not a shadow-backup file (basename "${basename6}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
14680
15216
  }
14681
15217
  const originalBasename = basename6.slice(0, basename6.length - match[0].length);
14682
- const originalPath = path28.join(path28.dirname(abs), originalBasename);
14683
- if (fs29.existsSync(originalPath) && !opts.force) {
15218
+ const originalPath = path30.join(path30.dirname(abs), originalBasename);
15219
+ if (fs31.existsSync(originalPath) && !opts.force) {
14684
15220
  throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
14685
15221
  }
14686
- if (opts.force && fs29.existsSync(originalPath)) {
14687
- fs29.unlinkSync(originalPath);
15222
+ if (opts.force && fs31.existsSync(originalPath)) {
15223
+ fs31.unlinkSync(originalPath);
14688
15224
  }
14689
- fs29.renameSync(abs, originalPath);
15225
+ fs31.renameSync(abs, originalPath);
14690
15226
  return { restoredTo: originalPath };
14691
15227
  }
14692
15228
  var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
@@ -14700,14 +15236,14 @@ var init_shadow_backup_manager = __esm({
14700
15236
  });
14701
15237
 
14702
15238
  // ../core/dist/skill-sources/doctor-checks.js
14703
- import * as fs30 from "node:fs";
14704
- import * as path29 from "node:path";
15239
+ import * as fs32 from "node:fs";
15240
+ import * as path31 from "node:path";
14705
15241
  import * as os19 from "node:os";
14706
15242
  function claudeDirInternal3() {
14707
15243
  const override = process.env["OLAM_CLAUDE_DIR"];
14708
15244
  if (override && override.length > 0)
14709
15245
  return override;
14710
- return path29.join(os19.homedir(), ".claude");
15246
+ return path31.join(os19.homedir(), ".claude");
14711
15247
  }
14712
15248
  function checkStateFileParse() {
14713
15249
  const filePath = globalConfigPath();
@@ -14716,11 +15252,11 @@ function checkStateFileParse() {
14716
15252
  healthy: true,
14717
15253
  description: `~/.olam state file (${filePath})`
14718
15254
  };
14719
- if (!fs30.existsSync(filePath)) {
15255
+ if (!fs32.existsSync(filePath)) {
14720
15256
  result.details = ["(file does not yet exist \u2014 will be created on first write)"];
14721
15257
  return result;
14722
15258
  }
14723
- const raw = fs30.readFileSync(filePath, "utf-8");
15259
+ const raw = fs32.readFileSync(filePath, "utf-8");
14724
15260
  let parsed;
14725
15261
  try {
14726
15262
  parsed = JSON.parse(raw);
@@ -14730,8 +15266,8 @@ function checkStateFileParse() {
14730
15266
  result.details = [err instanceof Error ? err.message : String(err)];
14731
15267
  result.repair = () => {
14732
15268
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
14733
- fs30.renameSync(filePath, aside);
14734
- fs30.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
15269
+ fs32.renameSync(filePath, aside);
15270
+ fs32.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
14735
15271
  };
14736
15272
  return result;
14737
15273
  }
@@ -14742,7 +15278,7 @@ function checkStateFileParse() {
14742
15278
  result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
14743
15279
  result.repair = () => {
14744
15280
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
14745
- fs30.copyFileSync(filePath, aside);
15281
+ fs32.copyFileSync(filePath, aside);
14746
15282
  const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
14747
15283
  const next = {
14748
15284
  ...base,
@@ -14751,7 +15287,7 @@ function checkStateFileParse() {
14751
15287
  runbooks: [],
14752
15288
  skillSources: []
14753
15289
  };
14754
- fs30.writeFileSync(filePath, JSON.stringify(next, null, 2));
15290
+ fs32.writeFileSync(filePath, JSON.stringify(next, null, 2));
14755
15291
  };
14756
15292
  return result;
14757
15293
  }
@@ -14762,16 +15298,16 @@ function checkDanglingSymlinks() {
14762
15298
  const buckets = ["commands", "agents", "skills", "scripts", "rules"];
14763
15299
  const dangling = [];
14764
15300
  for (const bucket of buckets) {
14765
- const dir = path29.join(claude, bucket);
14766
- if (!fs30.existsSync(dir))
15301
+ const dir = path31.join(claude, bucket);
15302
+ if (!fs32.existsSync(dir))
14767
15303
  continue;
14768
- for (const name of fs30.readdirSync(dir)) {
14769
- const linkPath = path29.join(dir, name);
15304
+ for (const name of fs32.readdirSync(dir)) {
15305
+ const linkPath = path31.join(dir, name);
14770
15306
  try {
14771
- const lst = fs30.lstatSync(linkPath);
15307
+ const lst = fs32.lstatSync(linkPath);
14772
15308
  if (!lst.isSymbolicLink())
14773
15309
  continue;
14774
- if (!fs30.existsSync(linkPath)) {
15310
+ if (!fs32.existsSync(linkPath)) {
14775
15311
  dangling.push(linkPath);
14776
15312
  }
14777
15313
  } catch {
@@ -14789,7 +15325,7 @@ function checkDanglingSymlinks() {
14789
15325
  result.repair = () => {
14790
15326
  for (const p of dangling) {
14791
15327
  try {
14792
- fs30.unlinkSync(p);
15328
+ fs32.unlinkSync(p);
14793
15329
  } catch {
14794
15330
  }
14795
15331
  }
@@ -14804,19 +15340,19 @@ function checkOrphanedSnapshots() {
14804
15340
  healthy: true,
14805
15341
  description: `orphaned migration snapshots under ${dir}`
14806
15342
  };
14807
- if (!fs30.existsSync(dir)) {
15343
+ if (!fs32.existsSync(dir)) {
14808
15344
  return result;
14809
15345
  }
14810
15346
  const orphans = [];
14811
- for (const name of fs30.readdirSync(dir)) {
15347
+ for (const name of fs32.readdirSync(dir)) {
14812
15348
  if (!name.endsWith(".json"))
14813
15349
  continue;
14814
- const full = path29.join(dir, name);
15350
+ const full = path31.join(dir, name);
14815
15351
  try {
14816
- const stat = fs30.statSync(full);
15352
+ const stat = fs32.statSync(full);
14817
15353
  if (!stat.isFile())
14818
15354
  continue;
14819
- const raw = fs30.readFileSync(full, "utf-8");
15355
+ const raw = fs32.readFileSync(full, "utf-8");
14820
15356
  let parsed;
14821
15357
  try {
14822
15358
  parsed = JSON.parse(raw);
@@ -14841,7 +15377,7 @@ function checkOrphanedSnapshots() {
14841
15377
  result.repair = () => {
14842
15378
  for (const o of orphans) {
14843
15379
  try {
14844
- fs30.unlinkSync(o.path);
15380
+ fs32.unlinkSync(o.path);
14845
15381
  } catch {
14846
15382
  }
14847
15383
  }
@@ -14856,12 +15392,12 @@ function checkSentinelDrift() {
14856
15392
  healthy: true,
14857
15393
  description: `olam-skills sentinel block in ${filePath}`
14858
15394
  };
14859
- if (!fs30.existsSync(filePath)) {
15395
+ if (!fs32.existsSync(filePath)) {
14860
15396
  return result;
14861
15397
  }
14862
15398
  let parsed;
14863
15399
  try {
14864
- parsed = JSON.parse(fs30.readFileSync(filePath, "utf-8"));
15400
+ parsed = JSON.parse(fs32.readFileSync(filePath, "utf-8"));
14865
15401
  } catch {
14866
15402
  return result;
14867
15403
  }
@@ -14902,7 +15438,7 @@ function checkSentinelDrift() {
14902
15438
  backupSettings();
14903
15439
  } catch {
14904
15440
  }
14905
- const next = JSON.parse(fs30.readFileSync(filePath, "utf-8"));
15441
+ const next = JSON.parse(fs32.readFileSync(filePath, "utf-8"));
14906
15442
  if (!next.hooks)
14907
15443
  return;
14908
15444
  for (const stage of Object.keys(next.hooks)) {
@@ -14925,18 +15461,125 @@ function checkSentinelDrift() {
14925
15461
  return bad === void 0;
14926
15462
  });
14927
15463
  }
14928
- fs30.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
15464
+ fs32.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
14929
15465
  };
14930
15466
  }
14931
15467
  return result;
14932
15468
  }
15469
+ function checkMemberNameMissing() {
15470
+ const result = {
15471
+ name: "[member-name-missing]",
15472
+ healthy: true,
15473
+ description: "atlas-toolbox registered and ~/.claude/.atlas-user configured"
15474
+ };
15475
+ let atlasSource;
15476
+ try {
15477
+ atlasSource = getSkillSourceByName("atlas-toolbox");
15478
+ } catch (err) {
15479
+ result.healthy = false;
15480
+ result.issue = `global config unreadable: ${err instanceof Error ? err.message : String(err)}`;
15481
+ return result;
15482
+ }
15483
+ if (atlasSource === null) {
15484
+ result.details = ["(atlas-toolbox source not registered \u2014 check not applicable)"];
15485
+ return result;
15486
+ }
15487
+ const claudeDir2 = claudeDirInternal3();
15488
+ const atlasUserPath = path31.join(claudeDir2, ".atlas-user");
15489
+ const value = fs32.existsSync(atlasUserPath) ? fs32.readFileSync(atlasUserPath, "utf-8").trim() : "";
15490
+ if (value.length > 0) {
15491
+ result.details = [`atlas-user: ${value}`];
15492
+ return result;
15493
+ }
15494
+ result.healthy = false;
15495
+ result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
15496
+ const clonePath = skillSourceClonePath(atlasSource.id);
15497
+ const membersDir = path31.join(clonePath, "members");
15498
+ const existing = fs32.existsSync(membersDir) ? fs32.readdirSync(membersDir).filter((e) => {
15499
+ try {
15500
+ return fs32.statSync(path31.join(membersDir, e)).isDirectory();
15501
+ } catch {
15502
+ return false;
15503
+ }
15504
+ }).sort() : [];
15505
+ result.details = [
15506
+ `Set via: echo <name> > ${atlasUserPath}`,
15507
+ `List existing members: ls ${membersDir}`,
15508
+ ...existing.length > 0 ? [`Existing members: ${existing.join(", ")}`] : []
15509
+ ];
15510
+ return result;
15511
+ }
15512
+ function checkMemberOverlayDrift() {
15513
+ const claudeDir2 = claudeDirInternal3();
15514
+ const atlasUserPath = path31.join(claudeDir2, ".atlas-user");
15515
+ const atlasUser = fs32.existsSync(atlasUserPath) ? fs32.readFileSync(atlasUserPath, "utf-8").trim() : "";
15516
+ if (atlasUser.length === 0) {
15517
+ return [];
15518
+ }
15519
+ let atlasSource;
15520
+ try {
15521
+ atlasSource = getSkillSourceByName("atlas-toolbox");
15522
+ } catch {
15523
+ return [];
15524
+ }
15525
+ if (atlasSource === null) {
15526
+ return [];
15527
+ }
15528
+ const clonePath = skillSourceClonePath(atlasSource.id);
15529
+ const results = [];
15530
+ for (const kind of ["skills", "agents"]) {
15531
+ const localRoot = path31.join(claudeDir2, `${kind}.overrides`);
15532
+ if (!fs32.existsSync(localRoot))
15533
+ continue;
15534
+ let entries;
15535
+ try {
15536
+ entries = fs32.readdirSync(localRoot);
15537
+ } catch {
15538
+ continue;
15539
+ }
15540
+ for (const entry of entries) {
15541
+ const localFile = path31.join(localRoot, entry);
15542
+ let stat;
15543
+ try {
15544
+ stat = fs32.statSync(localFile);
15545
+ } catch {
15546
+ continue;
15547
+ }
15548
+ if (!stat.isFile())
15549
+ continue;
15550
+ const cloneFile = path31.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
15551
+ const localSha = sha256OfPath(localFile);
15552
+ const cloneSha = sha256OfPath(cloneFile);
15553
+ if (localSha === cloneSha) {
15554
+ continue;
15555
+ }
15556
+ const driftResult = {
15557
+ name: `[member-overlay-drift: ${kind}/${entry}]`,
15558
+ healthy: false,
15559
+ description: `Local ${kind}.overrides/${entry} differs from atlas-toolbox member copy`,
15560
+ issue: `SHA mismatch: local=${localSha.slice(0, 8)}\u2026 clone=${cloneSha.slice(0, 8)}\u2026`,
15561
+ details: [
15562
+ `Diff: olam flywheel migrate-overlays --diff ${entry}`,
15563
+ `Push local \u2192 atlas: olam flywheel migrate-overlays --push --target=atlas-toolbox`,
15564
+ `Pull atlas \u2192 local: cp ${cloneFile} ${localFile}`,
15565
+ `Discard local: rm ${localFile}`
15566
+ ]
15567
+ };
15568
+ results.push(driftResult);
15569
+ }
15570
+ }
15571
+ return results;
15572
+ }
14933
15573
  function runAllDoctorChecks() {
14934
- return [
15574
+ const base = [
14935
15575
  checkStateFileParse(),
14936
15576
  checkDanglingSymlinks(),
14937
15577
  checkOrphanedSnapshots(),
14938
- checkSentinelDrift()
15578
+ checkSentinelDrift(),
15579
+ checkMemberNameMissing()
14939
15580
  ];
15581
+ const driftResults = checkMemberOverlayDrift();
15582
+ return [...base, ...driftResults];
14940
15583
  }
14941
15584
  var MigrationSnapshotMinimalSchema;
14942
15585
  var init_doctor_checks = __esm({
@@ -14948,6 +15591,9 @@ var init_doctor_checks = __esm({
14948
15591
  init_migration_snapshot();
14949
15592
  init_hook_template();
14950
15593
  init_settings_merger();
15594
+ init_store2();
15595
+ init_clone();
15596
+ init_markdown_merger();
14951
15597
  MigrationSnapshotMinimalSchema = external_exports.object({
14952
15598
  schemaVersion: external_exports.literal(MIGRATION_SNAPSHOT_SCHEMA_VERSION),
14953
15599
  takenAt: external_exports.string()
@@ -14985,6 +15631,8 @@ __export(skill_sources_exports, {
14985
15631
  backupSettings: () => backupSettings,
14986
15632
  buildSkillsHookEntry: () => buildSkillsHookEntry,
14987
15633
  checkDanglingSymlinks: () => checkDanglingSymlinks,
15634
+ checkMemberNameMissing: () => checkMemberNameMissing,
15635
+ checkMemberOverlayDrift: () => checkMemberOverlayDrift,
14988
15636
  checkOrphanedSnapshots: () => checkOrphanedSnapshots,
14989
15637
  checkSentinelDrift: () => checkSentinelDrift,
14990
15638
  checkStateFileParse: () => checkStateFileParse,
@@ -14998,6 +15646,7 @@ __export(skill_sources_exports, {
14998
15646
  detectToolboxState: () => detectToolboxState,
14999
15647
  findProjectOverride: () => findProjectOverride,
15000
15648
  getSkillSource: () => getSkillSource,
15649
+ getSkillSourceByName: () => getSkillSourceByName,
15001
15650
  installSkillsHookToFile: () => installSkillsHookToFile,
15002
15651
  isSkillsHookInstalled: () => isSkillsHookInstalled,
15003
15652
  listShadowBackups: () => listShadowBackups,
@@ -15015,6 +15664,7 @@ __export(skill_sources_exports, {
15015
15664
  removeSkillSource: () => removeSkillSource,
15016
15665
  removeSkillSourceClone: () => removeSkillSourceClone,
15017
15666
  reorderSkillSource: () => reorderSkillSource,
15667
+ resolveAtlasUser: () => resolveAtlasUser,
15018
15668
  resolveSourceArtifacts: () => resolveSourceArtifacts,
15019
15669
  resolveSubscriptions: () => resolveSubscriptions,
15020
15670
  restoreCloneToBranchHead: () => restoreCloneToBranchHead,
@@ -15310,10 +15960,10 @@ function mergeDefs(...defs) {
15310
15960
  function cloneDef(schema) {
15311
15961
  return mergeDefs(schema._zod.def);
15312
15962
  }
15313
- function getElementAtPath(obj, path46) {
15314
- if (!path46)
15963
+ function getElementAtPath(obj, path48) {
15964
+ if (!path48)
15315
15965
  return obj;
15316
- return path46.reduce((acc, key) => acc?.[key], obj);
15966
+ return path48.reduce((acc, key) => acc?.[key], obj);
15317
15967
  }
15318
15968
  function promiseAllObject(promisesObj) {
15319
15969
  const keys = Object.keys(promisesObj);
@@ -15722,11 +16372,11 @@ function explicitlyAborted(x, startIndex = 0) {
15722
16372
  }
15723
16373
  return false;
15724
16374
  }
15725
- function prefixIssues(path46, issues) {
16375
+ function prefixIssues(path48, issues) {
15726
16376
  return issues.map((iss) => {
15727
16377
  var _a3;
15728
16378
  (_a3 = iss).path ?? (_a3.path = []);
15729
- iss.path.unshift(path46);
16379
+ iss.path.unshift(path48);
15730
16380
  return iss;
15731
16381
  });
15732
16382
  }
@@ -15873,16 +16523,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
15873
16523
  }
15874
16524
  function formatError(error2, mapper = (issue2) => issue2.message) {
15875
16525
  const fieldErrors = { _errors: [] };
15876
- const processError = (error3, path46 = []) => {
16526
+ const processError = (error3, path48 = []) => {
15877
16527
  for (const issue2 of error3.issues) {
15878
16528
  if (issue2.code === "invalid_union" && issue2.errors.length) {
15879
- issue2.errors.map((issues) => processError({ issues }, [...path46, ...issue2.path]));
16529
+ issue2.errors.map((issues) => processError({ issues }, [...path48, ...issue2.path]));
15880
16530
  } else if (issue2.code === "invalid_key") {
15881
- processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
16531
+ processError({ issues: issue2.issues }, [...path48, ...issue2.path]);
15882
16532
  } else if (issue2.code === "invalid_element") {
15883
- processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
16533
+ processError({ issues: issue2.issues }, [...path48, ...issue2.path]);
15884
16534
  } else {
15885
- const fullpath = [...path46, ...issue2.path];
16535
+ const fullpath = [...path48, ...issue2.path];
15886
16536
  if (fullpath.length === 0) {
15887
16537
  fieldErrors._errors.push(mapper(issue2));
15888
16538
  } else {
@@ -22099,12 +22749,12 @@ var StdioServerTransport = class {
22099
22749
  this.onclose?.();
22100
22750
  }
22101
22751
  send(message) {
22102
- return new Promise((resolve13) => {
22752
+ return new Promise((resolve14) => {
22103
22753
  const json = serializeMessage(message);
22104
22754
  if (this._stdout.write(json)) {
22105
- resolve13();
22755
+ resolve14();
22106
22756
  } else {
22107
- this._stdout.once("drain", resolve13);
22757
+ this._stdout.once("drain", resolve14);
22108
22758
  }
22109
22759
  });
22110
22760
  }
@@ -24141,7 +24791,7 @@ var Protocol = class {
24141
24791
  return;
24142
24792
  }
24143
24793
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
24144
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
24794
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
24145
24795
  options?.signal?.throwIfAborted();
24146
24796
  }
24147
24797
  } catch (error2) {
@@ -24158,7 +24808,7 @@ var Protocol = class {
24158
24808
  */
24159
24809
  request(request2, resultSchema, options) {
24160
24810
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
24161
- return new Promise((resolve13, reject2) => {
24811
+ return new Promise((resolve14, reject2) => {
24162
24812
  const earlyReject = (error2) => {
24163
24813
  reject2(error2);
24164
24814
  };
@@ -24236,7 +24886,7 @@ var Protocol = class {
24236
24886
  if (!parseResult.success) {
24237
24887
  reject2(parseResult.error);
24238
24888
  } else {
24239
- resolve13(parseResult.data);
24889
+ resolve14(parseResult.data);
24240
24890
  }
24241
24891
  } catch (error2) {
24242
24892
  reject2(error2);
@@ -24497,12 +25147,12 @@ var Protocol = class {
24497
25147
  }
24498
25148
  } catch {
24499
25149
  }
24500
- return new Promise((resolve13, reject2) => {
25150
+ return new Promise((resolve14, reject2) => {
24501
25151
  if (signal.aborted) {
24502
25152
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
24503
25153
  return;
24504
25154
  }
24505
- const timeoutId = setTimeout(resolve13, interval);
25155
+ const timeoutId = setTimeout(resolve14, interval);
24506
25156
  signal.addEventListener("abort", () => {
24507
25157
  clearTimeout(timeoutId);
24508
25158
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -25602,7 +26252,7 @@ var McpServer = class {
25602
26252
  let task = createTaskResult.task;
25603
26253
  const pollInterval = task.pollInterval ?? 5e3;
25604
26254
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
25605
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
26255
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
25606
26256
  const updatedTask = await extra.taskStore.getTask(taskId);
25607
26257
  if (!updatedTask) {
25608
26258
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -26521,8 +27171,8 @@ var AuthClient = class {
26521
27171
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
26522
27172
  }
26523
27173
  }
26524
- async request(method, path46, body, attempt = 0) {
26525
- const url2 = `${this.baseUrl}${path46}`;
27174
+ async request(method, path48, body, attempt = 0) {
27175
+ const url2 = `${this.baseUrl}${path48}`;
26526
27176
  const controller = new AbortController();
26527
27177
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
26528
27178
  const headers = {};
@@ -26540,7 +27190,7 @@ var AuthClient = class {
26540
27190
  } catch (err) {
26541
27191
  if (attempt < RETRY_COUNT && isTransient(err)) {
26542
27192
  await sleep(RETRY_BACKOFF_MS * (attempt + 1));
26543
- return this.request(method, path46, body, attempt + 1);
27193
+ return this.request(method, path48, body, attempt + 1);
26544
27194
  }
26545
27195
  throw err;
26546
27196
  } finally {
@@ -26567,7 +27217,7 @@ async function safeText(res) {
26567
27217
  }
26568
27218
  }
26569
27219
  function sleep(ms) {
26570
- return new Promise((resolve13) => setTimeout(resolve13, ms));
27220
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
26571
27221
  }
26572
27222
 
26573
27223
  // ../core/dist/auth/container.js
@@ -26699,7 +27349,7 @@ function resolveAuthServicePath() {
26699
27349
  return path3.join(pkgsDir, "auth-service");
26700
27350
  }
26701
27351
  function sleep2(ms) {
26702
- return new Promise((resolve13) => setTimeout(resolve13, ms));
27352
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
26703
27353
  }
26704
27354
 
26705
27355
  // ../core/dist/auth/preflight.js
@@ -27068,6 +27718,9 @@ var WorldRegistry = class {
27068
27718
  }
27069
27719
  }
27070
27720
  register(world) {
27721
+ if (world.id === "_planning") {
27722
+ throw new Error("world.id '_planning' is reserved for in-flight planning sessions; see packages/chunks/src/schema.ts PLANNING_WORLD_ID");
27723
+ }
27071
27724
  this.db.prepare(`INSERT INTO worlds
27072
27725
  (id, name, status, repos, branch, port_offset, workspace_path,
27073
27726
  compute_provider, total_cost_usd, thought_count, created_at, updated_at,
@@ -27391,12 +28044,12 @@ function register3(server, _ctx, _initError) {
27391
28044
  registry2.close();
27392
28045
  }
27393
28046
  try {
27394
- const { default: fs46 } = await import("node:fs");
28047
+ const { default: fs48 } = await import("node:fs");
27395
28048
  const { default: os28 } = await import("node:os");
27396
- const { default: path46 } = await import("node:path");
27397
- const tokenPath = path46.join(os28.homedir(), ".olam", "host-cp.token");
27398
- if (fs46.existsSync(tokenPath)) {
27399
- const token = fs46.readFileSync(tokenPath, "utf-8").trim();
28049
+ const { default: path48 } = await import("node:path");
28050
+ const tokenPath = path48.join(os28.homedir(), ".olam", "host-cp.token");
28051
+ if (fs48.existsSync(tokenPath)) {
28052
+ const token = fs48.readFileSync(tokenPath, "utf-8").trim();
27400
28053
  await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
27401
28054
  method: "POST",
27402
28055
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
@@ -27816,10 +28469,10 @@ function extractMcpConfig(claudeJsonPath) {
27816
28469
  }
27817
28470
  return { mcpServers, secrets };
27818
28471
  }
27819
- function readOptional(path46) {
27820
- if (!existsSync6(path46)) return null;
28472
+ function readOptional(path48) {
28473
+ if (!existsSync6(path48)) return null;
27821
28474
  try {
27822
- return readFileSync5(path46, "utf8");
28475
+ return readFileSync5(path48, "utf8");
27823
28476
  } catch {
27824
28477
  return null;
27825
28478
  }
@@ -27944,7 +28597,7 @@ var realDocker = {
27944
28597
  }
27945
28598
  };
27946
28599
  function spawnAsync(cmd, args, opts = {}) {
27947
- return new Promise((resolve13) => {
28600
+ return new Promise((resolve14) => {
27948
28601
  const child = spawn(cmd, [...args], {
27949
28602
  stdio: ["ignore", "pipe", "pipe"],
27950
28603
  signal: opts.signal
@@ -27958,10 +28611,10 @@ function spawnAsync(cmd, args, opts = {}) {
27958
28611
  stderr += chunk.toString();
27959
28612
  });
27960
28613
  child.on("error", (err) => {
27961
- resolve13({ exitCode: -1, stdout, stderr: stderr + err.message });
28614
+ resolve14({ exitCode: -1, stdout, stderr: stderr + err.message });
27962
28615
  });
27963
28616
  child.on("close", (code) => {
27964
- resolve13({ exitCode: code ?? -1, stdout, stderr });
28617
+ resolve14({ exitCode: code ?? -1, stdout, stderr });
27965
28618
  });
27966
28619
  });
27967
28620
  }
@@ -28412,7 +29065,7 @@ var stopAndRemove = async (container) => {
28412
29065
 
28413
29066
  // ../adapters/dist/docker/exec.js
28414
29067
  import { PassThrough } from "node:stream";
28415
- var demuxStream = (stream) => new Promise((resolve13, reject2) => {
29068
+ var demuxStream = (stream) => new Promise((resolve14, reject2) => {
28416
29069
  const stdoutChunks = [];
28417
29070
  const stderrChunks = [];
28418
29071
  const stdout = new PassThrough();
@@ -28426,7 +29079,7 @@ var demuxStream = (stream) => new Promise((resolve13, reject2) => {
28426
29079
  stream.pipe(stdout);
28427
29080
  }
28428
29081
  stream.on("end", () => {
28429
- resolve13({
29082
+ resolve14({
28430
29083
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
28431
29084
  stderr: Buffer.concat(stderrChunks).toString("utf-8")
28432
29085
  });
@@ -28799,7 +29452,7 @@ var SSHConnectionPool = class {
28799
29452
  // -----------------------------------------------------------------------
28800
29453
  async exec(host, command) {
28801
29454
  const client = await this.getConnection(host);
28802
- return new Promise((resolve13, reject2) => {
29455
+ return new Promise((resolve14, reject2) => {
28803
29456
  client.exec(command, (err, stream) => {
28804
29457
  if (err) {
28805
29458
  reject2(new Error(`SSH exec failed on ${host}: ${err.message}`));
@@ -28814,7 +29467,7 @@ var SSHConnectionPool = class {
28814
29467
  stderr += data.toString();
28815
29468
  });
28816
29469
  stream.on("close", (code) => {
28817
- resolve13({
29470
+ resolve14({
28818
29471
  exitCode: code ?? 0,
28819
29472
  stdout: stdout.trimEnd(),
28820
29473
  stderr: stderr.trimEnd()
@@ -28845,10 +29498,10 @@ var SSHConnectionPool = class {
28845
29498
  throw new Error(`No SSH configuration found for host: ${host}`);
28846
29499
  }
28847
29500
  const client = new SSHClient();
28848
- return new Promise((resolve13, reject2) => {
29501
+ return new Promise((resolve14, reject2) => {
28849
29502
  client.on("ready", () => {
28850
29503
  this.connections.set(host, client);
28851
- resolve13(client);
29504
+ resolve14(client);
28852
29505
  }).on("error", (err) => {
28853
29506
  this.connections.delete(host);
28854
29507
  reject2(new Error(`SSH connection to ${host} failed: ${err.message}`));
@@ -29265,8 +29918,8 @@ var CloudflareProvider = class extends ComputeProvider {
29265
29918
  // -----------------------------------------------------------------------
29266
29919
  // Internal fetch helper
29267
29920
  // -----------------------------------------------------------------------
29268
- async request(path46, method, body) {
29269
- const url2 = `${this.config.workerUrl}${path46}`;
29921
+ async request(path48, method, body) {
29922
+ const url2 = `${this.config.workerUrl}${path48}`;
29270
29923
  const bearer = await this.config.mintToken();
29271
29924
  const headers = {
29272
29925
  Authorization: `Bearer ${bearer}`
@@ -29828,7 +30481,7 @@ function register6(server, ctx, initError) {
29828
30481
  }
29829
30482
  } catch {
29830
30483
  }
29831
- await new Promise((resolve13) => setTimeout(resolve13, POLL_INTERVAL_MS));
30484
+ await new Promise((resolve14) => setTimeout(resolve14, POLL_INTERVAL_MS));
29832
30485
  }
29833
30486
  }
29834
30487
  if (authenticated) {
@@ -30764,8 +31417,8 @@ function copyMatchingFiles(sourcePath, destPath, pattern) {
30764
31417
  try {
30765
31418
  const matches2 = globSync(fullPattern);
30766
31419
  for (const match of matches2) {
30767
- const relative3 = path10.relative(sourcePath, match);
30768
- const dest = path10.join(destPath, relative3);
31420
+ const relative5 = path10.relative(sourcePath, match);
31421
+ const dest = path10.join(destPath, relative5);
30769
31422
  fs8.mkdirSync(path10.dirname(dest), { recursive: true });
30770
31423
  fs8.copyFileSync(match, dest);
30771
31424
  }
@@ -31717,10 +32370,10 @@ async function writeManifest(args) {
31717
32370
  capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
31718
32371
  shots: entries
31719
32372
  };
31720
- const path46 = join13(args.outDir, "manifest.json");
31721
- await writeFile(path46, `${JSON.stringify(manifest, null, 2)}
32373
+ const path48 = join13(args.outDir, "manifest.json");
32374
+ await writeFile(path48, `${JSON.stringify(manifest, null, 2)}
31722
32375
  `, "utf8");
31723
- return { path: path46, manifest };
32376
+ return { path: path48, manifest };
31724
32377
  }
31725
32378
 
31726
32379
  // ../mcp-server/src/tools/_capture/proxy.ts
@@ -31974,9 +32627,9 @@ async function startProxy(opts) {
31974
32627
  const liveCompiled = verified.allowedPaths.map(compileGlob);
31975
32628
  const target = parseRequestTarget(req);
31976
32629
  if (!target) return httpReject(400, "invalid_target");
31977
- const path46 = target.pathname;
31978
- if (!liveCompiled.some((re) => re.test(path46))) {
31979
- return httpReject(403, "outside_allow_list", { path: path46 });
32630
+ const path48 = target.pathname;
32631
+ if (!liveCompiled.some((re) => re.test(path48))) {
32632
+ return httpReject(403, "outside_allow_list", { path: path48 });
31980
32633
  }
31981
32634
  const headerWorld = req.headers[WORLD_ASSERT_HEADER];
31982
32635
  const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
@@ -32080,15 +32733,15 @@ ${JSON.stringify({ error: reason })}`
32080
32733
  unlinkSync2(udsPath);
32081
32734
  } catch {
32082
32735
  }
32083
- await new Promise((resolve13, reject2) => {
32084
- server.listen(udsPath, () => resolve13());
32736
+ await new Promise((resolve14, reject2) => {
32737
+ server.listen(udsPath, () => resolve14());
32085
32738
  server.once("error", reject2);
32086
32739
  });
32087
32740
  chmodSync3(udsPath, 384);
32088
32741
  port2 = 0;
32089
32742
  } else {
32090
- await new Promise((resolve13, reject2) => {
32091
- server.listen(opts.port ?? 0, "127.0.0.1", () => resolve13());
32743
+ await new Promise((resolve14, reject2) => {
32744
+ server.listen(opts.port ?? 0, "127.0.0.1", () => resolve14());
32092
32745
  server.once("error", reject2);
32093
32746
  });
32094
32747
  const addr = server.address();
@@ -32104,10 +32757,10 @@ ${JSON.stringify({ error: reason })}`
32104
32757
  } catch {
32105
32758
  }
32106
32759
  await Promise.race([
32107
- new Promise((resolve13, reject2) => {
32108
- server.close((err) => err ? reject2(err) : resolve13());
32760
+ new Promise((resolve14, reject2) => {
32761
+ server.close((err) => err ? reject2(err) : resolve14());
32109
32762
  }),
32110
- new Promise((resolve13) => setTimeout(resolve13, 5e3))
32763
+ new Promise((resolve14) => setTimeout(resolve14, 5e3))
32111
32764
  ]);
32112
32765
  if (udsPath) {
32113
32766
  try {
@@ -32439,10 +33092,10 @@ async function acquireLaunchSlot() {
32439
33092
  _inFlightLaunches++;
32440
33093
  return releaseLaunchSlot;
32441
33094
  }
32442
- return new Promise((resolve13) => {
33095
+ return new Promise((resolve14) => {
32443
33096
  _launchQueue.push(() => {
32444
33097
  _inFlightLaunches++;
32445
- resolve13(releaseLaunchSlot);
33098
+ resolve14(releaseLaunchSlot);
32446
33099
  });
32447
33100
  });
32448
33101
  }
@@ -32458,8 +33111,8 @@ function resolveShootsRoot() {
32458
33111
  }
32459
33112
  function isUnderRoot(absPath, root) {
32460
33113
  if (absPath === root) return true;
32461
- const sep2 = root.endsWith("/") ? "" : "/";
32462
- return absPath.startsWith(root + sep2);
33114
+ const sep4 = root.endsWith("/") ? "" : "/";
33115
+ return absPath.startsWith(root + sep4);
32463
33116
  }
32464
33117
  function deriveAllowedPaths(shots) {
32465
33118
  const paths = /* @__PURE__ */ new Set();
@@ -32755,14 +33408,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
32755
33408
  await page.waitForTimeout(shot.afterLoadMs);
32756
33409
  }
32757
33410
  const ext = format === "jpeg" ? "jpg" : "png";
32758
- const path46 = join14(outDir, `${shot.name}.${ext}`);
33411
+ const path48 = join14(outDir, `${shot.name}.${ext}`);
32759
33412
  await page.screenshot({
32760
- path: path46,
33413
+ path: path48,
32761
33414
  type: format,
32762
33415
  ...format === "jpeg" ? { quality: jpegQuality } : {},
32763
33416
  fullPage: false
32764
33417
  });
32765
- return { name: shot.name, path: path46, urlRedacted: redactUrl(shot.url), viewport };
33418
+ return { name: shot.name, path: path48, urlRedacted: redactUrl(shot.url), viewport };
32766
33419
  } finally {
32767
33420
  await context.close();
32768
33421
  }
@@ -33206,12 +33859,12 @@ function openUrl(url2) {
33206
33859
  var HOST_CP_URL = "http://127.0.0.1:19000";
33207
33860
  async function readHostCpToken2() {
33208
33861
  try {
33209
- const { default: fs46 } = await import("node:fs");
33862
+ const { default: fs48 } = await import("node:fs");
33210
33863
  const { default: os28 } = await import("node:os");
33211
- const { default: path46 } = await import("node:path");
33212
- const tp = path46.join(os28.homedir(), ".olam", "host-cp.token");
33213
- if (!fs46.existsSync(tp)) return { token: null };
33214
- return { token: fs46.readFileSync(tp, "utf-8").trim() };
33864
+ const { default: path48 } = await import("node:path");
33865
+ const tp = path48.join(os28.homedir(), ".olam", "host-cp.token");
33866
+ if (!fs48.existsSync(tp)) return { token: null };
33867
+ return { token: fs48.readFileSync(tp, "utf-8").trim() };
33215
33868
  } catch {
33216
33869
  return { token: null };
33217
33870
  }
@@ -33471,9 +34124,9 @@ function register22(server, _ctx, _initError) {
33471
34124
  description: external_exports.string().optional().describe("Optional human-readable description."),
33472
34125
  defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
33473
34126
  },
33474
- async ({ name, path: path46, description, defaultBranch }) => {
34127
+ async ({ name, path: path48, description, defaultBranch }) => {
33475
34128
  try {
33476
- const entry = addRepo({ name, path: path46, description, defaultBranch });
34129
+ const entry = addRepo({ name, path: path48, description, defaultBranch });
33477
34130
  return {
33478
34131
  content: [{
33479
34132
  type: "text",
@@ -33514,9 +34167,9 @@ function register22(server, _ctx, _initError) {
33514
34167
  description: external_exports.string().optional().describe("New description."),
33515
34168
  defaultBranch: external_exports.string().optional().describe("New default branch.")
33516
34169
  },
33517
- async ({ name, path: path46, description, defaultBranch }) => {
34170
+ async ({ name, path: path48, description, defaultBranch }) => {
33518
34171
  try {
33519
- const entry = updateRepo(name, { path: path46, description, defaultBranch });
34172
+ const entry = updateRepo(name, { path: path48, description, defaultBranch });
33520
34173
  return {
33521
34174
  content: [{
33522
34175
  type: "text",
@@ -33537,15 +34190,15 @@ __export(process_port_exports, {
33537
34190
  resolveHostCpToken: () => resolveHostCpToken
33538
34191
  });
33539
34192
  init_v3();
33540
- import fs31 from "node:fs";
34193
+ import fs33 from "node:fs";
33541
34194
  import os20 from "node:os";
33542
- import path30 from "node:path";
34195
+ import path32 from "node:path";
33543
34196
  var HOST_CP_BASE = "http://127.0.0.1:19000";
33544
34197
  function resolveHostCpToken() {
33545
34198
  const envToken = process.env["OLAM_HOST_CP_TOKEN"];
33546
34199
  if (envToken) return envToken;
33547
- const tokenPath = path30.join(os20.homedir(), ".olam", "host-cp.token");
33548
- if (fs31.existsSync(tokenPath)) return fs31.readFileSync(tokenPath, "utf-8").trim();
34200
+ const tokenPath = path32.join(os20.homedir(), ".olam", "host-cp.token");
34201
+ if (fs33.existsSync(tokenPath)) return fs33.readFileSync(tokenPath, "utf-8").trim();
33549
34202
  return null;
33550
34203
  }
33551
34204
  function tokenMissingError() {
@@ -33977,8 +34630,8 @@ __export(skills_exports, {
33977
34630
  });
33978
34631
  init_v3();
33979
34632
  init_skill_sources();
33980
- import * as fs32 from "node:fs";
33981
- import * as path31 from "node:path";
34633
+ import * as fs34 from "node:fs";
34634
+ import * as path33 from "node:path";
33982
34635
  function asMessage8(err) {
33983
34636
  return err instanceof Error ? err.message : String(err);
33984
34637
  }
@@ -34001,14 +34654,14 @@ function listDeployed() {
34001
34654
  );
34002
34655
  const entries = [];
34003
34656
  for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
34004
- const bucketDir = path31.join(dir, bucket);
34005
- if (!fs32.existsSync(bucketDir)) continue;
34006
- for (const name of fs32.readdirSync(bucketDir)) {
34007
- const full = path31.join(bucketDir, name);
34657
+ const bucketDir = path33.join(dir, bucket);
34658
+ if (!fs34.existsSync(bucketDir)) continue;
34659
+ for (const name of fs34.readdirSync(bucketDir)) {
34660
+ const full = path33.join(bucketDir, name);
34008
34661
  try {
34009
- const stat = fs32.lstatSync(full);
34662
+ const stat = fs34.lstatSync(full);
34010
34663
  if (!stat.isSymbolicLink()) continue;
34011
- const target = fs32.readlinkSync(full);
34664
+ const target = fs34.readlinkSync(full);
34012
34665
  let sourceId;
34013
34666
  for (const [clonePath, id] of sourcePaths.entries()) {
34014
34667
  if (target.startsWith(clonePath)) {
@@ -34104,8 +34757,8 @@ function port() {
34104
34757
  const n = Number.parseInt(env, 10);
34105
34758
  return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
34106
34759
  }
34107
- function url(path46) {
34108
- return `http://127.0.0.1:${port()}${path46}`;
34760
+ function url(path48) {
34761
+ return `http://127.0.0.1:${port()}${path48}`;
34109
34762
  }
34110
34763
  function kgServiceHealthUrl() {
34111
34764
  return url("/health");
@@ -34304,8 +34957,8 @@ __export(kg_install_hook_exports, {
34304
34957
  });
34305
34958
  init_v3();
34306
34959
  init_merge_settings();
34307
- import * as fs33 from "node:fs";
34308
- import * as path32 from "node:path";
34960
+ import * as fs35 from "node:fs";
34961
+ import * as path34 from "node:path";
34309
34962
  import * as os21 from "node:os";
34310
34963
 
34311
34964
  // ../core/dist/kg/hook-template.js
@@ -34356,10 +35009,10 @@ function buildHookMatcherEntry(opts) {
34356
35009
  // ../mcp-server/src/tools/kg-install-hook.ts
34357
35010
  function settingsPathFor2(scope, projectPath) {
34358
35011
  if (scope === "user") {
34359
- return path32.join(os21.homedir(), ".claude", "settings.json");
35012
+ return path34.join(os21.homedir(), ".claude", "settings.json");
34360
35013
  }
34361
35014
  const root = projectPath ?? process.cwd();
34362
- return path32.join(root, ".claude", "settings.json");
35015
+ return path34.join(root, ".claude", "settings.json");
34363
35016
  }
34364
35017
  function register29(server, _ctx, _initError) {
34365
35018
  server.tool(
@@ -34373,12 +35026,12 @@ function register29(server, _ctx, _initError) {
34373
35026
  const scope = params.scope === "user" ? "user" : "project";
34374
35027
  const filePath = settingsPathFor2(scope, params.projectPath);
34375
35028
  try {
34376
- fs33.mkdirSync(path32.dirname(filePath), { recursive: true });
35029
+ fs35.mkdirSync(path34.dirname(filePath), { recursive: true });
34377
35030
  let backupPath = null;
34378
- if (fs33.existsSync(filePath)) {
35031
+ if (fs35.existsSync(filePath)) {
34379
35032
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
34380
35033
  backupPath = `${filePath}.olam-bak.${ts}`;
34381
- fs33.copyFileSync(filePath, backupPath);
35034
+ fs35.copyFileSync(filePath, backupPath);
34382
35035
  }
34383
35036
  const result = mergeHomeSettingsJson(filePath, {
34384
35037
  ensureHook: {
@@ -34389,7 +35042,7 @@ function register29(server, _ctx, _initError) {
34389
35042
  });
34390
35043
  if (result.status === "already-present" && backupPath) {
34391
35044
  try {
34392
- fs33.unlinkSync(backupPath);
35045
+ fs35.unlinkSync(backupPath);
34393
35046
  } catch {
34394
35047
  }
34395
35048
  }
@@ -34433,15 +35086,15 @@ __export(kg_uninstall_hook_exports, {
34433
35086
  register: () => register30
34434
35087
  });
34435
35088
  init_v3();
34436
- import * as fs34 from "node:fs";
34437
- import * as path33 from "node:path";
35089
+ import * as fs36 from "node:fs";
35090
+ import * as path35 from "node:path";
34438
35091
  import * as os22 from "node:os";
34439
35092
  function settingsPathFor3(scope, projectPath) {
34440
35093
  if (scope === "user") {
34441
- return path33.join(os22.homedir(), ".claude", "settings.json");
35094
+ return path35.join(os22.homedir(), ".claude", "settings.json");
34442
35095
  }
34443
35096
  const root = projectPath ?? process.cwd();
34444
- return path33.join(root, ".claude", "settings.json");
35097
+ return path35.join(root, ".claude", "settings.json");
34445
35098
  }
34446
35099
  function dropSentinel(matchers) {
34447
35100
  let changed = false;
@@ -34475,7 +35128,7 @@ function register30(server, _ctx, _initError) {
34475
35128
  const scope = params.scope === "user" ? "user" : "project";
34476
35129
  const filePath = settingsPathFor3(scope, params.projectPath);
34477
35130
  try {
34478
- if (!fs34.existsSync(filePath)) {
35131
+ if (!fs36.existsSync(filePath)) {
34479
35132
  return {
34480
35133
  content: [
34481
35134
  {
@@ -34489,7 +35142,7 @@ function register30(server, _ctx, _initError) {
34489
35142
  ]
34490
35143
  };
34491
35144
  }
34492
- const raw = fs34.readFileSync(filePath, "utf-8");
35145
+ const raw = fs36.readFileSync(filePath, "utf-8");
34493
35146
  const settings = raw.trim() ? JSON.parse(raw) : {};
34494
35147
  const preToolUse = settings.hooks?.PreToolUse;
34495
35148
  if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
@@ -34524,7 +35177,7 @@ function register30(server, _ctx, _initError) {
34524
35177
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
34525
35178
  const backupPath = `${filePath}.olam-bak.${ts}`;
34526
35179
  try {
34527
- fs34.copyFileSync(filePath, backupPath);
35180
+ fs36.copyFileSync(filePath, backupPath);
34528
35181
  } catch {
34529
35182
  }
34530
35183
  const next = {
@@ -34536,7 +35189,7 @@ function register30(server, _ctx, _initError) {
34536
35189
  if (otherStages.length === 0) delete next.hooks;
34537
35190
  else delete next.hooks.PreToolUse;
34538
35191
  }
34539
- fs34.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
35192
+ fs36.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
34540
35193
  return {
34541
35194
  content: [
34542
35195
  {
@@ -34751,9 +35404,9 @@ init_loader();
34751
35404
  // ../core/dist/world/manager.js
34752
35405
  import * as crypto8 from "node:crypto";
34753
35406
  import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
34754
- import * as fs43 from "node:fs";
35407
+ import * as fs45 from "node:fs";
34755
35408
  import * as os26 from "node:os";
34756
- import * as path43 from "node:path";
35409
+ import * as path45 from "node:path";
34757
35410
 
34758
35411
  // ../core/dist/world/state.js
34759
35412
  var VALID_TRANSITIONS = {
@@ -34849,8 +35502,8 @@ function resolveDevboxImage(config2, tag) {
34849
35502
 
34850
35503
  // ../core/dist/world/worktree.js
34851
35504
  import { execFileSync as execFileSync4 } from "node:child_process";
34852
- import * as fs35 from "node:fs";
34853
- import * as path34 from "node:path";
35505
+ import * as fs37 from "node:fs";
35506
+ import * as path36 from "node:path";
34854
35507
  function resolveGitDir(repo) {
34855
35508
  if (repo.path) {
34856
35509
  return repo.path;
@@ -34860,11 +35513,11 @@ function resolveGitDir(repo) {
34860
35513
  async function createWorktrees(repos, worldId, workspacePath, branch) {
34861
35514
  const created = [];
34862
35515
  for (const repo of repos) {
34863
- const worktreePath = path34.join(workspacePath, repo.name);
35516
+ const worktreePath = path36.join(workspacePath, repo.name);
34864
35517
  const gitDir = resolveGitDir(repo);
34865
35518
  const branchName = branch || `olam/${worldId}`;
34866
35519
  try {
34867
- fs35.mkdirSync(path34.dirname(worktreePath), { recursive: true });
35520
+ fs37.mkdirSync(path36.dirname(worktreePath), { recursive: true });
34868
35521
  execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
34869
35522
  cwd: gitDir,
34870
35523
  stdio: "pipe"
@@ -34897,7 +35550,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
34897
35550
  }
34898
35551
  async function removeWorktrees(repos, workspacePath) {
34899
35552
  for (const repo of repos) {
34900
- const worktreePath = path34.join(workspacePath, repo.name);
35553
+ const worktreePath = path36.join(workspacePath, repo.name);
34901
35554
  let gitDir;
34902
35555
  try {
34903
35556
  gitDir = resolveGitDir(repo);
@@ -34972,12 +35625,12 @@ function removeBranch(repo, branch) {
34972
35625
 
34973
35626
  // ../core/dist/world/kg-overlay.js
34974
35627
  import { execFileSync as execFileSync5 } from "node:child_process";
34975
- import * as fs36 from "node:fs";
34976
- import * as path35 from "node:path";
35628
+ import * as fs38 from "node:fs";
35629
+ import * as path37 from "node:path";
34977
35630
 
34978
35631
  // ../core/dist/kg/storage-paths.js
34979
35632
  import { homedir as homedir22 } from "node:os";
34980
- import { join as join35, resolve as resolve8 } from "node:path";
35633
+ import { join as join37, resolve as resolve9 } from "node:path";
34981
35634
 
34982
35635
  // ../core/dist/world/workspace-name.js
34983
35636
  var InvalidWorkspaceNameError = class extends Error {
@@ -34998,25 +35651,25 @@ function validateWorkspaceName(name) {
34998
35651
 
34999
35652
  // ../core/dist/kg/storage-paths.js
35000
35653
  function olamHome() {
35001
- return process.env.OLAM_HOME ?? join35(homedir22(), ".olam");
35654
+ return process.env.OLAM_HOME ?? join37(homedir22(), ".olam");
35002
35655
  }
35003
35656
  function kgRoot() {
35004
- return join35(olamHome(), "kg");
35657
+ return join37(olamHome(), "kg");
35005
35658
  }
35006
35659
  function worldsRoot() {
35007
- return join35(olamHome(), "worlds");
35660
+ return join37(olamHome(), "worlds");
35008
35661
  }
35009
- function assertWithinPrefix(path46, prefix, label) {
35010
- if (!path46.startsWith(prefix + "/")) {
35011
- throw new Error(`${label} escape: ${path46} not under ${prefix}/`);
35662
+ function assertWithinPrefix(path48, prefix, label) {
35663
+ if (!path48.startsWith(prefix + "/")) {
35664
+ throw new Error(`${label} escape: ${path48} not under ${prefix}/`);
35012
35665
  }
35013
35666
  }
35014
35667
  function kgPristinePath(workspace) {
35015
35668
  validateWorkspaceName(workspace);
35016
35669
  const root = kgRoot();
35017
- const path46 = resolve8(join35(root, workspace));
35018
- assertWithinPrefix(path46, root, "kgPristinePath");
35019
- return path46;
35670
+ const path48 = resolve9(join37(root, workspace));
35671
+ assertWithinPrefix(path48, root, "kgPristinePath");
35672
+ return path48;
35020
35673
  }
35021
35674
  var KG_PATHS_INTERNALS = Object.freeze({
35022
35675
  olamHome,
@@ -35032,10 +35685,10 @@ var KgOverlayError = class extends Error {
35032
35685
  }
35033
35686
  };
35034
35687
  function ensureGitignoreEntry(worldClonePath) {
35035
- const gitignorePath = path35.join(worldClonePath, ".gitignore");
35036
- if (!fs36.existsSync(gitignorePath))
35688
+ const gitignorePath = path37.join(worldClonePath, ".gitignore");
35689
+ if (!fs38.existsSync(gitignorePath))
35037
35690
  return "no-gitignore";
35038
- const content = fs36.readFileSync(gitignorePath, "utf-8");
35691
+ const content = fs38.readFileSync(gitignorePath, "utf-8");
35039
35692
  const lines = content.split("\n").map((l) => l.trim());
35040
35693
  const recognised = /* @__PURE__ */ new Set([
35041
35694
  "graphify-out",
@@ -35050,24 +35703,24 @@ function ensureGitignoreEntry(worldClonePath) {
35050
35703
  const eol = content.includes("\r\n") ? "\r\n" : "\n";
35051
35704
  const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
35052
35705
  const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
35053
- fs36.appendFileSync(gitignorePath, block, "utf-8");
35706
+ fs38.appendFileSync(gitignorePath, block, "utf-8");
35054
35707
  return "appended";
35055
35708
  }
35056
35709
  function createWorldOverlay(opts) {
35057
35710
  const pristineRoot = kgPristinePath(opts.workspace);
35058
- const pristinePath = path35.join(pristineRoot, "graphify-out");
35059
- if (!fs36.existsSync(pristinePath)) {
35711
+ const pristinePath = path37.join(pristineRoot, "graphify-out");
35712
+ if (!fs38.existsSync(pristinePath)) {
35060
35713
  throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
35061
35714
  }
35062
- if (!path35.isAbsolute(opts.worldClonePath)) {
35715
+ if (!path37.isAbsolute(opts.worldClonePath)) {
35063
35716
  throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
35064
35717
  }
35065
- if (!fs36.existsSync(opts.worldClonePath)) {
35718
+ if (!fs38.existsSync(opts.worldClonePath)) {
35066
35719
  throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
35067
35720
  }
35068
- const overlayPath = path35.join(opts.worldClonePath, "graphify-out");
35069
- if (fs36.existsSync(overlayPath)) {
35070
- fs36.rmSync(overlayPath, { recursive: true, force: true });
35721
+ const overlayPath = path37.join(opts.worldClonePath, "graphify-out");
35722
+ if (fs38.existsSync(overlayPath)) {
35723
+ fs38.rmSync(overlayPath, { recursive: true, force: true });
35071
35724
  }
35072
35725
  const useReflink = process.platform === "darwin";
35073
35726
  let strategy;
@@ -35085,7 +35738,7 @@ function createWorldOverlay(opts) {
35085
35738
  } else {
35086
35739
  strategy = "cp-r";
35087
35740
  }
35088
- if (strategy === "cp-r" || !fs36.existsSync(overlayPath)) {
35741
+ if (strategy === "cp-r" || !fs38.existsSync(overlayPath)) {
35089
35742
  try {
35090
35743
  execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
35091
35744
  stdio: ["ignore", "ignore", "pipe"]
@@ -35097,7 +35750,7 @@ function createWorldOverlay(opts) {
35097
35750
  throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
35098
35751
  }
35099
35752
  }
35100
- if (!fs36.existsSync(overlayPath)) {
35753
+ if (!fs38.existsSync(overlayPath)) {
35101
35754
  throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
35102
35755
  }
35103
35756
  const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
@@ -35111,9 +35764,9 @@ function createWorldOverlay(opts) {
35111
35764
 
35112
35765
  // ../core/dist/world/baseline-diff.js
35113
35766
  import { execFileSync as execFileSync6 } from "node:child_process";
35114
- import * as fs37 from "node:fs";
35767
+ import * as fs39 from "node:fs";
35115
35768
  import * as os23 from "node:os";
35116
- import * as path36 from "node:path";
35769
+ import * as path38 from "node:path";
35117
35770
  var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
35118
35771
  function expandHome2(p, homedir28) {
35119
35772
  return p.replace(/^~(?=$|\/|\\)/, homedir28());
@@ -35140,9 +35793,9 @@ ${stderr}`;
35140
35793
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
35141
35794
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
35142
35795
  const homedir28 = deps.homedir ?? (() => os23.homedir());
35143
- const baselineDir = path36.join(workspacePath, ".olam", "baseline");
35796
+ const baselineDir = path38.join(workspacePath, ".olam", "baseline");
35144
35797
  try {
35145
- fs37.mkdirSync(baselineDir, { recursive: true });
35798
+ fs39.mkdirSync(baselineDir, { recursive: true });
35146
35799
  } catch (err) {
35147
35800
  const msg = err instanceof Error ? err.message : String(err);
35148
35801
  console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
@@ -35154,9 +35807,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
35154
35807
  if (!repo.path)
35155
35808
  continue;
35156
35809
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
35157
- const outPath = path36.join(baselineDir, filename);
35810
+ const outPath = path38.join(baselineDir, filename);
35158
35811
  const repoPath = expandHome2(repo.path, homedir28);
35159
- if (!fs37.existsSync(repoPath)) {
35812
+ if (!fs39.existsSync(repoPath)) {
35160
35813
  writeBaselineFile(outPath, `# repo: ${repo.name}
35161
35814
  # (skipped: path ${repoPath} does not exist)
35162
35815
  `);
@@ -35223,7 +35876,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
35223
35876
  }
35224
35877
  function writeBaselineFile(outPath, content) {
35225
35878
  try {
35226
- fs37.writeFileSync(outPath, content);
35879
+ fs39.writeFileSync(outPath, content);
35227
35880
  } catch (err) {
35228
35881
  const msg = err instanceof Error ? err.message : String(err);
35229
35882
  console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
@@ -35231,8 +35884,8 @@ function writeBaselineFile(outPath, content) {
35231
35884
  }
35232
35885
  function stripWorktreeEdits(repos, workspacePath) {
35233
35886
  for (const repo of repos) {
35234
- const worktreePath = path36.join(workspacePath, repo.name);
35235
- if (!fs37.existsSync(worktreePath))
35887
+ const worktreePath = path38.join(workspacePath, repo.name);
35888
+ if (!fs39.existsSync(worktreePath))
35236
35889
  continue;
35237
35890
  try {
35238
35891
  execFileSync6("git", ["checkout", "--", "."], {
@@ -35292,20 +35945,20 @@ function extractStderr(err) {
35292
35945
  function carryUncommittedEdits(repos, workspacePath, deps = {}) {
35293
35946
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
35294
35947
  const homedir28 = deps.homedir ?? (() => os23.homedir());
35295
- const existsSync43 = deps.existsSync ?? ((p) => fs37.existsSync(p));
35296
- const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs37.copyFileSync(src, dest));
35297
- const mkdirSync28 = deps.mkdirSync ?? ((dirPath, opts) => {
35298
- fs37.mkdirSync(dirPath, opts);
35948
+ const existsSync46 = deps.existsSync ?? ((p) => fs39.existsSync(p));
35949
+ const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs39.copyFileSync(src, dest));
35950
+ const mkdirSync29 = deps.mkdirSync ?? ((dirPath, opts) => {
35951
+ fs39.mkdirSync(dirPath, opts);
35299
35952
  });
35300
35953
  const plans = [];
35301
35954
  for (const repo of repos) {
35302
35955
  if (!repo.path)
35303
35956
  continue;
35304
35957
  const repoPath = expandHome2(repo.path, homedir28);
35305
- const worktreePath = path36.join(workspacePath, repo.name);
35306
- if (!existsSync43(repoPath))
35958
+ const worktreePath = path38.join(workspacePath, repo.name);
35959
+ if (!existsSync46(repoPath))
35307
35960
  continue;
35308
- if (!existsSync43(worktreePath)) {
35961
+ if (!existsSync46(worktreePath)) {
35309
35962
  console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
35310
35963
  continue;
35311
35964
  }
@@ -35363,12 +36016,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
35363
36016
  }
35364
36017
  }
35365
36018
  for (const rel of plan.diff.untracked) {
35366
- const src = path36.join(plan.repoPath, rel);
35367
- const dest = path36.join(plan.worktreePath, rel);
35368
- if (!existsSync43(src))
36019
+ const src = path38.join(plan.repoPath, rel);
36020
+ const dest = path38.join(plan.worktreePath, rel);
36021
+ if (!existsSync46(src))
35369
36022
  continue;
35370
36023
  try {
35371
- mkdirSync28(path36.dirname(dest), { recursive: true });
36024
+ mkdirSync29(path38.dirname(dest), { recursive: true });
35372
36025
  copyFileSync9(src, dest);
35373
36026
  } catch (err) {
35374
36027
  const msg = err instanceof Error ? err.message : String(err);
@@ -35394,8 +36047,8 @@ function formatBaselineSummary(result) {
35394
36047
  }
35395
36048
 
35396
36049
  // ../core/dist/world/context-injection.js
35397
- import * as fs38 from "node:fs";
35398
- import * as path37 from "node:path";
36050
+ import * as fs40 from "node:fs";
36051
+ import * as path39 from "node:path";
35399
36052
 
35400
36053
  // ../core/dist/world/templates/_generated.js
35401
36054
  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';
@@ -35405,10 +36058,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
35405
36058
  // ../core/dist/world/context-injection.js
35406
36059
  function injectWorldContext(opts) {
35407
36060
  const { world } = opts;
35408
- const claudeDir2 = path37.join(world.workspacePath, ".claude");
35409
- fs38.mkdirSync(claudeDir2, { recursive: true });
36061
+ const claudeDir2 = path39.join(world.workspacePath, ".claude");
36062
+ fs40.mkdirSync(claudeDir2, { recursive: true });
35410
36063
  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));
35411
- fs38.writeFileSync(path37.join(claudeDir2, "CLAUDE.md"), content);
36064
+ fs40.writeFileSync(path39.join(claudeDir2, "CLAUDE.md"), content);
35412
36065
  writeOlamDocs(world.workspacePath);
35413
36066
  }
35414
36067
  function buildTaskBlock(opts) {
@@ -35482,10 +36135,10 @@ function buildExtraContextBlock(extra) {
35482
36135
  ${extra}`;
35483
36136
  }
35484
36137
  function writeOlamDocs(workspacePath) {
35485
- const docsDir = path37.join(workspacePath, ".olam", "docs");
35486
- fs38.mkdirSync(docsDir, { recursive: true });
35487
- fs38.writeFileSync(path37.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
35488
- fs38.writeFileSync(path37.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
36138
+ const docsDir = path39.join(workspacePath, ".olam", "docs");
36139
+ fs40.mkdirSync(docsDir, { recursive: true });
36140
+ fs40.writeFileSync(path39.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
36141
+ fs40.writeFileSync(path39.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
35489
36142
  }
35490
36143
  function formatTaskSource(ctx) {
35491
36144
  if (ctx.source === "linear" && ctx.ticketId) {
@@ -35499,9 +36152,9 @@ function formatTaskSource(ctx) {
35499
36152
  function hasPlanFile(world) {
35500
36153
  if (world.repos.length === 0)
35501
36154
  return false;
35502
- const plansDir = path37.join(world.workspacePath, world.repos[0], "docs", "plans");
36155
+ const plansDir = path39.join(world.workspacePath, world.repos[0], "docs", "plans");
35503
36156
  try {
35504
- return fs38.existsSync(plansDir) && fs38.readdirSync(plansDir).length > 0;
36157
+ return fs40.existsSync(plansDir) && fs40.readdirSync(plansDir).length > 0;
35505
36158
  } catch {
35506
36159
  return false;
35507
36160
  }
@@ -36073,25 +36726,25 @@ init_repo_manifest();
36073
36726
 
36074
36727
  // ../core/dist/world/snapshot.js
36075
36728
  import * as crypto7 from "node:crypto";
36076
- import * as fs39 from "node:fs";
36729
+ import * as fs41 from "node:fs";
36077
36730
  import * as os24 from "node:os";
36078
- import * as path38 from "node:path";
36731
+ import * as path40 from "node:path";
36079
36732
  import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
36080
36733
  import { gunzipSync } from "node:zlib";
36081
36734
  function snapshotsDir() {
36082
- return process.env["OLAM_SNAPSHOTS_DIR"] ?? path38.join(os24.homedir(), ".olam", "snapshots");
36735
+ return process.env["OLAM_SNAPSHOTS_DIR"] ?? path40.join(os24.homedir(), ".olam", "snapshots");
36083
36736
  }
36084
36737
  function snapshotKindDirByWorkspace(workspace, arch, kind) {
36085
- return path38.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
36738
+ return path40.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
36086
36739
  }
36087
36740
  function cleanupLegacyByWorldDir(worldId) {
36088
- const legacyDir = path38.join(snapshotsDir(), worldId);
36741
+ const legacyDir = path40.join(snapshotsDir(), worldId);
36089
36742
  if (worldId === "by-workspace")
36090
36743
  return;
36091
- if (!fs39.existsSync(legacyDir))
36744
+ if (!fs41.existsSync(legacyDir))
36092
36745
  return;
36093
36746
  try {
36094
- fs39.rmSync(legacyDir, { recursive: true, force: true });
36747
+ fs41.rmSync(legacyDir, { recursive: true, force: true });
36095
36748
  } catch {
36096
36749
  }
36097
36750
  }
@@ -36110,11 +36763,11 @@ function hashBuffers(entries) {
36110
36763
  return hash.digest("hex").slice(0, 12);
36111
36764
  }
36112
36765
  function computeGemsFingerprint(repoDir, imageDigest) {
36113
- const lockfile = path38.join(repoDir, "Gemfile.lock");
36114
- if (!fs39.existsSync(lockfile))
36766
+ const lockfile = path40.join(repoDir, "Gemfile.lock");
36767
+ if (!fs41.existsSync(lockfile))
36115
36768
  return null;
36116
36769
  const entries = [
36117
- { path: "Gemfile.lock", content: fs39.readFileSync(lockfile) }
36770
+ { path: "Gemfile.lock", content: fs41.readFileSync(lockfile) }
36118
36771
  ];
36119
36772
  if (imageDigest) {
36120
36773
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -36124,10 +36777,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
36124
36777
  function computeNodeFingerprint(repoDir, imageDigest) {
36125
36778
  const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
36126
36779
  for (const name of candidates) {
36127
- const lockfile = path38.join(repoDir, name);
36128
- if (fs39.existsSync(lockfile)) {
36780
+ const lockfile = path40.join(repoDir, name);
36781
+ if (fs41.existsSync(lockfile)) {
36129
36782
  const entries = [
36130
- { path: name, content: fs39.readFileSync(lockfile) }
36783
+ { path: name, content: fs41.readFileSync(lockfile) }
36131
36784
  ];
36132
36785
  if (imageDigest) {
36133
36786
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -36146,18 +36799,18 @@ function unpackTarballAtomic(srcPath, destDir) {
36146
36799
  detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
36147
36800
  };
36148
36801
  }
36149
- const parent = path38.dirname(destDir);
36150
- fs39.mkdirSync(parent, { recursive: true });
36802
+ const parent = path40.dirname(destDir);
36803
+ fs41.mkdirSync(parent, { recursive: true });
36151
36804
  const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
36152
36805
  const tmpDir = `${destDir}${tmpSuffix}`;
36153
36806
  try {
36154
- fs39.mkdirSync(tmpDir, { recursive: true });
36807
+ fs41.mkdirSync(tmpDir, { recursive: true });
36155
36808
  execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
36156
- fs39.renameSync(tmpDir, destDir);
36809
+ fs41.renameSync(tmpDir, destDir);
36157
36810
  return { ok: true, entryCount: validation.entries.length };
36158
36811
  } catch (err) {
36159
36812
  try {
36160
- fs39.rmSync(tmpDir, { recursive: true, force: true });
36813
+ fs41.rmSync(tmpDir, { recursive: true, force: true });
36161
36814
  } catch {
36162
36815
  }
36163
36816
  return {
@@ -36168,12 +36821,12 @@ function unpackTarballAtomic(srcPath, destDir) {
36168
36821
  }
36169
36822
  }
36170
36823
  function resolvesWithin(base, target) {
36171
- const resolved = path38.resolve(base, target);
36172
- const baseResolved = path38.resolve(base);
36173
- const rel = path38.relative(baseResolved, resolved);
36824
+ const resolved = path40.resolve(base, target);
36825
+ const baseResolved = path40.resolve(base);
36826
+ const rel = path40.relative(baseResolved, resolved);
36174
36827
  if (rel === "")
36175
36828
  return true;
36176
- return !rel.startsWith("..") && !path38.isAbsolute(rel);
36829
+ return !rel.startsWith("..") && !path40.isAbsolute(rel);
36177
36830
  }
36178
36831
  var TYPE_CHAR_TO_TYPE = {
36179
36832
  "-": "file",
@@ -36223,7 +36876,7 @@ function parseTarListLine(line) {
36223
36876
  function validateHardlinksBinary(tarPath, targetDir) {
36224
36877
  let raw;
36225
36878
  try {
36226
- raw = gunzipSync(fs39.readFileSync(tarPath));
36879
+ raw = gunzipSync(fs41.readFileSync(tarPath));
36227
36880
  } catch {
36228
36881
  return null;
36229
36882
  }
@@ -36238,7 +36891,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
36238
36891
  const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
36239
36892
  const linkNull = block.indexOf(0, 157);
36240
36893
  const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
36241
- if (linkname && (path38.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
36894
+ if (linkname && (path40.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
36242
36895
  return {
36243
36896
  valid: false,
36244
36897
  reason: "hardlink-escape",
@@ -36276,7 +36929,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
36276
36929
  const entry = parseTarListLine(line);
36277
36930
  if (!entry)
36278
36931
  continue;
36279
- if (path38.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
36932
+ if (path40.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
36280
36933
  return {
36281
36934
  valid: false,
36282
36935
  reason: "path-traversal",
@@ -36284,8 +36937,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
36284
36937
  };
36285
36938
  }
36286
36939
  if (entry.type === "symlink" && entry.linkname !== void 0) {
36287
- const symlinkParent = path38.join(targetDir, path38.dirname(entry.name));
36288
- if (path38.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path38.join(path38.dirname(entry.name), entry.linkname))) {
36940
+ const symlinkParent = path40.join(targetDir, path40.dirname(entry.name));
36941
+ if (path40.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path40.join(path40.dirname(entry.name), entry.linkname))) {
36289
36942
  return {
36290
36943
  valid: false,
36291
36944
  reason: "symlink-escape",
@@ -36295,7 +36948,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
36295
36948
  }
36296
36949
  }
36297
36950
  if (entry.type === "hardlink" && entry.linkname !== void 0) {
36298
- if (path38.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
36951
+ if (path40.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
36299
36952
  return {
36300
36953
  valid: false,
36301
36954
  reason: "hardlink-escape",
@@ -36328,8 +36981,8 @@ function restoreSnapshotsForRepos(input) {
36328
36981
  }
36329
36982
  const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
36330
36983
  const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
36331
- const tarPath = path38.join(archDir, tarFilename);
36332
- if (!fs39.existsSync(tarPath)) {
36984
+ const tarPath = path40.join(archDir, tarFilename);
36985
+ if (!fs41.existsSync(tarPath)) {
36333
36986
  outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
36334
36987
  continue;
36335
36988
  }
@@ -36344,9 +36997,9 @@ function restoreSnapshotsForRepos(input) {
36344
36997
  });
36345
36998
  continue;
36346
36999
  }
36347
- const targetDir = path38.join(repo.worktreeDir, targetSubpath);
37000
+ const targetDir = path40.join(repo.worktreeDir, targetSubpath);
36348
37001
  try {
36349
- fs39.rmSync(targetDir, { recursive: true, force: true });
37002
+ fs41.rmSync(targetDir, { recursive: true, force: true });
36350
37003
  } catch {
36351
37004
  }
36352
37005
  const result = unpackTarballAtomic(tarPath, targetDir);
@@ -36359,8 +37012,8 @@ function restoreSnapshotsForRepos(input) {
36359
37012
  fingerprint
36360
37013
  });
36361
37014
  try {
36362
- fs39.rmSync(tarPath, { force: true });
36363
- fs39.rmSync(manifestPath(tarPath), { force: true });
37015
+ fs41.rmSync(tarPath, { force: true });
37016
+ fs41.rmSync(manifestPath(tarPath), { force: true });
36364
37017
  } catch {
36365
37018
  }
36366
37019
  continue;
@@ -36376,10 +37029,10 @@ function restoreSnapshotsForRepos(input) {
36376
37029
  }
36377
37030
  function readManifest(tarPath) {
36378
37031
  const mPath = manifestPath(tarPath);
36379
- if (!fs39.existsSync(mPath))
37032
+ if (!fs41.existsSync(mPath))
36380
37033
  return null;
36381
37034
  try {
36382
- return JSON.parse(fs39.readFileSync(mPath, "utf-8"));
37035
+ return JSON.parse(fs41.readFileSync(mPath, "utf-8"));
36383
37036
  } catch {
36384
37037
  return null;
36385
37038
  }
@@ -36394,17 +37047,17 @@ function isPidAlive(pid) {
36394
37047
  }
36395
37048
  }
36396
37049
  function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
36397
- fs39.mkdirSync(dir, { recursive: true });
36398
- const lockPath = path38.join(dir, EVICT_LOCK_FILENAME);
37050
+ fs41.mkdirSync(dir, { recursive: true });
37051
+ const lockPath = path40.join(dir, EVICT_LOCK_FILENAME);
36399
37052
  let fd;
36400
37053
  try {
36401
- fd = fs39.openSync(lockPath, fs39.constants.O_WRONLY | fs39.constants.O_CREAT | fs39.constants.O_EXCL, 384);
37054
+ fd = fs41.openSync(lockPath, fs41.constants.O_WRONLY | fs41.constants.O_CREAT | fs41.constants.O_EXCL, 384);
36402
37055
  } catch (err) {
36403
37056
  if (err.code !== "EEXIST")
36404
37057
  return 0;
36405
37058
  let holderPid = null;
36406
37059
  try {
36407
- holderPid = parseInt(fs39.readFileSync(lockPath, "utf-8").trim(), 10);
37060
+ holderPid = parseInt(fs41.readFileSync(lockPath, "utf-8").trim(), 10);
36408
37061
  } catch {
36409
37062
  holderPid = null;
36410
37063
  }
@@ -36412,23 +37065,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
36412
37065
  return 0;
36413
37066
  }
36414
37067
  try {
36415
- fs39.unlinkSync(lockPath);
36416
- fd = fs39.openSync(lockPath, fs39.constants.O_WRONLY | fs39.constants.O_CREAT | fs39.constants.O_EXCL, 384);
37068
+ fs41.unlinkSync(lockPath);
37069
+ fd = fs41.openSync(lockPath, fs41.constants.O_WRONLY | fs41.constants.O_CREAT | fs41.constants.O_EXCL, 384);
36417
37070
  } catch {
36418
37071
  return 0;
36419
37072
  }
36420
37073
  }
36421
37074
  try {
36422
- fs39.writeSync(fd, `${process.pid}
37075
+ fs41.writeSync(fd, `${process.pid}
36423
37076
  `);
36424
37077
  } finally {
36425
- fs39.closeSync(fd);
37078
+ fs41.closeSync(fd);
36426
37079
  }
36427
37080
  try {
36428
37081
  return evictOldSnapshots(maxBytes, dir);
36429
37082
  } finally {
36430
37083
  try {
36431
- fs39.unlinkSync(lockPath);
37084
+ fs41.unlinkSync(lockPath);
36432
37085
  } catch {
36433
37086
  }
36434
37087
  }
@@ -36461,16 +37114,16 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
36461
37114
  }
36462
37115
  }
36463
37116
  function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
36464
- if (!fs39.existsSync(dir))
37117
+ if (!fs41.existsSync(dir))
36465
37118
  return 0;
36466
37119
  const allTars = [];
36467
37120
  const walk = (d) => {
36468
- for (const entry of fs39.readdirSync(d, { withFileTypes: true })) {
36469
- const full = path38.join(d, entry.name);
37121
+ for (const entry of fs41.readdirSync(d, { withFileTypes: true })) {
37122
+ const full = path40.join(d, entry.name);
36470
37123
  if (entry.isDirectory()) {
36471
37124
  walk(full);
36472
37125
  } else if (entry.name.endsWith(".tar.gz")) {
36473
- const stat = fs39.statSync(full);
37126
+ const stat = fs41.statSync(full);
36474
37127
  allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
36475
37128
  }
36476
37129
  }
@@ -36485,8 +37138,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
36485
37138
  for (const tar of allTars) {
36486
37139
  if (remaining <= maxBytes)
36487
37140
  break;
36488
- fs39.rmSync(tar.path, { force: true });
36489
- fs39.rmSync(manifestPath(tar.path), { force: true });
37141
+ fs41.rmSync(tar.path, { force: true });
37142
+ fs41.rmSync(manifestPath(tar.path), { force: true });
36490
37143
  freed += tar.size;
36491
37144
  remaining -= tar.size;
36492
37145
  }
@@ -36603,14 +37256,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
36603
37256
 
36604
37257
  // ../core/dist/world/olam-yaml.js
36605
37258
  init_repo_manifest();
36606
- import * as path39 from "node:path";
37259
+ import * as path41 from "node:path";
36607
37260
  import YAML2 from "yaml";
36608
37261
  function enrichReposWithManifests(repos, workspacePath) {
36609
37262
  return repos.map((repo) => {
36610
37263
  if (repo.manifest !== void 0 && repo.manifest !== null) {
36611
37264
  return repo;
36612
37265
  }
36613
- const repoDir = path39.join(workspacePath, repo.name);
37266
+ const repoDir = path41.join(workspacePath, repo.name);
36614
37267
  let manifest = null;
36615
37268
  try {
36616
37269
  manifest = loadRepoManifest(repoDir);
@@ -36625,10 +37278,10 @@ function enrichReposWithManifests(repos, workspacePath) {
36625
37278
  }
36626
37279
 
36627
37280
  // ../core/dist/policies/loader.js
36628
- import * as fs40 from "node:fs";
36629
- import * as path40 from "node:path";
37281
+ import * as fs42 from "node:fs";
37282
+ import * as path42 from "node:path";
36630
37283
  import { parse as parseYaml4 } from "yaml";
36631
- function parseFrontmatter(content) {
37284
+ function parseFrontmatter2(content) {
36632
37285
  const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
36633
37286
  if (!match)
36634
37287
  return null;
@@ -36646,21 +37299,21 @@ function toStringArray(v) {
36646
37299
  return v.filter((x) => typeof x === "string");
36647
37300
  }
36648
37301
  function loadPolicies(workspaceRoot) {
36649
- const policiesDir = path40.join(workspaceRoot, ".olam", "policies");
36650
- if (!fs40.existsSync(policiesDir))
37302
+ const policiesDir = path42.join(workspaceRoot, ".olam", "policies");
37303
+ if (!fs42.existsSync(policiesDir))
36651
37304
  return [];
36652
37305
  let files;
36653
37306
  try {
36654
- files = fs40.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
37307
+ files = fs42.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
36655
37308
  } catch {
36656
37309
  return [];
36657
37310
  }
36658
37311
  const policies = [];
36659
37312
  for (const file of files) {
36660
- const filePath = path40.join(policiesDir, file);
37313
+ const filePath = path42.join(policiesDir, file);
36661
37314
  try {
36662
- const content = fs40.readFileSync(filePath, "utf8");
36663
- const parsed = parseFrontmatter(content);
37315
+ const content = fs42.readFileSync(filePath, "utf8");
37316
+ const parsed = parseFrontmatter2(content);
36664
37317
  if (!parsed) {
36665
37318
  console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
36666
37319
  continue;
@@ -36742,7 +37395,7 @@ var TaskDispatchError = class extends Error {
36742
37395
  this.name = "TaskDispatchError";
36743
37396
  }
36744
37397
  };
36745
- var DEFAULT_SLEEP = (ms) => new Promise((resolve13) => setTimeout(resolve13, ms));
37398
+ var DEFAULT_SLEEP = (ms) => new Promise((resolve14) => setTimeout(resolve14, ms));
36746
37399
  async function probeHealth(containerName, dockerExec, budgetMs, sleep5) {
36747
37400
  const deadline = Date.now() + budgetMs;
36748
37401
  const cadenceMs = 100;
@@ -36806,12 +37459,12 @@ init_store();
36806
37459
  init_bridge();
36807
37460
 
36808
37461
  // ../core/dist/global-config/runbook-resolver.js
36809
- import * as fs41 from "node:fs";
37462
+ import * as fs43 from "node:fs";
36810
37463
  import * as os25 from "node:os";
36811
- import * as path41 from "node:path";
37464
+ import * as path43 from "node:path";
36812
37465
  function expandTilde(p) {
36813
37466
  if (p === "~" || p.startsWith("~/")) {
36814
- return path41.join(os25.homedir(), p.slice(1));
37467
+ return path43.join(os25.homedir(), p.slice(1));
36815
37468
  }
36816
37469
  return p;
36817
37470
  }
@@ -36823,7 +37476,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
36823
37476
  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.`);
36824
37477
  }
36825
37478
  const resolvedPath = expandTilde(entry.path);
36826
- if (!fs41.existsSync(resolvedPath)) {
37479
+ if (!fs43.existsSync(resolvedPath)) {
36827
37480
  throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
36828
37481
  }
36829
37482
  }
@@ -36839,19 +37492,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
36839
37492
  init_port_validator();
36840
37493
 
36841
37494
  // ../core/dist/world/bootstrap-hooks.js
36842
- import * as fs42 from "node:fs";
36843
- import * as path42 from "node:path";
37495
+ import * as fs44 from "node:fs";
37496
+ import * as path44 from "node:path";
36844
37497
  function runFixtureCopySeeds(seeds, workspacePath) {
36845
37498
  if (!seeds)
36846
37499
  return;
36847
37500
  for (const seed of seeds) {
36848
37501
  if (seed.type !== "fixture-copy")
36849
37502
  continue;
36850
- const srcAbs = path42.resolve(workspacePath, seed.repo, seed.src);
36851
- const destAbs = path42.resolve(workspacePath, seed.repo, seed.dest);
36852
- const destDir = path42.dirname(destAbs);
36853
- fs42.mkdirSync(destDir, { recursive: true });
36854
- fs42.cpSync(srcAbs, destAbs, { recursive: true, force: true });
37503
+ const srcAbs = path44.resolve(workspacePath, seed.repo, seed.src);
37504
+ const destAbs = path44.resolve(workspacePath, seed.repo, seed.dest);
37505
+ const destDir = path44.dirname(destAbs);
37506
+ fs44.mkdirSync(destDir, { recursive: true });
37507
+ fs44.cpSync(srcAbs, destAbs, { recursive: true, force: true });
36855
37508
  }
36856
37509
  }
36857
37510
  async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
@@ -37487,7 +38140,7 @@ ${detail}`);
37487
38140
  runbookSeeds = resolved.seeds;
37488
38141
  }
37489
38142
  const worldId = generateWorldId();
37490
- const workspacePath = path43.join(os26.homedir(), ".olam", "worlds", worldId);
38143
+ const workspacePath = path45.join(os26.homedir(), ".olam", "worlds", worldId);
37491
38144
  const portOffset = this.registry.getNextPortOffset();
37492
38145
  const branch = opts.branchName ?? `olam/${worldId}`;
37493
38146
  const repos = this.resolveReposWithWorkspace(opts);
@@ -37569,37 +38222,37 @@ ${detail}`);
37569
38222
  if (!repo.path)
37570
38223
  continue;
37571
38224
  const sourceRoot = repo.path.replace(/^~/, os26.homedir());
37572
- const worktreeRoot = path43.join(workspacePath, repo.name);
37573
- if (!fs43.existsSync(sourceRoot) || !fs43.existsSync(worktreeRoot))
38225
+ const worktreeRoot = path45.join(workspacePath, repo.name);
38226
+ if (!fs45.existsSync(sourceRoot) || !fs45.existsSync(worktreeRoot))
37574
38227
  continue;
37575
38228
  let copied = 0;
37576
38229
  for (const pattern of RUNTIME_FILE_PATTERNS) {
37577
38230
  const matches2 = [];
37578
38231
  if (pattern.includes("*")) {
37579
- const [dir, glob] = [path43.dirname(pattern), path43.basename(pattern)];
37580
- const sourceDir = path43.join(sourceRoot, dir);
37581
- if (fs43.existsSync(sourceDir)) {
38232
+ const [dir, glob] = [path45.dirname(pattern), path45.basename(pattern)];
38233
+ const sourceDir = path45.join(sourceRoot, dir);
38234
+ if (fs45.existsSync(sourceDir)) {
37582
38235
  const ext = glob.replace(/^\*+/, "");
37583
38236
  try {
37584
- for (const entry of fs43.readdirSync(sourceDir)) {
38237
+ for (const entry of fs45.readdirSync(sourceDir)) {
37585
38238
  if (ext === "" || entry.endsWith(ext))
37586
- matches2.push(path43.join(dir, entry));
38239
+ matches2.push(path45.join(dir, entry));
37587
38240
  }
37588
38241
  } catch {
37589
38242
  }
37590
38243
  }
37591
- } else if (fs43.existsSync(path43.join(sourceRoot, pattern))) {
38244
+ } else if (fs45.existsSync(path45.join(sourceRoot, pattern))) {
37592
38245
  matches2.push(pattern);
37593
38246
  }
37594
38247
  for (const rel of matches2) {
37595
- const src = path43.join(sourceRoot, rel);
37596
- const dst = path43.join(worktreeRoot, rel);
38248
+ const src = path45.join(sourceRoot, rel);
38249
+ const dst = path45.join(worktreeRoot, rel);
37597
38250
  try {
37598
- const st = fs43.statSync(src);
38251
+ const st = fs45.statSync(src);
37599
38252
  if (!st.isFile())
37600
38253
  continue;
37601
- fs43.mkdirSync(path43.dirname(dst), { recursive: true });
37602
- fs43.copyFileSync(src, dst);
38254
+ fs45.mkdirSync(path45.dirname(dst), { recursive: true });
38255
+ fs45.copyFileSync(src, dst);
37603
38256
  copied++;
37604
38257
  } catch {
37605
38258
  }
@@ -37685,7 +38338,7 @@ ${detail}`);
37685
38338
  }
37686
38339
  const overlayAttachments = [];
37687
38340
  for (const repo of repos) {
37688
- const worldClonePath = path43.join(workspacePath, repo.name);
38341
+ const worldClonePath = path45.join(workspacePath, repo.name);
37689
38342
  try {
37690
38343
  const result = createWorldOverlay({
37691
38344
  workspace: repo.name,
@@ -37740,7 +38393,7 @@ ${detail}`);
37740
38393
  try {
37741
38394
  const hostExec = makeHostExecFn();
37742
38395
  for (const repo of repos) {
37743
- const repoDir = path43.join(workspacePath, repo.name);
38396
+ const repoDir = path45.join(workspacePath, repo.name);
37744
38397
  if (repo.stack && Object.keys(repo.stack).length > 0) {
37745
38398
  preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
37746
38399
  } else {
@@ -37784,10 +38437,10 @@ ${detail}`);
37784
38437
  const worldEnv = {};
37785
38438
  if (opts.task)
37786
38439
  worldEnv.OLAM_TASK = opts.task;
37787
- const r2CredsPath = path43.join(os26.homedir(), ".olam", "r2-credentials.json");
37788
- if (fs43.existsSync(r2CredsPath)) {
38440
+ const r2CredsPath = path45.join(os26.homedir(), ".olam", "r2-credentials.json");
38441
+ if (fs45.existsSync(r2CredsPath)) {
37789
38442
  try {
37790
- const r2Raw = fs43.readFileSync(r2CredsPath, "utf-8").trim();
38443
+ const r2Raw = fs45.readFileSync(r2CredsPath, "utf-8").trim();
37791
38444
  if (r2Raw.length > 0) {
37792
38445
  const r2 = JSON.parse(r2Raw);
37793
38446
  if (typeof r2.account_id === "string")
@@ -37804,10 +38457,10 @@ ${detail}`);
37804
38457
  } catch {
37805
38458
  }
37806
38459
  }
37807
- const keysYamlPath = path43.join(os26.homedir(), ".olam", "keys.yaml");
37808
- if (fs43.existsSync(keysYamlPath)) {
38460
+ const keysYamlPath = path45.join(os26.homedir(), ".olam", "keys.yaml");
38461
+ if (fs45.existsSync(keysYamlPath)) {
37809
38462
  try {
37810
- const keysRaw = fs43.readFileSync(keysYamlPath, "utf-8").trim();
38463
+ const keysRaw = fs45.readFileSync(keysYamlPath, "utf-8").trim();
37811
38464
  if (keysRaw.length > 0) {
37812
38465
  const parsed = YAML3.parse(keysRaw);
37813
38466
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
@@ -37866,10 +38519,10 @@ ${detail}`);
37866
38519
  worldEnv[k] = v;
37867
38520
  }
37868
38521
  for (const { repoName, relativePath, content } of fileWrites) {
37869
- const absPath = path43.join(workspacePath, repoName, relativePath);
38522
+ const absPath = path45.join(workspacePath, repoName, relativePath);
37870
38523
  try {
37871
- fs43.mkdirSync(path43.dirname(absPath), { recursive: true });
37872
- fs43.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
38524
+ fs45.mkdirSync(path45.dirname(absPath), { recursive: true });
38525
+ fs45.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
37873
38526
  mode: 384
37874
38527
  });
37875
38528
  console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
@@ -38046,7 +38699,7 @@ ${detail}`);
38046
38699
  imageDigest: void 0,
38047
38700
  repos: enrichedRepos.map((r) => ({
38048
38701
  name: r.name,
38049
- worktreeDir: path43.join(workspacePath, r.name)
38702
+ worktreeDir: path45.join(workspacePath, r.name)
38050
38703
  }))
38051
38704
  });
38052
38705
  for (const out of restoreResult.outcomes) {
@@ -38152,7 +38805,7 @@ ${detail}`);
38152
38805
  }
38153
38806
  if (opts.task) {
38154
38807
  const allPolicies = repos.flatMap((repo) => {
38155
- const repoWorktree = path43.join(workspacePath, repo.name);
38808
+ const repoWorktree = path45.join(workspacePath, repo.name);
38156
38809
  try {
38157
38810
  return loadPolicies(repoWorktree);
38158
38811
  } catch (err) {
@@ -38165,8 +38818,8 @@ ${detail}`);
38165
38818
  try {
38166
38819
  execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
38167
38820
  for (const repo of repos) {
38168
- const policiesDir = path43.join(workspacePath, repo.name, ".olam", "policies");
38169
- if (fs43.existsSync(policiesDir)) {
38821
+ const policiesDir = path45.join(workspacePath, repo.name, ".olam", "policies");
38822
+ if (fs45.existsSync(policiesDir)) {
38170
38823
  execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
38171
38824
  }
38172
38825
  }
@@ -38274,8 +38927,8 @@ ${detail}`);
38274
38927
  } catch {
38275
38928
  }
38276
38929
  try {
38277
- fs43.rmSync(world.workspacePath, { recursive: true, force: true });
38278
- if (fs43.existsSync(world.workspacePath)) {
38930
+ fs45.rmSync(world.workspacePath, { recursive: true, force: true });
38931
+ if (fs45.existsSync(world.workspacePath)) {
38279
38932
  console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
38280
38933
  }
38281
38934
  } catch (err) {
@@ -38384,14 +39037,14 @@ ${detail}`);
38384
39037
  }).filter((r) => r !== void 0);
38385
39038
  }
38386
39039
  transportPlanFile(planFilePath, workspacePath, repoNames) {
38387
- const planContent = fs43.readFileSync(planFilePath, "utf-8");
38388
- const planFileName = path43.basename(planFilePath);
39040
+ const planContent = fs45.readFileSync(planFilePath, "utf-8");
39041
+ const planFileName = path45.basename(planFilePath);
38389
39042
  const targetRepo = repoNames[0];
38390
39043
  if (!targetRepo)
38391
39044
  return;
38392
- const plansDir = path43.join(workspacePath, targetRepo, "docs", "plans");
38393
- fs43.mkdirSync(plansDir, { recursive: true });
38394
- fs43.writeFileSync(path43.join(plansDir, planFileName), planContent);
39045
+ const plansDir = path45.join(workspacePath, targetRepo, "docs", "plans");
39046
+ fs45.mkdirSync(plansDir, { recursive: true });
39047
+ fs45.writeFileSync(path45.join(plansDir, planFileName), planContent);
38395
39048
  }
38396
39049
  resolveServices(repos) {
38397
39050
  const services = [];
@@ -38825,8 +39478,8 @@ import * as http2 from "node:http";
38825
39478
 
38826
39479
  // ../core/dist/dashboard/server.js
38827
39480
  import * as http from "node:http";
38828
- import * as fs44 from "node:fs";
38829
- import * as path44 from "node:path";
39481
+ import * as fs46 from "node:fs";
39482
+ import * as path46 from "node:path";
38830
39483
  import { fileURLToPath as fileURLToPath3 } from "node:url";
38831
39484
 
38832
39485
  // ../core/dist/dashboard/serialize.js
@@ -39161,7 +39814,7 @@ function notFound(res) {
39161
39814
  }
39162
39815
  function openThoughtStore(workspacePath) {
39163
39816
  const dbPath = getWorldDbPath(workspacePath);
39164
- if (!fs44.existsSync(dbPath))
39817
+ if (!fs46.existsSync(dbPath))
39165
39818
  return null;
39166
39819
  return new ThoughtLocalStore(dbPath);
39167
39820
  }
@@ -39332,13 +39985,13 @@ function findSessionInWorld(registry2, sessionId) {
39332
39985
  }
39333
39986
  function createDashboardServer(opts) {
39334
39987
  const { port: port2, registry: registry2 } = opts;
39335
- const thisDir = path44.dirname(fileURLToPath3(import.meta.url));
39336
- const defaultPublicDir = path44.resolve(thisDir, "../../../control-plane/public");
39988
+ const thisDir = path46.dirname(fileURLToPath3(import.meta.url));
39989
+ const defaultPublicDir = path46.resolve(thisDir, "../../../control-plane/public");
39337
39990
  const publicDir = opts.publicDir ?? defaultPublicDir;
39338
- let hasPublicDir = fs44.existsSync(publicDir);
39991
+ let hasPublicDir = fs46.existsSync(publicDir);
39339
39992
  const server = http.createServer((req, res) => {
39340
39993
  if (!hasPublicDir) {
39341
- hasPublicDir = fs44.existsSync(publicDir);
39994
+ hasPublicDir = fs46.existsSync(publicDir);
39342
39995
  }
39343
39996
  const host = req.headers.host ?? `localhost:${port2}`;
39344
39997
  const url2 = new URL(req.url ?? "/", `http://${host}`);
@@ -39612,22 +40265,22 @@ function createDashboardServer(opts) {
39612
40265
  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>`);
39613
40266
  return;
39614
40267
  }
39615
- let filePath = path44.join(publicDir, pathname === "/" ? "index.html" : pathname);
40268
+ let filePath = path46.join(publicDir, pathname === "/" ? "index.html" : pathname);
39616
40269
  if (!filePath.startsWith(publicDir)) {
39617
40270
  notFound(res);
39618
40271
  return;
39619
40272
  }
39620
- if (fs44.existsSync(filePath) && fs44.statSync(filePath).isFile()) {
39621
- const ext = path44.extname(filePath);
40273
+ if (fs46.existsSync(filePath) && fs46.statSync(filePath).isFile()) {
40274
+ const ext = path46.extname(filePath);
39622
40275
  const contentType = MIME[ext] ?? "application/octet-stream";
39623
40276
  res.writeHead(200, { "Content-Type": contentType });
39624
- fs44.createReadStream(filePath).pipe(res);
40277
+ fs46.createReadStream(filePath).pipe(res);
39625
40278
  return;
39626
40279
  }
39627
- filePath = path44.join(publicDir, "index.html");
39628
- if (fs44.existsSync(filePath)) {
40280
+ filePath = path46.join(publicDir, "index.html");
40281
+ if (fs46.existsSync(filePath)) {
39629
40282
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
39630
- fs44.createReadStream(filePath).pipe(res);
40283
+ fs46.createReadStream(filePath).pipe(res);
39631
40284
  return;
39632
40285
  }
39633
40286
  notFound(res);
@@ -39637,17 +40290,17 @@ function createDashboardServer(opts) {
39637
40290
  }
39638
40291
 
39639
40292
  // ../core/dist/dashboard/state.js
39640
- import * as fs45 from "node:fs";
40293
+ import * as fs47 from "node:fs";
39641
40294
  import * as os27 from "node:os";
39642
- import * as path45 from "node:path";
39643
- var STATE_PATH = path45.join(os27.homedir(), ".olam", "dashboard.json");
40295
+ import * as path47 from "node:path";
40296
+ var STATE_PATH = path47.join(os27.homedir(), ".olam", "dashboard.json");
39644
40297
  function saveDashboardState(state) {
39645
- fs45.mkdirSync(path45.dirname(STATE_PATH), { recursive: true });
39646
- fs45.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
40298
+ fs47.mkdirSync(path47.dirname(STATE_PATH), { recursive: true });
40299
+ fs47.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
39647
40300
  }
39648
40301
  function loadDashboardState() {
39649
40302
  try {
39650
- const raw = fs45.readFileSync(STATE_PATH, "utf-8");
40303
+ const raw = fs47.readFileSync(STATE_PATH, "utf-8");
39651
40304
  return JSON.parse(raw);
39652
40305
  } catch {
39653
40306
  return null;
@@ -39655,7 +40308,7 @@ function loadDashboardState() {
39655
40308
  }
39656
40309
  function clearDashboardState() {
39657
40310
  try {
39658
- fs45.unlinkSync(STATE_PATH);
40311
+ fs47.unlinkSync(STATE_PATH);
39659
40312
  } catch {
39660
40313
  }
39661
40314
  }
@@ -39684,7 +40337,7 @@ function isCloudflaredAvailable() {
39684
40337
  }
39685
40338
  }
39686
40339
  function startTunnel(port2) {
39687
- return new Promise((resolve13, reject2) => {
40340
+ return new Promise((resolve14, reject2) => {
39688
40341
  const child = spawn3("cloudflared", ["tunnel", "--url", `http://localhost:${port2}`], {
39689
40342
  stdio: ["ignore", "pipe", "pipe"],
39690
40343
  detached: false
@@ -39706,7 +40359,7 @@ function startTunnel(port2) {
39706
40359
  if (match) {
39707
40360
  resolved = true;
39708
40361
  clearTimeout(timeout);
39709
- resolve13(match[0]);
40362
+ resolve14(match[0]);
39710
40363
  }
39711
40364
  }
39712
40365
  child.stdout?.on("data", scan);
@@ -39774,8 +40427,8 @@ var DashboardManager = class {
39774
40427
  }
39775
40428
  throw err;
39776
40429
  }
39777
- await new Promise((resolve13, reject2) => {
39778
- this.server.on("listening", resolve13);
40430
+ await new Promise((resolve14, reject2) => {
40431
+ this.server.on("listening", resolve14);
39779
40432
  this.server.on("error", reject2);
39780
40433
  });
39781
40434
  this.info = { localUrl: `http://localhost:${port2}` };
@@ -39821,8 +40474,8 @@ var DashboardManager = class {
39821
40474
  async stop() {
39822
40475
  stopTunnel();
39823
40476
  if (this.server) {
39824
- await new Promise((resolve13) => {
39825
- this.server.close(() => resolve13());
40477
+ await new Promise((resolve14) => {
40478
+ this.server.close(() => resolve14());
39826
40479
  });
39827
40480
  this.server = null;
39828
40481
  }
@@ -39935,8 +40588,8 @@ var PleriClient = class {
39935
40588
  };
39936
40589
 
39937
40590
  // ../mcp-server/src/env-loader.ts
39938
- import { readFileSync as readFileSync33, existsSync as existsSync42, statSync as statSync12 } from "node:fs";
39939
- import { join as join46, dirname as dirname28, resolve as resolve12 } from "node:path";
40591
+ import { readFileSync as readFileSync36, existsSync as existsSync45, statSync as statSync14 } from "node:fs";
40592
+ import { join as join48, dirname as dirname28, resolve as resolve13 } from "node:path";
39940
40593
  var PROJECT_MARKERS = [
39941
40594
  ".olam/config.yaml",
39942
40595
  ".olam/config.yml",
@@ -39944,16 +40597,16 @@ var PROJECT_MARKERS = [
39944
40597
  "olam.yml"
39945
40598
  ];
39946
40599
  function findProjectRoot2(startDir) {
39947
- let dir = resolve12(startDir);
39948
- const root = resolve12("/");
40600
+ let dir = resolve13(startDir);
40601
+ const root = resolve13("/");
39949
40602
  while (true) {
39950
40603
  for (const marker of PROJECT_MARKERS) {
39951
- if (existsSync42(join46(dir, marker))) return dir;
40604
+ if (existsSync45(join48(dir, marker))) return dir;
39952
40605
  }
39953
- const pkg = join46(dir, "package.json");
39954
- if (existsSync42(pkg)) {
40606
+ const pkg = join48(dir, "package.json");
40607
+ if (existsSync45(pkg)) {
39955
40608
  try {
39956
- const json = JSON.parse(readFileSync33(pkg, "utf8"));
40609
+ const json = JSON.parse(readFileSync36(pkg, "utf8"));
39957
40610
  const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
39958
40611
  const hasOlamDep = json.dependencies && Object.keys(json.dependencies).some((k) => k.startsWith("@olam/")) || json.devDependencies && Object.keys(json.devDependencies).some((k) => k.startsWith("@olam/"));
39959
40612
  if (isOlamWorkspace || hasOlamDep) return dir;
@@ -39965,9 +40618,9 @@ function findProjectRoot2(startDir) {
39965
40618
  dir = parent;
39966
40619
  }
39967
40620
  }
39968
- function parseEnvFile(path46) {
40621
+ function parseEnvFile(path48) {
39969
40622
  const out = {};
39970
- const raw = readFileSync33(path46, "utf8");
40623
+ const raw = readFileSync36(path48, "utf8");
39971
40624
  for (const line of raw.split(/\r?\n/)) {
39972
40625
  const trimmed = line.trim();
39973
40626
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -39990,8 +40643,8 @@ function loadProjectEnv(startDir = process.cwd()) {
39990
40643
  const filesRead = [];
39991
40644
  const merged = {};
39992
40645
  for (const name of [".env", ".env.local"]) {
39993
- const p = join46(root, name);
39994
- if (existsSync42(p) && statSync12(p).isFile()) {
40646
+ const p = join48(root, name);
40647
+ if (existsSync45(p) && statSync14(p).isFile()) {
39995
40648
  Object.assign(merged, parseEnvFile(p));
39996
40649
  filesRead.push(p);
39997
40650
  }