@pleri/olam-cli 0.1.146 → 0.1.147

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.
@@ -445,8 +445,8 @@ var init_parseUtil = __esm({
445
445
  init_errors();
446
446
  init_en();
447
447
  makeIssue = (params) => {
448
- const { data, path: path44, errorMaps, issueData } = params;
449
- const fullPath = [...path44, ...issueData.path || []];
448
+ const { data, path: path46, errorMaps, issueData } = params;
449
+ const fullPath = [...path46, ...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, path44, key) {
757
+ constructor(parent, value, path46, key) {
758
758
  this._cachedPath = [];
759
759
  this.parent = parent;
760
760
  this.data = value;
761
- this._path = path44;
761
+ this._path = path46;
762
762
  this._key = key;
763
763
  }
764
764
  get path() {
@@ -7332,8 +7332,8 @@ var require_utils = __commonJS({
7332
7332
  }
7333
7333
  return ind;
7334
7334
  }
7335
- function removeDotSegments(path44) {
7336
- let input = path44;
7335
+ function removeDotSegments(path46) {
7336
+ let input = path46;
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 [path44, query] = wsComponent.resourceName.split("?");
7536
- wsComponent.path = path44 && path44 !== "/" ? path44 : void 0;
7535
+ const [path46, query] = wsComponent.resourceName.split("?");
7536
+ wsComponent.path = path46 && path46 !== "/" ? path46 : void 0;
7537
7537
  wsComponent.query = query;
7538
7538
  wsComponent.resourceName = void 0;
7539
7539
  }
@@ -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, fs42, exportName) {
10898
+ function addFormats(ajv, list, fs46, 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, fs42[f]);
10903
+ ajv.addFormat(f, fs46[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, path44, ctx, rejectSource) {
11011
+ function refineForbiddenKeys(value, path46, 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, path44, ctx, rejectSource) {
11016
11016
  if (FORBIDDEN_KEYS.has(key)) {
11017
11017
  ctx.addIssue({
11018
11018
  code: external_exports.ZodIssueCode.custom,
11019
- path: [...path44, key],
11019
+ path: [...path46, key],
11020
11020
  message: `forbidden key "${key}" (prototype-pollution surface)`
11021
11021
  });
11022
11022
  continue;
11023
11023
  }
11024
- if (rejectSource && path44.length === 0 && key === "source") {
11024
+ if (rejectSource && path46.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, path44, ctx, rejectSource) {
11029
11029
  });
11030
11030
  continue;
11031
11031
  }
11032
- refineForbiddenKeys(value[key], [...path44, key], ctx, false);
11032
+ refineForbiddenKeys(value[key], [...path46, key], ctx, false);
11033
11033
  }
11034
11034
  }
11035
- function rejectForbiddenKeys(value, path44, rejectSource) {
11035
+ function rejectForbiddenKeys(value, path46, 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] ${path44}: forbidden key "${key}" (prototype-pollution surface)`);
11041
+ throw new Error(`[manifest] ${path46}: forbidden key "${key}" (prototype-pollution surface)`);
11042
11042
  }
11043
11043
  if (rejectSource && key === "source") {
11044
- throw new Error(`[manifest] ${path44}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11044
+ throw new Error(`[manifest] ${path46}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11045
11045
  }
11046
- rejectForbiddenKeys(value[key], `${path44}.${key}`, false);
11046
+ rejectForbiddenKeys(value[key], `${path46}.${key}`, false);
11047
11047
  }
11048
11048
  }
11049
11049
  function unknownTopLevelKeys(parsed) {
@@ -11921,7 +11921,7 @@ function isAbsoluteOrTilde(p) {
11921
11921
  function hasNoTraversalComponents(p) {
11922
11922
  return !p.split("/").some((seg) => seg === "..");
11923
11923
  }
11924
- var RepoEntrySchema, PortMapSchema, SeedSqlFileSchema, SeedCommandSchema, SeedFixtureCopySchema, SeedSchema, RunbookSchema, GlobalConfigSchema, DEFAULT_GLOBAL_CONFIG;
11924
+ var RepoEntrySchema, PortMapSchema, SeedSqlFileSchema, SeedCommandSchema, SeedFixtureCopySchema, SeedSchema, RunbookSchema, MetaHookBlockKindSchema, GlobalConfigSchema, DEFAULT_GLOBAL_CONFIG;
11925
11925
  var init_schema4 = __esm({
11926
11926
  "../core/dist/global-config/schema.js"() {
11927
11927
  "use strict";
@@ -11971,11 +11971,19 @@ var init_schema4 = __esm({
11971
11971
  env: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.string())).optional(),
11972
11972
  updatedAt: external_exports.number().int().nonnegative()
11973
11973
  });
11974
+ MetaHookBlockKindSchema = external_exports.enum(["memory-recall", "memory-classify"]);
11974
11975
  GlobalConfigSchema = external_exports.object({
11975
11976
  schemaVersion: external_exports.literal(1),
11976
11977
  repos: external_exports.array(RepoEntrySchema).optional().default([]),
11977
11978
  runbooks: external_exports.array(RunbookSchema).optional().default([]),
11978
- skillSources: external_exports.array(SkillSourceSchema).optional().default([])
11979
+ skillSources: external_exports.array(SkillSourceSchema).optional().default([]),
11980
+ /**
11981
+ * Phase B B4 — per-block disable list. Operator escape-hatch when a
11982
+ * specific meta-hook misbehaves; engine `injectMetaHooks` filters
11983
+ * these out regardless of services-status detection. CLI
11984
+ * `--meta-hooks-disabled <a,b>` flag (deferred) can override per-call.
11985
+ */
11986
+ metaHooksDisabled: external_exports.array(MetaHookBlockKindSchema).optional().default([])
11979
11987
  }).strip().superRefine((val, ctx) => {
11980
11988
  const repoNames = val.repos.map((r) => r.name);
11981
11989
  const repoDupes = repoNames.filter((n, i) => repoNames.indexOf(n) !== i);
@@ -12002,7 +12010,8 @@ var init_schema4 = __esm({
12002
12010
  schemaVersion: 1,
12003
12011
  repos: [],
12004
12012
  runbooks: [],
12005
- skillSources: []
12013
+ skillSources: [],
12014
+ metaHooksDisabled: []
12006
12015
  };
12007
12016
  }
12008
12017
  });
@@ -12402,7 +12411,14 @@ var init_trust_audit_log = __esm({
12402
12411
  "use strict";
12403
12412
  init_v3();
12404
12413
  SKILL_SOURCES_AUDIT_LOG_FILENAME = "skill-sources-audit.log";
12405
- TrustActionSchema = external_exports.enum(["added", "rejected", "auto-rejected", "failed", "removed"]);
12414
+ TrustActionSchema = external_exports.enum([
12415
+ "added",
12416
+ "rejected",
12417
+ "auto-rejected",
12418
+ "failed",
12419
+ "removed",
12420
+ "meta-hook-stripped"
12421
+ ]);
12406
12422
  TrustMethodSchema = external_exports.enum(["flag", "interactive", "auto-reject-tty", "none"]);
12407
12423
  TrustAuditEntrySchema = external_exports.object({
12408
12424
  timestamp: external_exports.string().min(1),
@@ -13317,8 +13333,167 @@ var init_symlink_deployer = __esm({
13317
13333
  }
13318
13334
  });
13319
13335
 
13320
- // ../core/dist/skill-sync/settings-merger.js
13336
+ // ../core/dist/meta-hooks/memory-recall.js
13321
13337
  import * as fs21 from "node:fs";
13338
+ function buildMemoryRecallHookEntry() {
13339
+ return {
13340
+ matcher: OLAM_META_MEMORY_RECALL_MATCHER,
13341
+ hooks: [
13342
+ {
13343
+ type: "command",
13344
+ command: `OLAM_META_SENTINEL=${OLAM_META_MEMORY_RECALL_SENTINEL}; ${OLAM_META_NOOP_GUARD} node "${OLAM_META_MEMORY_RECALL_SCRIPT_PATH}"`,
13345
+ timeout: OLAM_META_MEMORY_RECALL_TIMEOUT_MS
13346
+ }
13347
+ ]
13348
+ };
13349
+ }
13350
+ function computeMemoryRecallUninstall(settings) {
13351
+ const matchers = settings.hooks?.PreToolUse;
13352
+ if (!Array.isArray(matchers) || matchers.length === 0) {
13353
+ return { status: "not-found" };
13354
+ }
13355
+ let changed = false;
13356
+ const filteredMatchers = [];
13357
+ for (const matcher of matchers) {
13358
+ const innerHooks = matcher.hooks ?? [];
13359
+ const keptInner = innerHooks.filter((h) => {
13360
+ if (typeof h.command === "string" && h.command.includes(OLAM_META_MEMORY_RECALL_SENTINEL)) {
13361
+ changed = true;
13362
+ return false;
13363
+ }
13364
+ return true;
13365
+ });
13366
+ if (keptInner.length === 0 && innerHooks.length > 0) {
13367
+ changed = true;
13368
+ continue;
13369
+ }
13370
+ if (keptInner.length === innerHooks.length) {
13371
+ filteredMatchers.push(matcher);
13372
+ } else {
13373
+ filteredMatchers.push({ ...matcher, hooks: keptInner });
13374
+ }
13375
+ }
13376
+ if (!changed)
13377
+ return { status: "not-found" };
13378
+ const next = {
13379
+ ...settings,
13380
+ hooks: {
13381
+ ...settings.hooks,
13382
+ PreToolUse: filteredMatchers
13383
+ }
13384
+ };
13385
+ if (filteredMatchers.length === 0) {
13386
+ const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "PreToolUse");
13387
+ if (otherStages.length === 0) {
13388
+ delete next.hooks;
13389
+ } else {
13390
+ delete next.hooks.PreToolUse;
13391
+ }
13392
+ }
13393
+ return { status: "removed", settingsAfter: next };
13394
+ }
13395
+ function matchMemoryRecallSentinel(commandLine) {
13396
+ return commandLine.includes(OLAM_META_MEMORY_RECALL_SENTINEL);
13397
+ }
13398
+ var OLAM_META_MEMORY_RECALL_SENTINEL, OLAM_META_MEMORY_RECALL_STAGE, OLAM_META_MEMORY_RECALL_MATCHER, OLAM_META_MEMORY_RECALL_TIMEOUT_MS, OLAM_META_MEMORY_RECALL_SCRIPT_PATH, OLAM_META_NOOP_GUARD;
13399
+ var init_memory_recall = __esm({
13400
+ "../core/dist/meta-hooks/memory-recall.js"() {
13401
+ "use strict";
13402
+ OLAM_META_MEMORY_RECALL_SENTINEL = "olam-meta-memory-recall-v1";
13403
+ OLAM_META_MEMORY_RECALL_STAGE = "PreToolUse";
13404
+ OLAM_META_MEMORY_RECALL_MATCHER = "Bash|Edit|MultiEdit|Write|Read|NotebookEdit";
13405
+ OLAM_META_MEMORY_RECALL_TIMEOUT_MS = 5e3;
13406
+ OLAM_META_MEMORY_RECALL_SCRIPT_PATH = "$HOME/.claude/scripts/agentmemory-classifier/agentmemory-recall-trigger.mjs";
13407
+ OLAM_META_NOOP_GUARD = "command -v olam >/dev/null 2>&1 || exit 0;";
13408
+ }
13409
+ });
13410
+
13411
+ // ../core/dist/meta-hooks/memory-classify.js
13412
+ import * as fs22 from "node:fs";
13413
+ function buildMemoryClassifyHookEntry() {
13414
+ return {
13415
+ matcher: OLAM_META_MEMORY_CLASSIFY_MATCHER,
13416
+ hooks: [
13417
+ {
13418
+ type: "command",
13419
+ command: `OLAM_META_SENTINEL=${OLAM_META_MEMORY_CLASSIFY_SENTINEL}; ${OLAM_META_NOOP_GUARD2} node "${OLAM_META_MEMORY_CLASSIFY_SCRIPT_PATH}"`,
13420
+ timeout: OLAM_META_MEMORY_CLASSIFY_TIMEOUT_MS
13421
+ }
13422
+ ]
13423
+ };
13424
+ }
13425
+ function computeMemoryClassifyUninstall(settings) {
13426
+ const matchers = settings.hooks?.PostToolUse;
13427
+ if (!Array.isArray(matchers) || matchers.length === 0) {
13428
+ return { status: "not-found" };
13429
+ }
13430
+ let changed = false;
13431
+ const filteredMatchers = [];
13432
+ for (const matcher of matchers) {
13433
+ const innerHooks = matcher.hooks ?? [];
13434
+ const keptInner = innerHooks.filter((h) => {
13435
+ if (typeof h.command === "string" && h.command.includes(OLAM_META_MEMORY_CLASSIFY_SENTINEL)) {
13436
+ changed = true;
13437
+ return false;
13438
+ }
13439
+ return true;
13440
+ });
13441
+ if (keptInner.length === 0 && innerHooks.length > 0) {
13442
+ changed = true;
13443
+ continue;
13444
+ }
13445
+ if (keptInner.length === innerHooks.length) {
13446
+ filteredMatchers.push(matcher);
13447
+ } else {
13448
+ filteredMatchers.push({ ...matcher, hooks: keptInner });
13449
+ }
13450
+ }
13451
+ if (!changed)
13452
+ return { status: "not-found" };
13453
+ const next = {
13454
+ ...settings,
13455
+ hooks: {
13456
+ ...settings.hooks,
13457
+ PostToolUse: filteredMatchers
13458
+ }
13459
+ };
13460
+ if (filteredMatchers.length === 0) {
13461
+ const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "PostToolUse");
13462
+ if (otherStages.length === 0) {
13463
+ delete next.hooks;
13464
+ } else {
13465
+ delete next.hooks.PostToolUse;
13466
+ }
13467
+ }
13468
+ return { status: "removed", settingsAfter: next };
13469
+ }
13470
+ function matchMemoryClassifySentinel(commandLine) {
13471
+ return commandLine.includes(OLAM_META_MEMORY_CLASSIFY_SENTINEL);
13472
+ }
13473
+ var OLAM_META_MEMORY_CLASSIFY_SENTINEL, OLAM_META_MEMORY_CLASSIFY_STAGE, OLAM_META_MEMORY_CLASSIFY_MATCHER, OLAM_META_MEMORY_CLASSIFY_TIMEOUT_MS, OLAM_META_MEMORY_CLASSIFY_SCRIPT_PATH, OLAM_META_NOOP_GUARD2;
13474
+ var init_memory_classify = __esm({
13475
+ "../core/dist/meta-hooks/memory-classify.js"() {
13476
+ "use strict";
13477
+ OLAM_META_MEMORY_CLASSIFY_SENTINEL = "olam-meta-memory-classify-v1";
13478
+ OLAM_META_MEMORY_CLASSIFY_STAGE = "PostToolUse";
13479
+ OLAM_META_MEMORY_CLASSIFY_MATCHER = "Bash|Edit|MultiEdit|Write|Read|NotebookEdit";
13480
+ OLAM_META_MEMORY_CLASSIFY_TIMEOUT_MS = 5e3;
13481
+ OLAM_META_MEMORY_CLASSIFY_SCRIPT_PATH = "$HOME/.claude/scripts/agentmemory-classifier/agentmemory-classify-queue.mjs";
13482
+ OLAM_META_NOOP_GUARD2 = "command -v olam >/dev/null 2>&1 || exit 0;";
13483
+ }
13484
+ });
13485
+
13486
+ // ../core/dist/meta-hooks/index.js
13487
+ var init_meta_hooks = __esm({
13488
+ "../core/dist/meta-hooks/index.js"() {
13489
+ "use strict";
13490
+ init_memory_recall();
13491
+ init_memory_classify();
13492
+ }
13493
+ });
13494
+
13495
+ // ../core/dist/skill-sync/settings-merger.js
13496
+ import * as fs23 from "node:fs";
13322
13497
  import * as os14 from "node:os";
13323
13498
  import * as path22 from "node:path";
13324
13499
  function claudeSettingsPath() {
@@ -13346,32 +13521,66 @@ function dedupeByMatcher(entries) {
13346
13521
  }
13347
13522
  return [...map.values()];
13348
13523
  }
13524
+ function commandsInEntry(entry) {
13525
+ const cmds = [];
13526
+ const direct = entry["command"];
13527
+ if (typeof direct === "string")
13528
+ cmds.push(direct);
13529
+ const inner = entry["hooks"];
13530
+ if (Array.isArray(inner)) {
13531
+ for (const h of inner) {
13532
+ if (h && typeof h === "object" && typeof h.command === "string") {
13533
+ cmds.push(h.command);
13534
+ }
13535
+ }
13536
+ }
13537
+ return cmds;
13538
+ }
13539
+ function applyDualWriteDedup(incoming, preserved) {
13540
+ const preservedCommands = preserved.flatMap(commandsInEntry);
13541
+ const preservedHas = (sentinel) => preservedCommands.some((c) => c.includes(sentinel));
13542
+ let droppedCount = 0;
13543
+ const droppedCommands = [];
13544
+ const kept = incoming.filter((entry) => {
13545
+ const incomingCommands = commandsInEntry(entry);
13546
+ for (const rule of DUAL_WRITE_DEDUP_RULES) {
13547
+ const hasIncomingScript = incomingCommands.some((c) => c.includes(rule.incomingCommandSubstring));
13548
+ if (hasIncomingScript && preservedHas(rule.preservedSentinel)) {
13549
+ droppedCount += 1;
13550
+ droppedCommands.push(...incomingCommands.filter((c) => c.includes(rule.incomingCommandSubstring)));
13551
+ return false;
13552
+ }
13553
+ }
13554
+ return true;
13555
+ });
13556
+ return { kept, droppedCount, droppedCommands };
13557
+ }
13349
13558
  function tagOlam(entry) {
13350
13559
  return { ...entry, [OLAM_SKILLS_MARKER]: true };
13351
13560
  }
13352
13561
  function readJson(file) {
13353
- return JSON.parse(fs21.readFileSync(file, "utf-8"));
13562
+ return JSON.parse(fs23.readFileSync(file, "utf-8"));
13354
13563
  }
13355
13564
  function rotateBackups(backupDir) {
13356
- if (!fs21.existsSync(backupDir))
13565
+ if (!fs23.existsSync(backupDir))
13357
13566
  return;
13358
- const files = fs21.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path22.join(backupDir, f), mtime: fs21.statSync(path22.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
13567
+ const files = fs23.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path22.join(backupDir, f), mtime: fs23.statSync(path22.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
13359
13568
  for (const f of files.slice(BACKUP_RETENTION)) {
13360
13569
  try {
13361
- fs21.unlinkSync(f.full);
13570
+ fs23.unlinkSync(f.full);
13362
13571
  } catch {
13363
13572
  }
13364
13573
  }
13365
13574
  }
13366
13575
  function backupSettings() {
13367
13576
  const src = claudeSettingsPath();
13368
- if (!fs21.existsSync(src))
13577
+ if (!fs23.existsSync(src))
13369
13578
  return void 0;
13370
13579
  const dir = settingsBackupDir();
13371
- fs21.mkdirSync(dir, { recursive: true });
13580
+ fs23.mkdirSync(dir, { recursive: true });
13372
13581
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13373
13582
  const dest = path22.join(dir, `settings-${stamp}.json`);
13374
- fs21.copyFileSync(src, dest);
13583
+ fs23.copyFileSync(src, dest);
13375
13584
  rotateBackups(dir);
13376
13585
  return dest;
13377
13586
  }
@@ -13379,7 +13588,7 @@ function mergeSettings(input) {
13379
13588
  const settingsPath = claudeSettingsPath();
13380
13589
  const backupPath = backupSettings();
13381
13590
  let base = {};
13382
- if (fs21.existsSync(settingsPath)) {
13591
+ if (fs23.existsSync(settingsPath)) {
13383
13592
  try {
13384
13593
  base = readJson(settingsPath);
13385
13594
  } catch {
@@ -13411,13 +13620,18 @@ function mergeSettings(input) {
13411
13620
  ...olamHooksByCategory.keys()
13412
13621
  ]);
13413
13622
  let hooksAdded = 0;
13623
+ let dualWriteDeduped = 0;
13624
+ const dualWriteDroppedCommands = [];
13414
13625
  for (const cat of categories) {
13415
13626
  const existing = Array.isArray(existingHooks[cat]) ? existingHooks[cat] : [];
13416
13627
  const preserved = existing.filter((e) => !e[OLAM_SKILLS_MARKER]);
13417
13628
  const olam = olamHooksByCategory.get(cat) ?? [];
13418
13629
  const olamDeduped = dedupeByMatcher(olam);
13419
- mergedHooks[cat] = [...preserved, ...olamDeduped];
13420
- hooksAdded += olam.length;
13630
+ const { kept: olamFinal, droppedCount, droppedCommands } = applyDualWriteDedup(olamDeduped, preserved);
13631
+ dualWriteDeduped += droppedCount;
13632
+ dualWriteDroppedCommands.push(...droppedCommands);
13633
+ mergedHooks[cat] = [...preserved, ...olamFinal];
13634
+ hooksAdded += olamFinal.length;
13421
13635
  }
13422
13636
  const permSet = /* @__PURE__ */ new Set();
13423
13637
  for (const file of input.permissionFiles) {
@@ -13442,18 +13656,29 @@ function mergeSettings(input) {
13442
13656
  ...input.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
13443
13657
  }
13444
13658
  };
13445
- fs21.mkdirSync(path22.dirname(settingsPath), { recursive: true });
13659
+ fs23.mkdirSync(path22.dirname(settingsPath), { recursive: true });
13446
13660
  const tmp = `${settingsPath}.tmp-${process.pid}`;
13447
- fs21.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
13448
- fs21.renameSync(tmp, settingsPath);
13449
- return { backupPath, hooksAdded, permissionsCount: permSet.size };
13661
+ fs23.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
13662
+ fs23.renameSync(tmp, settingsPath);
13663
+ return { backupPath, hooksAdded, permissionsCount: permSet.size, dualWriteDeduped, dualWriteDroppedCommands };
13450
13664
  }
13451
- var OLAM_SKILLS_MARKER, BACKUP_RETENTION;
13665
+ var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
13452
13666
  var init_settings_merger = __esm({
13453
13667
  "../core/dist/skill-sync/settings-merger.js"() {
13454
13668
  "use strict";
13669
+ init_meta_hooks();
13455
13670
  OLAM_SKILLS_MARKER = "_olamSkillsManaged";
13456
13671
  BACKUP_RETENTION = 30;
13672
+ DUAL_WRITE_DEDUP_RULES = [
13673
+ {
13674
+ preservedSentinel: OLAM_META_MEMORY_RECALL_SENTINEL,
13675
+ incomingCommandSubstring: "agentmemory-recall-trigger.mjs"
13676
+ },
13677
+ {
13678
+ preservedSentinel: OLAM_META_MEMORY_CLASSIFY_SENTINEL,
13679
+ incomingCommandSubstring: "agentmemory-classify-queue.mjs"
13680
+ }
13681
+ ];
13457
13682
  }
13458
13683
  });
13459
13684
 
@@ -13491,7 +13716,7 @@ var init_schema5 = __esm({
13491
13716
 
13492
13717
  // ../core/dist/skill-sync/per-project-override.js
13493
13718
  import { execFileSync as execFileSync3 } from "node:child_process";
13494
- import * as fs22 from "node:fs";
13719
+ import * as fs24 from "node:fs";
13495
13720
  import * as path23 from "node:path";
13496
13721
  import { parse as parseYaml3 } from "yaml";
13497
13722
  function findProjectOverride(startDir) {
@@ -13499,8 +13724,8 @@ function findProjectOverride(startDir) {
13499
13724
  const root = path23.parse(dir).root;
13500
13725
  while (true) {
13501
13726
  const candidate = path23.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
13502
- if (fs22.existsSync(candidate) && fs22.statSync(candidate).isFile()) {
13503
- const raw = fs22.readFileSync(candidate, "utf-8");
13727
+ if (fs24.existsSync(candidate) && fs24.statSync(candidate).isFile()) {
13728
+ const raw = fs24.readFileSync(candidate, "utf-8");
13504
13729
  let parsed;
13505
13730
  try {
13506
13731
  parsed = parseYaml3(raw);
@@ -13559,7 +13784,7 @@ var init_per_project_override = __esm({
13559
13784
  });
13560
13785
 
13561
13786
  // ../core/dist/skill-sync/source-lock.js
13562
- import * as fs23 from "node:fs";
13787
+ import * as fs25 from "node:fs";
13563
13788
  import * as os15 from "node:os";
13564
13789
  import * as path24 from "node:path";
13565
13790
  function defaultIsPidAlive(pid) {
@@ -13576,7 +13801,7 @@ function sleep3(ms) {
13576
13801
  }
13577
13802
  function readLockMeta(lockPath) {
13578
13803
  try {
13579
- const raw = fs23.readFileSync(lockPath, "utf-8");
13804
+ const raw = fs25.readFileSync(lockPath, "utf-8");
13580
13805
  const parsed = JSON.parse(raw);
13581
13806
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
13582
13807
  return parsed;
@@ -13595,12 +13820,12 @@ function isLockStale(meta2, opts) {
13595
13820
  }
13596
13821
  function tryAcquireOnce(lockPath, meta2, opts) {
13597
13822
  try {
13598
- fs23.mkdirSync(path24.dirname(lockPath), { recursive: true });
13599
- const fd = fs23.openSync(lockPath, "wx", 384);
13823
+ fs25.mkdirSync(path24.dirname(lockPath), { recursive: true });
13824
+ const fd = fs25.openSync(lockPath, "wx", 384);
13600
13825
  try {
13601
- fs23.writeSync(fd, JSON.stringify(meta2));
13826
+ fs25.writeSync(fd, JSON.stringify(meta2));
13602
13827
  } finally {
13603
- fs23.closeSync(fd);
13828
+ fs25.closeSync(fd);
13604
13829
  }
13605
13830
  return true;
13606
13831
  } catch (err) {
@@ -13610,14 +13835,14 @@ function tryAcquireOnce(lockPath, meta2, opts) {
13610
13835
  const existing = readLockMeta(lockPath);
13611
13836
  if (existing === void 0) {
13612
13837
  try {
13613
- fs23.unlinkSync(lockPath);
13838
+ fs25.unlinkSync(lockPath);
13614
13839
  } catch {
13615
13840
  }
13616
13841
  return tryAcquireOnce(lockPath, meta2, opts);
13617
13842
  }
13618
13843
  if (isLockStale(existing, opts)) {
13619
13844
  try {
13620
- fs23.unlinkSync(lockPath);
13845
+ fs25.unlinkSync(lockPath);
13621
13846
  } catch {
13622
13847
  }
13623
13848
  return tryAcquireOnce(lockPath, meta2, opts);
@@ -13646,7 +13871,7 @@ async function acquireSourceLock(clonePath, options = {}) {
13646
13871
  lockPath,
13647
13872
  release: () => {
13648
13873
  try {
13649
- fs23.unlinkSync(lockPath);
13874
+ fs25.unlinkSync(lockPath);
13650
13875
  } catch {
13651
13876
  }
13652
13877
  }
@@ -13685,17 +13910,475 @@ var init_source_lock = __esm({
13685
13910
  }
13686
13911
  });
13687
13912
 
13688
- // ../core/dist/skill-sync/engine.js
13689
- import * as fs24 from "node:fs";
13913
+ // ../core/dist/skill-sync/settings-json-lock.js
13914
+ import * as fs26 from "node:fs";
13690
13915
  import * as os16 from "node:os";
13691
13916
  import * as path25 from "node:path";
13917
+ function defaultSettingsJsonLockPath() {
13918
+ const stateDir = process.env["OLAM_STATE_DIR"] ?? path25.join(os16.homedir(), ".olam", "state");
13919
+ return path25.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
13920
+ }
13921
+ function defaultIsPidAlive2(pid) {
13922
+ try {
13923
+ process.kill(pid, 0);
13924
+ return true;
13925
+ } catch (err) {
13926
+ const code = err.code;
13927
+ return code === "EPERM";
13928
+ }
13929
+ }
13930
+ function sleep4(ms) {
13931
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
13932
+ }
13933
+ function readLockMeta2(lockPath) {
13934
+ try {
13935
+ const raw = fs26.readFileSync(lockPath, "utf-8");
13936
+ const parsed = JSON.parse(raw);
13937
+ if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
13938
+ return parsed;
13939
+ }
13940
+ } catch {
13941
+ }
13942
+ return void 0;
13943
+ }
13944
+ function isLockStale2(meta2, opts) {
13945
+ const ageMs = opts.now - meta2.timestamp;
13946
+ if (ageMs < opts.staleLockMs / 2)
13947
+ return false;
13948
+ if (meta2.hostname !== os16.hostname()) {
13949
+ return ageMs > opts.staleLockMs * 2;
13950
+ }
13951
+ if (!opts.isPidAlive(meta2.pid))
13952
+ return true;
13953
+ return ageMs > opts.staleLockMs;
13954
+ }
13955
+ function tryAcquireOnce2(lockPath, meta2, opts) {
13956
+ for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
13957
+ try {
13958
+ fs26.mkdirSync(path25.dirname(lockPath), { recursive: true });
13959
+ const fd = fs26.openSync(lockPath, "wx", 384);
13960
+ try {
13961
+ fs26.writeSync(fd, JSON.stringify(meta2));
13962
+ } finally {
13963
+ fs26.closeSync(fd);
13964
+ }
13965
+ return true;
13966
+ } catch (err) {
13967
+ const code = err.code;
13968
+ if (code !== "EEXIST")
13969
+ throw err;
13970
+ }
13971
+ if (attempt >= MAX_STEAL_ATTEMPTS) {
13972
+ return false;
13973
+ }
13974
+ const existing = readLockMeta2(lockPath);
13975
+ const isStale = existing === void 0 || isLockStale2(existing, opts);
13976
+ if (!isStale) {
13977
+ return false;
13978
+ }
13979
+ const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
13980
+ try {
13981
+ fs26.renameSync(lockPath, victimPath);
13982
+ try {
13983
+ fs26.unlinkSync(victimPath);
13984
+ } catch {
13985
+ }
13986
+ } catch (err) {
13987
+ const code = err.code;
13988
+ if (code !== "ENOENT")
13989
+ throw err;
13990
+ }
13991
+ }
13992
+ return false;
13993
+ }
13994
+ async function acquireSettingsJsonLock(options = {}) {
13995
+ const lockPath = options.lockPath ?? defaultSettingsJsonLockPath();
13996
+ const acquireTimeoutMs = options.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS2;
13997
+ const staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS2;
13998
+ const now = options.now ?? Date.now;
13999
+ const isPidAlive2 = options.isPidAlive ?? defaultIsPidAlive2;
14000
+ const deadline = now() + acquireTimeoutMs;
14001
+ let backoffMs = 25;
14002
+ while (true) {
14003
+ const meta2 = {
14004
+ pid: process.pid,
14005
+ hostname: os16.hostname(),
14006
+ timestamp: now(),
14007
+ ...options.reason ? { reason: options.reason } : {}
14008
+ };
14009
+ const acquired = tryAcquireOnce2(lockPath, meta2, { now: now(), staleLockMs, isPidAlive: isPidAlive2 });
14010
+ if (acquired) {
14011
+ return {
14012
+ lockPath,
14013
+ release: () => {
14014
+ try {
14015
+ fs26.unlinkSync(lockPath);
14016
+ } catch {
14017
+ }
14018
+ }
14019
+ };
14020
+ }
14021
+ if (now() >= deadline) {
14022
+ const existing = readLockMeta2(lockPath);
14023
+ const held = existing ? `(held by pid ${existing.pid} on ${existing.hostname}, since ${new Date(existing.timestamp).toISOString()})` : "(holder unknown)";
14024
+ throw new SettingsJsonLockError(`failed to acquire settings.json lock at ${lockPath} within ${acquireTimeoutMs}ms ${held}`);
14025
+ }
14026
+ await sleep4(Math.min(backoffMs, 200));
14027
+ backoffMs = Math.min(backoffMs * 2, 200);
14028
+ }
14029
+ }
14030
+ async function withSettingsJsonLock(fn, options) {
14031
+ const { release } = await acquireSettingsJsonLock(options);
14032
+ try {
14033
+ return await fn();
14034
+ } finally {
14035
+ release();
14036
+ }
14037
+ }
14038
+ var SETTINGS_JSON_LOCK_FILENAME, DEFAULT_ACQUIRE_TIMEOUT_MS2, DEFAULT_STALE_LOCK_MS2, SettingsJsonLockError, MAX_STEAL_ATTEMPTS;
14039
+ var init_settings_json_lock = __esm({
14040
+ "../core/dist/skill-sync/settings-json-lock.js"() {
14041
+ "use strict";
14042
+ SETTINGS_JSON_LOCK_FILENAME = ".settings-json.lock";
14043
+ DEFAULT_ACQUIRE_TIMEOUT_MS2 = 1e4;
14044
+ DEFAULT_STALE_LOCK_MS2 = 5 * 6e4;
14045
+ SettingsJsonLockError = class extends Error {
14046
+ constructor(message) {
14047
+ super(message);
14048
+ this.name = "SettingsJsonLockError";
14049
+ }
14050
+ };
14051
+ MAX_STEAL_ATTEMPTS = 3;
14052
+ }
14053
+ });
14054
+
14055
+ // ../core/dist/services-status/memory-probe.js
14056
+ async function probeMemoryBridge(opts = {}) {
14057
+ const port2 = opts.port ?? DEFAULT_MEMORY_PORT;
14058
+ const healthPath = opts.healthPath ?? DEFAULT_HEALTH_PATH;
14059
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
14060
+ const url2 = `http://127.0.0.1:${port2}${healthPath}`;
14061
+ const t0 = Date.now();
14062
+ try {
14063
+ const res = await fetch(url2, {
14064
+ signal: AbortSignal.timeout(timeoutMs),
14065
+ // CP3 LOW fix: refuse to follow redirects. A local attacker
14066
+ // controlling the bridge port (or a misconfigured bridge
14067
+ // returning 3xx) could redirect to an external URL; default
14068
+ // `redirect: 'follow'` would leak timing + reachability.
14069
+ redirect: "error"
14070
+ });
14071
+ await res.text().catch(() => "");
14072
+ const latencyMs = Date.now() - t0;
14073
+ if (res.ok) {
14074
+ return { up: true, latencyMs };
14075
+ }
14076
+ return {
14077
+ up: false,
14078
+ latencyMs,
14079
+ detail: `http ${res.status}`
14080
+ };
14081
+ } catch (err) {
14082
+ const latencyMs = Date.now() - t0;
14083
+ const code = err?.code;
14084
+ const name = err?.name;
14085
+ if (name === "AbortError" || name === "TimeoutError") {
14086
+ return { up: false, latencyMs, detail: `timeout after ${timeoutMs}ms` };
14087
+ }
14088
+ if (code === "ECONNREFUSED") {
14089
+ return { up: false, latencyMs, detail: "connection refused (bridge not running)" };
14090
+ }
14091
+ return {
14092
+ up: false,
14093
+ latencyMs,
14094
+ detail: err instanceof Error ? err.message : String(err)
14095
+ };
14096
+ }
14097
+ }
14098
+ var DEFAULT_TIMEOUT_MS3, DEFAULT_MEMORY_PORT, DEFAULT_HEALTH_PATH;
14099
+ var init_memory_probe = __esm({
14100
+ "../core/dist/services-status/memory-probe.js"() {
14101
+ "use strict";
14102
+ DEFAULT_TIMEOUT_MS3 = 2e3;
14103
+ DEFAULT_MEMORY_PORT = 3111;
14104
+ DEFAULT_HEALTH_PATH = "/agentmemory/livez";
14105
+ }
14106
+ });
14107
+
14108
+ // ../core/dist/services-status/index.js
14109
+ var init_services_status = __esm({
14110
+ "../core/dist/services-status/index.js"() {
14111
+ "use strict";
14112
+ init_memory_probe();
14113
+ }
14114
+ });
14115
+
14116
+ // ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
14117
+ import * as crypto5 from "node:crypto";
14118
+ import * as fs27 from "node:fs";
14119
+ import * as os17 from "node:os";
14120
+ import * as path26 from "node:path";
14121
+ function migrationSnapshotsDir2() {
14122
+ const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
14123
+ if (override && override.length > 0)
14124
+ return override;
14125
+ return path26.join(os17.homedir(), ".olam", "state", "migration-snapshots");
14126
+ }
14127
+ function writeMetaHooksSnapshot(originalSettings) {
14128
+ const snapshot = {
14129
+ schemaVersion: META_HOOKS_SNAPSHOT_SCHEMA_VERSION,
14130
+ takenAt: (/* @__PURE__ */ new Date()).toISOString(),
14131
+ namespace: "meta-hooks",
14132
+ originalSettings
14133
+ };
14134
+ const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
14135
+ const dir = migrationSnapshotsDir2();
14136
+ fs27.mkdirSync(dir, { recursive: true });
14137
+ const stamp = validated.takenAt.replace(/[:.]/g, "-");
14138
+ const rand = crypto5.randomBytes(3).toString("hex");
14139
+ const file = path26.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
14140
+ fs27.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
14141
+ return file;
14142
+ }
14143
+ var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
14144
+ var init_meta_hooks_migration_snapshot = __esm({
14145
+ "../core/dist/skill-sources/meta-hooks-migration-snapshot.js"() {
14146
+ "use strict";
14147
+ init_v3();
14148
+ META_HOOKS_SNAPSHOT_SCHEMA_VERSION = 1;
14149
+ META_HOOKS_SNAPSHOT_PREFIX = "meta-hooks-";
14150
+ SettingsLooseSchema = external_exports.record(external_exports.unknown());
14151
+ MetaHooksMigrationSnapshotSchema = external_exports.object({
14152
+ schemaVersion: external_exports.literal(META_HOOKS_SNAPSHOT_SCHEMA_VERSION),
14153
+ takenAt: external_exports.string().min(1),
14154
+ namespace: external_exports.literal("meta-hooks"),
14155
+ /**
14156
+ * Full settings.json content captured before injection. Reverting
14157
+ * writes this back verbatim. May be `null` when no settings.json
14158
+ * existed pre-injection (operator's first sync wrote a fresh one);
14159
+ * revert in that case deletes the file.
14160
+ */
14161
+ originalSettings: external_exports.union([SettingsLooseSchema, external_exports.null()])
14162
+ });
14163
+ }
14164
+ });
14165
+
14166
+ // ../core/dist/skill-sync/atlas-hook-strip.js
14167
+ function isStripCommand(command) {
14168
+ for (const sentinel of OLAM_META_SENTINELS_GUARDED) {
14169
+ if (command.includes(sentinel))
14170
+ return { match: false };
14171
+ }
14172
+ for (const pattern of AGENTMEMORY_SCRIPT_PATTERNS) {
14173
+ if (command.includes(pattern))
14174
+ return { match: true, pattern };
14175
+ }
14176
+ return { match: false };
14177
+ }
14178
+ function findStripCandidates(settings) {
14179
+ const stages = ["PreToolUse", "PostToolUse"];
14180
+ const out = [];
14181
+ for (const stage of stages) {
14182
+ const matchers = settings.hooks?.[stage];
14183
+ if (!Array.isArray(matchers))
14184
+ continue;
14185
+ for (let mi = 0; mi < matchers.length; mi += 1) {
14186
+ const matcher = matchers[mi];
14187
+ const inner = Array.isArray(matcher.hooks) ? matcher.hooks : [];
14188
+ for (let ii = 0; ii < inner.length; ii += 1) {
14189
+ const cmd = inner[ii]?.command;
14190
+ if (typeof cmd !== "string")
14191
+ continue;
14192
+ const verdict = isStripCommand(cmd);
14193
+ if (verdict.match) {
14194
+ out.push({
14195
+ stage,
14196
+ matcherIndex: mi,
14197
+ innerIndex: ii,
14198
+ command: cmd,
14199
+ matcher: matcher.matcher,
14200
+ matchedPattern: verdict.pattern
14201
+ });
14202
+ }
14203
+ }
14204
+ }
14205
+ }
14206
+ return out;
14207
+ }
14208
+ function applyStrip(settings, candidates) {
14209
+ if (candidates.length === 0) {
14210
+ return { nextSettings: settings, removedCount: 0 };
14211
+ }
14212
+ const stripByStageMatcher = /* @__PURE__ */ new Map();
14213
+ for (const c of candidates) {
14214
+ const key = `${c.stage}:${c.matcherIndex}`;
14215
+ if (!stripByStageMatcher.has(key))
14216
+ stripByStageMatcher.set(key, /* @__PURE__ */ new Set());
14217
+ stripByStageMatcher.get(key).add(c.innerIndex);
14218
+ }
14219
+ const nextHooks = { ...settings.hooks ?? {} };
14220
+ const stages = ["PreToolUse", "PostToolUse"];
14221
+ for (const stage of stages) {
14222
+ const matchers = settings.hooks?.[stage];
14223
+ if (!Array.isArray(matchers))
14224
+ continue;
14225
+ const nextMatchers = [];
14226
+ for (let mi = 0; mi < matchers.length; mi += 1) {
14227
+ const matcher = matchers[mi];
14228
+ const innerHooks = Array.isArray(matcher.hooks) ? matcher.hooks : [];
14229
+ const stripIdx = stripByStageMatcher.get(`${stage}:${mi}`);
14230
+ const keptInner = stripIdx === void 0 ? innerHooks : innerHooks.filter((_, ii) => !stripIdx.has(ii));
14231
+ if (keptInner.length === innerHooks.length) {
14232
+ nextMatchers.push(matcher);
14233
+ } else if (keptInner.length === 0) {
14234
+ } else {
14235
+ nextMatchers.push({ ...matcher, hooks: keptInner });
14236
+ }
14237
+ }
14238
+ if (nextMatchers.length === 0) {
14239
+ delete nextHooks[stage];
14240
+ } else {
14241
+ nextHooks[stage] = nextMatchers;
14242
+ }
14243
+ }
14244
+ const next = { ...settings };
14245
+ if (Object.keys(nextHooks).length === 0) {
14246
+ delete next.hooks;
14247
+ } else {
14248
+ next.hooks = nextHooks;
14249
+ }
14250
+ return { nextSettings: next, removedCount: candidates.length };
14251
+ }
14252
+ var AGENTMEMORY_SCRIPT_PATTERNS, OLAM_META_SENTINELS_GUARDED;
14253
+ var init_atlas_hook_strip = __esm({
14254
+ "../core/dist/skill-sync/atlas-hook-strip.js"() {
14255
+ "use strict";
14256
+ init_memory_recall();
14257
+ init_memory_classify();
14258
+ AGENTMEMORY_SCRIPT_PATTERNS = [
14259
+ "agentmemory-recall-trigger.mjs",
14260
+ "agentmemory-classify-queue.mjs"
14261
+ ];
14262
+ OLAM_META_SENTINELS_GUARDED = [
14263
+ OLAM_META_MEMORY_RECALL_SENTINEL,
14264
+ OLAM_META_MEMORY_CLASSIFY_SENTINEL
14265
+ ];
14266
+ }
14267
+ });
14268
+
14269
+ // ../core/dist/skill-sync/meta-hook-injector.js
14270
+ function decideTargetBlocks(opts) {
14271
+ const mode = opts.mode ?? "auto";
14272
+ const disabled = new Set(opts.disabledBlocks ?? []);
14273
+ if (mode === "never")
14274
+ return /* @__PURE__ */ new Set();
14275
+ const wantMemory = mode === "always" || opts.servicesStatus.memory;
14276
+ const target = /* @__PURE__ */ new Set();
14277
+ if (wantMemory && !disabled.has("memory-recall"))
14278
+ target.add("memory-recall");
14279
+ if (wantMemory && !disabled.has("memory-classify"))
14280
+ target.add("memory-classify");
14281
+ return target;
14282
+ }
14283
+ function injectMetaHooks(opts) {
14284
+ const target = decideTargetBlocks(opts);
14285
+ let working = JSON.parse(JSON.stringify(opts.currentSettings ?? {}));
14286
+ const blocksAdded = [];
14287
+ const blocksRemoved = [];
14288
+ const memoryRecallPresent = hasMemoryRecallBlock(working);
14289
+ if (target.has("memory-recall")) {
14290
+ if (!memoryRecallPresent) {
14291
+ working = appendBlock(working, OLAM_META_MEMORY_RECALL_STAGE, buildMemoryRecallHookEntry());
14292
+ blocksAdded.push("memory-recall");
14293
+ }
14294
+ } else {
14295
+ if (memoryRecallPresent) {
14296
+ const r = computeMemoryRecallUninstall(working);
14297
+ if (r.status === "removed" && r.settingsAfter) {
14298
+ working = r.settingsAfter;
14299
+ blocksRemoved.push("memory-recall");
14300
+ }
14301
+ }
14302
+ }
14303
+ const memoryClassifyPresent = hasMemoryClassifyBlock(working);
14304
+ if (target.has("memory-classify")) {
14305
+ if (!memoryClassifyPresent) {
14306
+ working = appendBlock(working, OLAM_META_MEMORY_CLASSIFY_STAGE, buildMemoryClassifyHookEntry());
14307
+ blocksAdded.push("memory-classify");
14308
+ }
14309
+ } else {
14310
+ if (memoryClassifyPresent) {
14311
+ const r = computeMemoryClassifyUninstall(working);
14312
+ if (r.status === "removed" && r.settingsAfter) {
14313
+ working = r.settingsAfter;
14314
+ blocksRemoved.push("memory-classify");
14315
+ }
14316
+ }
14317
+ }
14318
+ return {
14319
+ nextSettings: working,
14320
+ blocksAdded,
14321
+ blocksRemoved,
14322
+ mode: opts.mode ?? "auto"
14323
+ };
14324
+ }
14325
+ function hasMemoryRecallBlock(settings) {
14326
+ const entries = settings.hooks?.PreToolUse;
14327
+ if (!Array.isArray(entries))
14328
+ return false;
14329
+ for (const matcher of entries) {
14330
+ const inner = matcher?.hooks ?? [];
14331
+ if (!Array.isArray(inner))
14332
+ continue;
14333
+ for (const h of inner) {
14334
+ if (typeof h?.command === "string" && matchMemoryRecallSentinel(h.command))
14335
+ return true;
14336
+ }
14337
+ }
14338
+ return false;
14339
+ }
14340
+ function hasMemoryClassifyBlock(settings) {
14341
+ const entries = settings.hooks?.PostToolUse;
14342
+ if (!Array.isArray(entries))
14343
+ return false;
14344
+ for (const matcher of entries) {
14345
+ const inner = matcher?.hooks ?? [];
14346
+ if (!Array.isArray(inner))
14347
+ continue;
14348
+ for (const h of inner) {
14349
+ if (typeof h?.command === "string" && matchMemoryClassifySentinel(h.command))
14350
+ return true;
14351
+ }
14352
+ }
14353
+ return false;
14354
+ }
14355
+ function appendBlock(settings, stage, entry) {
14356
+ const next = { ...settings };
14357
+ const hooks = { ...settings.hooks ?? {} };
14358
+ const stageEntries = Array.isArray(hooks[stage]) ? [...hooks[stage]] : [];
14359
+ stageEntries.push(entry);
14360
+ hooks[stage] = stageEntries;
14361
+ next.hooks = hooks;
14362
+ return next;
14363
+ }
14364
+ var init_meta_hook_injector = __esm({
14365
+ "../core/dist/skill-sync/meta-hook-injector.js"() {
14366
+ "use strict";
14367
+ init_meta_hooks();
14368
+ }
14369
+ });
14370
+
14371
+ // ../core/dist/skill-sync/engine.js
14372
+ import * as fs28 from "node:fs";
14373
+ import * as os18 from "node:os";
14374
+ import * as path27 from "node:path";
13692
14375
  function resolveAtlasUser(override) {
13693
14376
  if (override)
13694
14377
  return override;
13695
- const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path25.join(os16.homedir(), ".claude");
13696
- const f = path25.join(claudeDir2, ".atlas-user");
13697
- if (fs24.existsSync(f)) {
13698
- return fs24.readFileSync(f, "utf-8").trim() || void 0;
14378
+ const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path27.join(os18.homedir(), ".claude");
14379
+ const f = path27.join(claudeDir2, ".atlas-user");
14380
+ if (fs28.existsSync(f)) {
14381
+ return fs28.readFileSync(f, "utf-8").trim() || void 0;
13699
14382
  }
13700
14383
  return void 0;
13701
14384
  }
@@ -13707,7 +14390,7 @@ async function syncSkills(opts = {}) {
13707
14390
  const perSource = [];
13708
14391
  for (const source of sources) {
13709
14392
  const clonePath = skillSourceClonePath(source.id);
13710
- if (!fs24.existsSync(clonePath))
14393
+ if (!fs28.existsSync(clonePath))
13711
14394
  continue;
13712
14395
  const { artifacts, subscription } = await withSourceLock(clonePath, () => {
13713
14396
  const pinRef = projectOverride?.override.pin?.[source.id];
@@ -13743,6 +14426,7 @@ async function syncSkills(opts = {}) {
13743
14426
  projectOverride,
13744
14427
  deploy: void 0,
13745
14428
  merge: void 0,
14429
+ metaHooks: void 0,
13746
14430
  perSource
13747
14431
  };
13748
14432
  if (opts.dryRun) {
@@ -13752,35 +14436,135 @@ async function syncSkills(opts = {}) {
13752
14436
  summary.deploy = deployArtifacts(projectFilteredArtifacts);
13753
14437
  summary.collisions = summary.deploy.collisions;
13754
14438
  summary.merge = mergeSettings({ hookFiles, permissionFiles });
14439
+ if (opts.metaHooks !== "never") {
14440
+ summary.metaHooks = await injectMetaHooksIntoSettings(opts);
14441
+ }
13755
14442
  return summary;
13756
14443
  }
14444
+ async function injectMetaHooksIntoSettings(opts) {
14445
+ const mode = opts.metaHooks ?? "auto";
14446
+ const memoryProbe = await probeMemoryBridge();
14447
+ const servicesStatus = {
14448
+ memory: memoryProbe.up,
14449
+ ...memoryProbe.detail !== void 0 ? { memoryDetail: memoryProbe.detail } : {}
14450
+ };
14451
+ const settingsFile = claudeSettingsPath();
14452
+ let snapshotError;
14453
+ let stripCandidates = [];
14454
+ const result = await withSettingsJsonLock(() => {
14455
+ let currentSettings = {};
14456
+ let settingsExisted = false;
14457
+ if (fs28.existsSync(settingsFile)) {
14458
+ settingsExisted = true;
14459
+ try {
14460
+ const raw = fs28.readFileSync(settingsFile, "utf-8");
14461
+ currentSettings = raw.trim() ? JSON.parse(raw) : {};
14462
+ } catch {
14463
+ try {
14464
+ const raw = fs28.readFileSync(settingsFile);
14465
+ const bakDir = path27.join(path27.dirname(settingsFile), ".malformed-backups");
14466
+ fs28.mkdirSync(bakDir, { recursive: true });
14467
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
14468
+ const bakFile = path27.join(bakDir, `settings.json.malformed.${stamp}.bak`);
14469
+ fs28.writeFileSync(bakFile, raw, { mode: 384 });
14470
+ snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
14471
+ } catch (bakErr) {
14472
+ snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
14473
+ }
14474
+ currentSettings = {};
14475
+ settingsExisted = false;
14476
+ }
14477
+ }
14478
+ stripCandidates = findStripCandidates(currentSettings);
14479
+ const settingsForInject = stripCandidates.length > 0 ? applyStrip(currentSettings, stripCandidates).nextSettings : currentSettings;
14480
+ let configDisabled = [];
14481
+ try {
14482
+ const cfg = readGlobalConfig();
14483
+ configDisabled = cfg.metaHooksDisabled ?? [];
14484
+ } catch {
14485
+ }
14486
+ const disabledBlocks = Array.from(/* @__PURE__ */ new Set([
14487
+ ...configDisabled,
14488
+ ...opts.metaHooksDisabled ?? []
14489
+ ]));
14490
+ const inject = injectMetaHooks({
14491
+ servicesStatus,
14492
+ currentSettings: settingsForInject,
14493
+ mode,
14494
+ ...disabledBlocks.length > 0 ? { disabledBlocks } : {}
14495
+ });
14496
+ const noInjectDelta = inject.blocksAdded.length === 0 && inject.blocksRemoved.length === 0;
14497
+ const noStripDelta = stripCandidates.length === 0;
14498
+ if (noInjectDelta && noStripDelta) {
14499
+ return inject;
14500
+ }
14501
+ let snapshotPath;
14502
+ try {
14503
+ snapshotPath = writeMetaHooksSnapshot(settingsExisted ? currentSettings : null);
14504
+ } catch (err) {
14505
+ snapshotError = err instanceof Error ? err.message : String(err);
14506
+ }
14507
+ if (stripCandidates.length > 0) {
14508
+ try {
14509
+ appendTrustAudit({
14510
+ gitUrl: "internal:olam-meta-hooks",
14511
+ action: "meta-hook-stripped",
14512
+ trustMethod: "none",
14513
+ sourceId: "atlas-toolbox",
14514
+ note: `auto-migration during syncSkills stripped ${stripCandidates.length} agentmemory hook entry(ies)${snapshotPath ? `; snapshot at ${snapshotPath}` : ""}`
14515
+ });
14516
+ } catch {
14517
+ }
14518
+ }
14519
+ fs28.mkdirSync(path27.dirname(settingsFile), { recursive: true });
14520
+ const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
14521
+ fs28.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
14522
+ fs28.renameSync(tmpPath, settingsFile);
14523
+ return inject;
14524
+ }, { reason: `syncSkills meta-hook injection (mode=${mode})` });
14525
+ return {
14526
+ mode: result.mode,
14527
+ servicesStatus,
14528
+ blocksAdded: result.blocksAdded,
14529
+ blocksRemoved: result.blocksRemoved,
14530
+ ...snapshotError !== void 0 ? { snapshotError } : {},
14531
+ ...stripCandidates.length > 0 ? { autoMigrated: { strippedCount: stripCandidates.length, stripCandidates } } : {}
14532
+ };
14533
+ }
13757
14534
  var init_engine = __esm({
13758
14535
  "../core/dist/skill-sync/engine.js"() {
13759
14536
  "use strict";
13760
14537
  init_store2();
13761
14538
  init_clone();
14539
+ init_store();
13762
14540
  init_artifact_resolver();
13763
14541
  init_symlink_deployer();
13764
14542
  init_settings_merger();
13765
14543
  init_per_project_override();
13766
14544
  init_source_lock();
14545
+ init_settings_json_lock();
14546
+ init_services_status();
14547
+ init_meta_hooks_migration_snapshot();
14548
+ init_trust_audit_log();
14549
+ init_atlas_hook_strip();
14550
+ init_meta_hook_injector();
13767
14551
  }
13768
14552
  });
13769
14553
 
13770
14554
  // ../core/dist/skill-sync/shadow-backup-manager.js
13771
- import * as fs25 from "node:fs";
13772
- import * as path26 from "node:path";
14555
+ import * as fs29 from "node:fs";
14556
+ import * as path28 from "node:path";
13773
14557
  function listShadowBackups(opts = {}) {
13774
14558
  const claude = opts.claudeDirOverride ?? claudeDir();
13775
14559
  const now = opts.now ?? Date.now();
13776
14560
  const out = [];
13777
14561
  for (const bucket of SHADOW_BACKUP_BUCKETS) {
13778
- const bucketDir = path26.join(claude, bucket);
13779
- if (!fs25.existsSync(bucketDir))
14562
+ const bucketDir = path28.join(claude, bucket);
14563
+ if (!fs29.existsSync(bucketDir))
13780
14564
  continue;
13781
14565
  let entries;
13782
14566
  try {
13783
- entries = fs25.readdirSync(bucketDir);
14567
+ entries = fs29.readdirSync(bucketDir);
13784
14568
  } catch {
13785
14569
  continue;
13786
14570
  }
@@ -13791,10 +14575,10 @@ function listShadowBackups(opts = {}) {
13791
14575
  const epochSeconds = Number.parseInt(match[1], 10);
13792
14576
  if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
13793
14577
  continue;
13794
- const full = path26.join(bucketDir, name);
14578
+ const full = path28.join(bucketDir, name);
13795
14579
  let sizeBytes = 0;
13796
14580
  try {
13797
- const st = fs25.statSync(full);
14581
+ const st = fs29.statSync(full);
13798
14582
  if (st.isDirectory())
13799
14583
  continue;
13800
14584
  sizeBytes = st.size;
@@ -13807,7 +14591,7 @@ function listShadowBackups(opts = {}) {
13807
14591
  bucket,
13808
14592
  basename: name,
13809
14593
  originalBasename,
13810
- originalPath: path26.join(bucketDir, originalBasename),
14594
+ originalPath: path28.join(bucketDir, originalBasename),
13811
14595
  epochSeconds,
13812
14596
  ageMs: now - epochSeconds * 1e3,
13813
14597
  sizeBytes
@@ -13850,7 +14634,7 @@ function pruneShadowBackups(opts) {
13850
14634
  }
13851
14635
  if (!opts.dryRun) {
13852
14636
  try {
13853
- fs25.unlinkSync(b.path);
14637
+ fs29.unlinkSync(b.path);
13854
14638
  } catch {
13855
14639
  skipped.push(b);
13856
14640
  continue;
@@ -13861,24 +14645,24 @@ function pruneShadowBackups(opts) {
13861
14645
  return { deleted, skipped };
13862
14646
  }
13863
14647
  function restoreShadowBackup(opts) {
13864
- const abs = path26.resolve(opts.backupPath);
13865
- if (!fs25.existsSync(abs)) {
14648
+ const abs = path28.resolve(opts.backupPath);
14649
+ if (!fs29.existsSync(abs)) {
13866
14650
  throw new Error(`backup file not found: ${abs}`);
13867
14651
  }
13868
- const basename6 = path26.basename(abs);
14652
+ const basename6 = path28.basename(abs);
13869
14653
  const match = SHADOW_BACKUP_SUFFIX_RE.exec(basename6);
13870
14654
  if (!match) {
13871
14655
  throw new Error(`not a shadow-backup file (basename "${basename6}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
13872
14656
  }
13873
14657
  const originalBasename = basename6.slice(0, basename6.length - match[0].length);
13874
- const originalPath = path26.join(path26.dirname(abs), originalBasename);
13875
- if (fs25.existsSync(originalPath) && !opts.force) {
14658
+ const originalPath = path28.join(path28.dirname(abs), originalBasename);
14659
+ if (fs29.existsSync(originalPath) && !opts.force) {
13876
14660
  throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
13877
14661
  }
13878
- if (opts.force && fs25.existsSync(originalPath)) {
13879
- fs25.unlinkSync(originalPath);
14662
+ if (opts.force && fs29.existsSync(originalPath)) {
14663
+ fs29.unlinkSync(originalPath);
13880
14664
  }
13881
- fs25.renameSync(abs, originalPath);
14665
+ fs29.renameSync(abs, originalPath);
13882
14666
  return { restoredTo: originalPath };
13883
14667
  }
13884
14668
  var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
@@ -13892,14 +14676,14 @@ var init_shadow_backup_manager = __esm({
13892
14676
  });
13893
14677
 
13894
14678
  // ../core/dist/skill-sources/doctor-checks.js
13895
- import * as fs26 from "node:fs";
13896
- import * as path27 from "node:path";
13897
- import * as os17 from "node:os";
14679
+ import * as fs30 from "node:fs";
14680
+ import * as path29 from "node:path";
14681
+ import * as os19 from "node:os";
13898
14682
  function claudeDirInternal3() {
13899
14683
  const override = process.env["OLAM_CLAUDE_DIR"];
13900
14684
  if (override && override.length > 0)
13901
14685
  return override;
13902
- return path27.join(os17.homedir(), ".claude");
14686
+ return path29.join(os19.homedir(), ".claude");
13903
14687
  }
13904
14688
  function checkStateFileParse() {
13905
14689
  const filePath = globalConfigPath();
@@ -13908,11 +14692,11 @@ function checkStateFileParse() {
13908
14692
  healthy: true,
13909
14693
  description: `~/.olam state file (${filePath})`
13910
14694
  };
13911
- if (!fs26.existsSync(filePath)) {
14695
+ if (!fs30.existsSync(filePath)) {
13912
14696
  result.details = ["(file does not yet exist \u2014 will be created on first write)"];
13913
14697
  return result;
13914
14698
  }
13915
- const raw = fs26.readFileSync(filePath, "utf-8");
14699
+ const raw = fs30.readFileSync(filePath, "utf-8");
13916
14700
  let parsed;
13917
14701
  try {
13918
14702
  parsed = JSON.parse(raw);
@@ -13922,8 +14706,8 @@ function checkStateFileParse() {
13922
14706
  result.details = [err instanceof Error ? err.message : String(err)];
13923
14707
  result.repair = () => {
13924
14708
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
13925
- fs26.renameSync(filePath, aside);
13926
- fs26.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
14709
+ fs30.renameSync(filePath, aside);
14710
+ fs30.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
13927
14711
  };
13928
14712
  return result;
13929
14713
  }
@@ -13934,7 +14718,7 @@ function checkStateFileParse() {
13934
14718
  result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
13935
14719
  result.repair = () => {
13936
14720
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
13937
- fs26.copyFileSync(filePath, aside);
14721
+ fs30.copyFileSync(filePath, aside);
13938
14722
  const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
13939
14723
  const next = {
13940
14724
  ...base,
@@ -13943,7 +14727,7 @@ function checkStateFileParse() {
13943
14727
  runbooks: [],
13944
14728
  skillSources: []
13945
14729
  };
13946
- fs26.writeFileSync(filePath, JSON.stringify(next, null, 2));
14730
+ fs30.writeFileSync(filePath, JSON.stringify(next, null, 2));
13947
14731
  };
13948
14732
  return result;
13949
14733
  }
@@ -13954,16 +14738,16 @@ function checkDanglingSymlinks() {
13954
14738
  const buckets = ["commands", "agents", "skills", "scripts", "rules"];
13955
14739
  const dangling = [];
13956
14740
  for (const bucket of buckets) {
13957
- const dir = path27.join(claude, bucket);
13958
- if (!fs26.existsSync(dir))
14741
+ const dir = path29.join(claude, bucket);
14742
+ if (!fs30.existsSync(dir))
13959
14743
  continue;
13960
- for (const name of fs26.readdirSync(dir)) {
13961
- const linkPath = path27.join(dir, name);
14744
+ for (const name of fs30.readdirSync(dir)) {
14745
+ const linkPath = path29.join(dir, name);
13962
14746
  try {
13963
- const lst = fs26.lstatSync(linkPath);
14747
+ const lst = fs30.lstatSync(linkPath);
13964
14748
  if (!lst.isSymbolicLink())
13965
14749
  continue;
13966
- if (!fs26.existsSync(linkPath)) {
14750
+ if (!fs30.existsSync(linkPath)) {
13967
14751
  dangling.push(linkPath);
13968
14752
  }
13969
14753
  } catch {
@@ -13981,7 +14765,7 @@ function checkDanglingSymlinks() {
13981
14765
  result.repair = () => {
13982
14766
  for (const p of dangling) {
13983
14767
  try {
13984
- fs26.unlinkSync(p);
14768
+ fs30.unlinkSync(p);
13985
14769
  } catch {
13986
14770
  }
13987
14771
  }
@@ -13996,19 +14780,19 @@ function checkOrphanedSnapshots() {
13996
14780
  healthy: true,
13997
14781
  description: `orphaned migration snapshots under ${dir}`
13998
14782
  };
13999
- if (!fs26.existsSync(dir)) {
14783
+ if (!fs30.existsSync(dir)) {
14000
14784
  return result;
14001
14785
  }
14002
14786
  const orphans = [];
14003
- for (const name of fs26.readdirSync(dir)) {
14787
+ for (const name of fs30.readdirSync(dir)) {
14004
14788
  if (!name.endsWith(".json"))
14005
14789
  continue;
14006
- const full = path27.join(dir, name);
14790
+ const full = path29.join(dir, name);
14007
14791
  try {
14008
- const stat = fs26.statSync(full);
14792
+ const stat = fs30.statSync(full);
14009
14793
  if (!stat.isFile())
14010
14794
  continue;
14011
- const raw = fs26.readFileSync(full, "utf-8");
14795
+ const raw = fs30.readFileSync(full, "utf-8");
14012
14796
  let parsed;
14013
14797
  try {
14014
14798
  parsed = JSON.parse(raw);
@@ -14033,7 +14817,7 @@ function checkOrphanedSnapshots() {
14033
14817
  result.repair = () => {
14034
14818
  for (const o of orphans) {
14035
14819
  try {
14036
- fs26.unlinkSync(o.path);
14820
+ fs30.unlinkSync(o.path);
14037
14821
  } catch {
14038
14822
  }
14039
14823
  }
@@ -14048,12 +14832,12 @@ function checkSentinelDrift() {
14048
14832
  healthy: true,
14049
14833
  description: `olam-skills sentinel block in ${filePath}`
14050
14834
  };
14051
- if (!fs26.existsSync(filePath)) {
14835
+ if (!fs30.existsSync(filePath)) {
14052
14836
  return result;
14053
14837
  }
14054
14838
  let parsed;
14055
14839
  try {
14056
- parsed = JSON.parse(fs26.readFileSync(filePath, "utf-8"));
14840
+ parsed = JSON.parse(fs30.readFileSync(filePath, "utf-8"));
14057
14841
  } catch {
14058
14842
  return result;
14059
14843
  }
@@ -14094,7 +14878,7 @@ function checkSentinelDrift() {
14094
14878
  backupSettings();
14095
14879
  } catch {
14096
14880
  }
14097
- const next = JSON.parse(fs26.readFileSync(filePath, "utf-8"));
14881
+ const next = JSON.parse(fs30.readFileSync(filePath, "utf-8"));
14098
14882
  if (!next.hooks)
14099
14883
  return;
14100
14884
  for (const stage of Object.keys(next.hooks)) {
@@ -14117,7 +14901,7 @@ function checkSentinelDrift() {
14117
14901
  return bad === void 0;
14118
14902
  });
14119
14903
  }
14120
- fs26.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
14904
+ fs30.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
14121
14905
  };
14122
14906
  }
14123
14907
  return result;
@@ -14502,10 +15286,10 @@ function mergeDefs(...defs) {
14502
15286
  function cloneDef(schema) {
14503
15287
  return mergeDefs(schema._zod.def);
14504
15288
  }
14505
- function getElementAtPath(obj, path44) {
14506
- if (!path44)
15289
+ function getElementAtPath(obj, path46) {
15290
+ if (!path46)
14507
15291
  return obj;
14508
- return path44.reduce((acc, key) => acc?.[key], obj);
15292
+ return path46.reduce((acc, key) => acc?.[key], obj);
14509
15293
  }
14510
15294
  function promiseAllObject(promisesObj) {
14511
15295
  const keys = Object.keys(promisesObj);
@@ -14914,11 +15698,11 @@ function explicitlyAborted(x, startIndex = 0) {
14914
15698
  }
14915
15699
  return false;
14916
15700
  }
14917
- function prefixIssues(path44, issues) {
15701
+ function prefixIssues(path46, issues) {
14918
15702
  return issues.map((iss) => {
14919
15703
  var _a3;
14920
15704
  (_a3 = iss).path ?? (_a3.path = []);
14921
- iss.path.unshift(path44);
15705
+ iss.path.unshift(path46);
14922
15706
  return iss;
14923
15707
  });
14924
15708
  }
@@ -15065,16 +15849,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
15065
15849
  }
15066
15850
  function formatError(error2, mapper = (issue2) => issue2.message) {
15067
15851
  const fieldErrors = { _errors: [] };
15068
- const processError = (error3, path44 = []) => {
15852
+ const processError = (error3, path46 = []) => {
15069
15853
  for (const issue2 of error3.issues) {
15070
15854
  if (issue2.code === "invalid_union" && issue2.errors.length) {
15071
- issue2.errors.map((issues) => processError({ issues }, [...path44, ...issue2.path]));
15855
+ issue2.errors.map((issues) => processError({ issues }, [...path46, ...issue2.path]));
15072
15856
  } else if (issue2.code === "invalid_key") {
15073
- processError({ issues: issue2.issues }, [...path44, ...issue2.path]);
15857
+ processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
15074
15858
  } else if (issue2.code === "invalid_element") {
15075
- processError({ issues: issue2.issues }, [...path44, ...issue2.path]);
15859
+ processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
15076
15860
  } else {
15077
- const fullpath = [...path44, ...issue2.path];
15861
+ const fullpath = [...path46, ...issue2.path];
15078
15862
  if (fullpath.length === 0) {
15079
15863
  fieldErrors._errors.push(mapper(issue2));
15080
15864
  } else {
@@ -25713,8 +26497,8 @@ var AuthClient = class {
25713
26497
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
25714
26498
  }
25715
26499
  }
25716
- async request(method, path44, body, attempt = 0) {
25717
- const url2 = `${this.baseUrl}${path44}`;
26500
+ async request(method, path46, body, attempt = 0) {
26501
+ const url2 = `${this.baseUrl}${path46}`;
25718
26502
  const controller = new AbortController();
25719
26503
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
25720
26504
  const headers = {};
@@ -25732,7 +26516,7 @@ var AuthClient = class {
25732
26516
  } catch (err) {
25733
26517
  if (attempt < RETRY_COUNT && isTransient(err)) {
25734
26518
  await sleep(RETRY_BACKOFF_MS * (attempt + 1));
25735
- return this.request(method, path44, body, attempt + 1);
26519
+ return this.request(method, path46, body, attempt + 1);
25736
26520
  }
25737
26521
  throw err;
25738
26522
  } finally {
@@ -26583,12 +27367,12 @@ function register3(server, _ctx, _initError) {
26583
27367
  registry2.close();
26584
27368
  }
26585
27369
  try {
26586
- const { default: fs42 } = await import("node:fs");
26587
- const { default: os26 } = await import("node:os");
26588
- const { default: path44 } = await import("node:path");
26589
- const tokenPath = path44.join(os26.homedir(), ".olam", "host-cp.token");
26590
- if (fs42.existsSync(tokenPath)) {
26591
- const token = fs42.readFileSync(tokenPath, "utf-8").trim();
27370
+ const { default: fs46 } = await import("node:fs");
27371
+ const { default: os28 } = await import("node:os");
27372
+ const { default: path46 } = await import("node:path");
27373
+ const tokenPath = path46.join(os28.homedir(), ".olam", "host-cp.token");
27374
+ if (fs46.existsSync(tokenPath)) {
27375
+ const token = fs46.readFileSync(tokenPath, "utf-8").trim();
26592
27376
  await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
26593
27377
  method: "POST",
26594
27378
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
@@ -27008,10 +27792,10 @@ function extractMcpConfig(claudeJsonPath) {
27008
27792
  }
27009
27793
  return { mcpServers, secrets };
27010
27794
  }
27011
- function readOptional(path44) {
27012
- if (!existsSync6(path44)) return null;
27795
+ function readOptional(path46) {
27796
+ if (!existsSync6(path46)) return null;
27013
27797
  try {
27014
- return readFileSync5(path44, "utf8");
27798
+ return readFileSync5(path46, "utf8");
27015
27799
  } catch {
27016
27800
  return null;
27017
27801
  }
@@ -28427,8 +29211,8 @@ var CloudflareProvider = class extends ComputeProvider {
28427
29211
  // -----------------------------------------------------------------------
28428
29212
  // Internal fetch helper
28429
29213
  // -----------------------------------------------------------------------
28430
- async request(path44, method, body) {
28431
- const url2 = `${this.config.workerUrl}${path44}`;
29214
+ async request(path46, method, body) {
29215
+ const url2 = `${this.config.workerUrl}${path46}`;
28432
29216
  const bearer = await this.config.mintToken();
28433
29217
  const headers = {
28434
29218
  Authorization: `Bearer ${bearer}`
@@ -30879,10 +31663,10 @@ async function writeManifest(args) {
30879
31663
  capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
30880
31664
  shots: entries
30881
31665
  };
30882
- const path44 = join13(args.outDir, "manifest.json");
30883
- await writeFile(path44, `${JSON.stringify(manifest, null, 2)}
31666
+ const path46 = join13(args.outDir, "manifest.json");
31667
+ await writeFile(path46, `${JSON.stringify(manifest, null, 2)}
30884
31668
  `, "utf8");
30885
- return { path: path44, manifest };
31669
+ return { path: path46, manifest };
30886
31670
  }
30887
31671
 
30888
31672
  // ../mcp-server/src/tools/_capture/proxy.ts
@@ -31136,9 +31920,9 @@ async function startProxy(opts) {
31136
31920
  const liveCompiled = verified.allowedPaths.map(compileGlob);
31137
31921
  const target = parseRequestTarget(req);
31138
31922
  if (!target) return httpReject(400, "invalid_target");
31139
- const path44 = target.pathname;
31140
- if (!liveCompiled.some((re) => re.test(path44))) {
31141
- return httpReject(403, "outside_allow_list", { path: path44 });
31923
+ const path46 = target.pathname;
31924
+ if (!liveCompiled.some((re) => re.test(path46))) {
31925
+ return httpReject(403, "outside_allow_list", { path: path46 });
31142
31926
  }
31143
31927
  const headerWorld = req.headers[WORLD_ASSERT_HEADER];
31144
31928
  const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
@@ -31501,16 +32285,16 @@ var UnsafeUrlError = class extends Error {
31501
32285
  this.reason = reason;
31502
32286
  }
31503
32287
  };
31504
- async function lookupWithTimeout(hostname2, lookup, timeoutMs) {
32288
+ async function lookupWithTimeout(hostname3, lookup, timeoutMs) {
31505
32289
  let timer;
31506
32290
  const timeout = new Promise((_, reject2) => {
31507
32291
  timer = setTimeout(
31508
- () => reject2(new Error(`dns_lookup_timeout: ${hostname2} (>${timeoutMs}ms)`)),
32292
+ () => reject2(new Error(`dns_lookup_timeout: ${hostname3} (>${timeoutMs}ms)`)),
31509
32293
  timeoutMs
31510
32294
  );
31511
32295
  });
31512
32296
  try {
31513
- return await Promise.race([lookup(hostname2), timeout]);
32297
+ return await Promise.race([lookup(hostname3), timeout]);
31514
32298
  } finally {
31515
32299
  if (timer) clearTimeout(timer);
31516
32300
  }
@@ -31917,14 +32701,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
31917
32701
  await page.waitForTimeout(shot.afterLoadMs);
31918
32702
  }
31919
32703
  const ext = format === "jpeg" ? "jpg" : "png";
31920
- const path44 = join14(outDir, `${shot.name}.${ext}`);
32704
+ const path46 = join14(outDir, `${shot.name}.${ext}`);
31921
32705
  await page.screenshot({
31922
- path: path44,
32706
+ path: path46,
31923
32707
  type: format,
31924
32708
  ...format === "jpeg" ? { quality: jpegQuality } : {},
31925
32709
  fullPage: false
31926
32710
  });
31927
- return { name: shot.name, path: path44, urlRedacted: redactUrl(shot.url), viewport };
32711
+ return { name: shot.name, path: path46, urlRedacted: redactUrl(shot.url), viewport };
31928
32712
  } finally {
31929
32713
  await context.close();
31930
32714
  }
@@ -32368,12 +33152,12 @@ function openUrl(url2) {
32368
33152
  var HOST_CP_URL = "http://127.0.0.1:19000";
32369
33153
  async function readHostCpToken2() {
32370
33154
  try {
32371
- const { default: fs42 } = await import("node:fs");
32372
- const { default: os26 } = await import("node:os");
32373
- const { default: path44 } = await import("node:path");
32374
- const tp = path44.join(os26.homedir(), ".olam", "host-cp.token");
32375
- if (!fs42.existsSync(tp)) return { token: null };
32376
- return { token: fs42.readFileSync(tp, "utf-8").trim() };
33155
+ const { default: fs46 } = await import("node:fs");
33156
+ const { default: os28 } = await import("node:os");
33157
+ const { default: path46 } = await import("node:path");
33158
+ const tp = path46.join(os28.homedir(), ".olam", "host-cp.token");
33159
+ if (!fs46.existsSync(tp)) return { token: null };
33160
+ return { token: fs46.readFileSync(tp, "utf-8").trim() };
32377
33161
  } catch {
32378
33162
  return { token: null };
32379
33163
  }
@@ -32633,9 +33417,9 @@ function register22(server, _ctx, _initError) {
32633
33417
  description: external_exports.string().optional().describe("Optional human-readable description."),
32634
33418
  defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
32635
33419
  },
32636
- async ({ name, path: path44, description, defaultBranch }) => {
33420
+ async ({ name, path: path46, description, defaultBranch }) => {
32637
33421
  try {
32638
- const entry = addRepo({ name, path: path44, description, defaultBranch });
33422
+ const entry = addRepo({ name, path: path46, description, defaultBranch });
32639
33423
  return {
32640
33424
  content: [{
32641
33425
  type: "text",
@@ -32676,9 +33460,9 @@ function register22(server, _ctx, _initError) {
32676
33460
  description: external_exports.string().optional().describe("New description."),
32677
33461
  defaultBranch: external_exports.string().optional().describe("New default branch.")
32678
33462
  },
32679
- async ({ name, path: path44, description, defaultBranch }) => {
33463
+ async ({ name, path: path46, description, defaultBranch }) => {
32680
33464
  try {
32681
- const entry = updateRepo(name, { path: path44, description, defaultBranch });
33465
+ const entry = updateRepo(name, { path: path46, description, defaultBranch });
32682
33466
  return {
32683
33467
  content: [{
32684
33468
  type: "text",
@@ -32699,15 +33483,15 @@ __export(process_port_exports, {
32699
33483
  resolveHostCpToken: () => resolveHostCpToken
32700
33484
  });
32701
33485
  init_v3();
32702
- import fs27 from "node:fs";
32703
- import os18 from "node:os";
32704
- import path28 from "node:path";
33486
+ import fs31 from "node:fs";
33487
+ import os20 from "node:os";
33488
+ import path30 from "node:path";
32705
33489
  var HOST_CP_BASE = "http://127.0.0.1:19000";
32706
33490
  function resolveHostCpToken() {
32707
33491
  const envToken = process.env["OLAM_HOST_CP_TOKEN"];
32708
33492
  if (envToken) return envToken;
32709
- const tokenPath = path28.join(os18.homedir(), ".olam", "host-cp.token");
32710
- if (fs27.existsSync(tokenPath)) return fs27.readFileSync(tokenPath, "utf-8").trim();
33493
+ const tokenPath = path30.join(os20.homedir(), ".olam", "host-cp.token");
33494
+ if (fs31.existsSync(tokenPath)) return fs31.readFileSync(tokenPath, "utf-8").trim();
32711
33495
  return null;
32712
33496
  }
32713
33497
  function tokenMissingError() {
@@ -33139,8 +33923,8 @@ __export(skills_exports, {
33139
33923
  });
33140
33924
  init_v3();
33141
33925
  init_skill_sources();
33142
- import * as fs28 from "node:fs";
33143
- import * as path29 from "node:path";
33926
+ import * as fs32 from "node:fs";
33927
+ import * as path31 from "node:path";
33144
33928
  function asMessage8(err) {
33145
33929
  return err instanceof Error ? err.message : String(err);
33146
33930
  }
@@ -33163,14 +33947,14 @@ function listDeployed() {
33163
33947
  );
33164
33948
  const entries = [];
33165
33949
  for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
33166
- const bucketDir = path29.join(dir, bucket);
33167
- if (!fs28.existsSync(bucketDir)) continue;
33168
- for (const name of fs28.readdirSync(bucketDir)) {
33169
- const full = path29.join(bucketDir, name);
33950
+ const bucketDir = path31.join(dir, bucket);
33951
+ if (!fs32.existsSync(bucketDir)) continue;
33952
+ for (const name of fs32.readdirSync(bucketDir)) {
33953
+ const full = path31.join(bucketDir, name);
33170
33954
  try {
33171
- const stat = fs28.lstatSync(full);
33955
+ const stat = fs32.lstatSync(full);
33172
33956
  if (!stat.isSymbolicLink()) continue;
33173
- const target = fs28.readlinkSync(full);
33957
+ const target = fs32.readlinkSync(full);
33174
33958
  let sourceId;
33175
33959
  for (const [clonePath, id] of sourcePaths.entries()) {
33176
33960
  if (target.startsWith(clonePath)) {
@@ -33266,8 +34050,8 @@ function port() {
33266
34050
  const n = Number.parseInt(env, 10);
33267
34051
  return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
33268
34052
  }
33269
- function url(path44) {
33270
- return `http://127.0.0.1:${port()}${path44}`;
34053
+ function url(path46) {
34054
+ return `http://127.0.0.1:${port()}${path46}`;
33271
34055
  }
33272
34056
  function kgServiceHealthUrl() {
33273
34057
  return url("/health");
@@ -33286,8 +34070,8 @@ var KgServiceUnreachableError = class extends Error {
33286
34070
  this.name = "KgServiceUnreachableError";
33287
34071
  }
33288
34072
  };
33289
- var DEFAULT_TIMEOUT_MS3 = 5e3;
33290
- async function postJson(endpointUrl, body, timeoutMs = DEFAULT_TIMEOUT_MS3) {
34073
+ var DEFAULT_TIMEOUT_MS4 = 5e3;
34074
+ async function postJson(endpointUrl, body, timeoutMs = DEFAULT_TIMEOUT_MS4) {
33291
34075
  let res;
33292
34076
  try {
33293
34077
  res = await fetch(endpointUrl, {
@@ -33305,7 +34089,7 @@ async function postJson(endpointUrl, body, timeoutMs = DEFAULT_TIMEOUT_MS3) {
33305
34089
  }
33306
34090
  return await res.json();
33307
34091
  }
33308
- async function getJson(endpointUrl, timeoutMs = DEFAULT_TIMEOUT_MS3) {
34092
+ async function getJson(endpointUrl, timeoutMs = DEFAULT_TIMEOUT_MS4) {
33309
34093
  let res;
33310
34094
  try {
33311
34095
  res = await fetch(endpointUrl, { signal: AbortSignal.timeout(timeoutMs) });
@@ -33466,9 +34250,9 @@ __export(kg_install_hook_exports, {
33466
34250
  });
33467
34251
  init_v3();
33468
34252
  init_merge_settings();
33469
- import * as fs29 from "node:fs";
33470
- import * as path30 from "node:path";
33471
- import * as os19 from "node:os";
34253
+ import * as fs33 from "node:fs";
34254
+ import * as path32 from "node:path";
34255
+ import * as os21 from "node:os";
33472
34256
 
33473
34257
  // ../core/dist/kg/hook-template.js
33474
34258
  var KG_HOOK_SENTINEL = "kg-service-v2-classifier-hook";
@@ -33518,10 +34302,10 @@ function buildHookMatcherEntry(opts) {
33518
34302
  // ../mcp-server/src/tools/kg-install-hook.ts
33519
34303
  function settingsPathFor2(scope, projectPath) {
33520
34304
  if (scope === "user") {
33521
- return path30.join(os19.homedir(), ".claude", "settings.json");
34305
+ return path32.join(os21.homedir(), ".claude", "settings.json");
33522
34306
  }
33523
34307
  const root = projectPath ?? process.cwd();
33524
- return path30.join(root, ".claude", "settings.json");
34308
+ return path32.join(root, ".claude", "settings.json");
33525
34309
  }
33526
34310
  function register29(server, _ctx, _initError) {
33527
34311
  server.tool(
@@ -33535,12 +34319,12 @@ function register29(server, _ctx, _initError) {
33535
34319
  const scope = params.scope === "user" ? "user" : "project";
33536
34320
  const filePath = settingsPathFor2(scope, params.projectPath);
33537
34321
  try {
33538
- fs29.mkdirSync(path30.dirname(filePath), { recursive: true });
34322
+ fs33.mkdirSync(path32.dirname(filePath), { recursive: true });
33539
34323
  let backupPath = null;
33540
- if (fs29.existsSync(filePath)) {
34324
+ if (fs33.existsSync(filePath)) {
33541
34325
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
33542
34326
  backupPath = `${filePath}.olam-bak.${ts}`;
33543
- fs29.copyFileSync(filePath, backupPath);
34327
+ fs33.copyFileSync(filePath, backupPath);
33544
34328
  }
33545
34329
  const result = mergeHomeSettingsJson(filePath, {
33546
34330
  ensureHook: {
@@ -33551,7 +34335,7 @@ function register29(server, _ctx, _initError) {
33551
34335
  });
33552
34336
  if (result.status === "already-present" && backupPath) {
33553
34337
  try {
33554
- fs29.unlinkSync(backupPath);
34338
+ fs33.unlinkSync(backupPath);
33555
34339
  } catch {
33556
34340
  }
33557
34341
  }
@@ -33595,15 +34379,15 @@ __export(kg_uninstall_hook_exports, {
33595
34379
  register: () => register30
33596
34380
  });
33597
34381
  init_v3();
33598
- import * as fs30 from "node:fs";
33599
- import * as path31 from "node:path";
33600
- import * as os20 from "node:os";
34382
+ import * as fs34 from "node:fs";
34383
+ import * as path33 from "node:path";
34384
+ import * as os22 from "node:os";
33601
34385
  function settingsPathFor3(scope, projectPath) {
33602
34386
  if (scope === "user") {
33603
- return path31.join(os20.homedir(), ".claude", "settings.json");
34387
+ return path33.join(os22.homedir(), ".claude", "settings.json");
33604
34388
  }
33605
34389
  const root = projectPath ?? process.cwd();
33606
- return path31.join(root, ".claude", "settings.json");
34390
+ return path33.join(root, ".claude", "settings.json");
33607
34391
  }
33608
34392
  function dropSentinel(matchers) {
33609
34393
  let changed = false;
@@ -33637,7 +34421,7 @@ function register30(server, _ctx, _initError) {
33637
34421
  const scope = params.scope === "user" ? "user" : "project";
33638
34422
  const filePath = settingsPathFor3(scope, params.projectPath);
33639
34423
  try {
33640
- if (!fs30.existsSync(filePath)) {
34424
+ if (!fs34.existsSync(filePath)) {
33641
34425
  return {
33642
34426
  content: [
33643
34427
  {
@@ -33651,7 +34435,7 @@ function register30(server, _ctx, _initError) {
33651
34435
  ]
33652
34436
  };
33653
34437
  }
33654
- const raw = fs30.readFileSync(filePath, "utf-8");
34438
+ const raw = fs34.readFileSync(filePath, "utf-8");
33655
34439
  const settings = raw.trim() ? JSON.parse(raw) : {};
33656
34440
  const preToolUse = settings.hooks?.PreToolUse;
33657
34441
  if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
@@ -33686,7 +34470,7 @@ function register30(server, _ctx, _initError) {
33686
34470
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
33687
34471
  const backupPath = `${filePath}.olam-bak.${ts}`;
33688
34472
  try {
33689
- fs30.copyFileSync(filePath, backupPath);
34473
+ fs34.copyFileSync(filePath, backupPath);
33690
34474
  } catch {
33691
34475
  }
33692
34476
  const next = {
@@ -33698,7 +34482,7 @@ function register30(server, _ctx, _initError) {
33698
34482
  if (otherStages.length === 0) delete next.hooks;
33699
34483
  else delete next.hooks.PreToolUse;
33700
34484
  }
33701
- fs30.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
34485
+ fs34.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
33702
34486
  return {
33703
34487
  content: [
33704
34488
  {
@@ -33911,11 +34695,11 @@ function assertBetterSqlite3Loadable(deps = {}) {
33911
34695
  init_loader();
33912
34696
 
33913
34697
  // ../core/dist/world/manager.js
33914
- import * as crypto7 from "node:crypto";
34698
+ import * as crypto8 from "node:crypto";
33915
34699
  import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
33916
- import * as fs39 from "node:fs";
33917
- import * as os24 from "node:os";
33918
- import * as path41 from "node:path";
34700
+ import * as fs43 from "node:fs";
34701
+ import * as os26 from "node:os";
34702
+ import * as path43 from "node:path";
33919
34703
 
33920
34704
  // ../core/dist/world/state.js
33921
34705
  var VALID_TRANSITIONS = {
@@ -34011,8 +34795,8 @@ function resolveDevboxImage(config2, tag) {
34011
34795
 
34012
34796
  // ../core/dist/world/worktree.js
34013
34797
  import { execFileSync as execFileSync4 } from "node:child_process";
34014
- import * as fs31 from "node:fs";
34015
- import * as path32 from "node:path";
34798
+ import * as fs35 from "node:fs";
34799
+ import * as path34 from "node:path";
34016
34800
  function resolveGitDir(repo) {
34017
34801
  if (repo.path) {
34018
34802
  return repo.path;
@@ -34022,11 +34806,11 @@ function resolveGitDir(repo) {
34022
34806
  async function createWorktrees(repos, worldId, workspacePath, branch) {
34023
34807
  const created = [];
34024
34808
  for (const repo of repos) {
34025
- const worktreePath = path32.join(workspacePath, repo.name);
34809
+ const worktreePath = path34.join(workspacePath, repo.name);
34026
34810
  const gitDir = resolveGitDir(repo);
34027
34811
  const branchName = branch || `olam/${worldId}`;
34028
34812
  try {
34029
- fs31.mkdirSync(path32.dirname(worktreePath), { recursive: true });
34813
+ fs35.mkdirSync(path34.dirname(worktreePath), { recursive: true });
34030
34814
  execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
34031
34815
  cwd: gitDir,
34032
34816
  stdio: "pipe"
@@ -34059,7 +34843,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
34059
34843
  }
34060
34844
  async function removeWorktrees(repos, workspacePath) {
34061
34845
  for (const repo of repos) {
34062
- const worktreePath = path32.join(workspacePath, repo.name);
34846
+ const worktreePath = path34.join(workspacePath, repo.name);
34063
34847
  let gitDir;
34064
34848
  try {
34065
34849
  gitDir = resolveGitDir(repo);
@@ -34134,12 +34918,12 @@ function removeBranch(repo, branch) {
34134
34918
 
34135
34919
  // ../core/dist/world/kg-overlay.js
34136
34920
  import { execFileSync as execFileSync5 } from "node:child_process";
34137
- import * as fs32 from "node:fs";
34138
- import * as path33 from "node:path";
34921
+ import * as fs36 from "node:fs";
34922
+ import * as path35 from "node:path";
34139
34923
 
34140
34924
  // ../core/dist/kg/storage-paths.js
34141
- import { homedir as homedir20 } from "node:os";
34142
- import { join as join33, resolve as resolve7 } from "node:path";
34925
+ import { homedir as homedir22 } from "node:os";
34926
+ import { join as join35, resolve as resolve7 } from "node:path";
34143
34927
 
34144
34928
  // ../core/dist/world/workspace-name.js
34145
34929
  var InvalidWorkspaceNameError = class extends Error {
@@ -34160,25 +34944,25 @@ function validateWorkspaceName(name) {
34160
34944
 
34161
34945
  // ../core/dist/kg/storage-paths.js
34162
34946
  function olamHome() {
34163
- return process.env.OLAM_HOME ?? join33(homedir20(), ".olam");
34947
+ return process.env.OLAM_HOME ?? join35(homedir22(), ".olam");
34164
34948
  }
34165
34949
  function kgRoot() {
34166
- return join33(olamHome(), "kg");
34950
+ return join35(olamHome(), "kg");
34167
34951
  }
34168
34952
  function worldsRoot() {
34169
- return join33(olamHome(), "worlds");
34953
+ return join35(olamHome(), "worlds");
34170
34954
  }
34171
- function assertWithinPrefix(path44, prefix, label) {
34172
- if (!path44.startsWith(prefix + "/")) {
34173
- throw new Error(`${label} escape: ${path44} not under ${prefix}/`);
34955
+ function assertWithinPrefix(path46, prefix, label) {
34956
+ if (!path46.startsWith(prefix + "/")) {
34957
+ throw new Error(`${label} escape: ${path46} not under ${prefix}/`);
34174
34958
  }
34175
34959
  }
34176
34960
  function kgPristinePath(workspace) {
34177
34961
  validateWorkspaceName(workspace);
34178
34962
  const root = kgRoot();
34179
- const path44 = resolve7(join33(root, workspace));
34180
- assertWithinPrefix(path44, root, "kgPristinePath");
34181
- return path44;
34963
+ const path46 = resolve7(join35(root, workspace));
34964
+ assertWithinPrefix(path46, root, "kgPristinePath");
34965
+ return path46;
34182
34966
  }
34183
34967
  var KG_PATHS_INTERNALS = Object.freeze({
34184
34968
  olamHome,
@@ -34194,10 +34978,10 @@ var KgOverlayError = class extends Error {
34194
34978
  }
34195
34979
  };
34196
34980
  function ensureGitignoreEntry(worldClonePath) {
34197
- const gitignorePath = path33.join(worldClonePath, ".gitignore");
34198
- if (!fs32.existsSync(gitignorePath))
34981
+ const gitignorePath = path35.join(worldClonePath, ".gitignore");
34982
+ if (!fs36.existsSync(gitignorePath))
34199
34983
  return "no-gitignore";
34200
- const content = fs32.readFileSync(gitignorePath, "utf-8");
34984
+ const content = fs36.readFileSync(gitignorePath, "utf-8");
34201
34985
  const lines = content.split("\n").map((l) => l.trim());
34202
34986
  const recognised = /* @__PURE__ */ new Set([
34203
34987
  "graphify-out",
@@ -34212,24 +34996,24 @@ function ensureGitignoreEntry(worldClonePath) {
34212
34996
  const eol = content.includes("\r\n") ? "\r\n" : "\n";
34213
34997
  const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
34214
34998
  const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
34215
- fs32.appendFileSync(gitignorePath, block, "utf-8");
34999
+ fs36.appendFileSync(gitignorePath, block, "utf-8");
34216
35000
  return "appended";
34217
35001
  }
34218
35002
  function createWorldOverlay(opts) {
34219
35003
  const pristineRoot = kgPristinePath(opts.workspace);
34220
- const pristinePath = path33.join(pristineRoot, "graphify-out");
34221
- if (!fs32.existsSync(pristinePath)) {
35004
+ const pristinePath = path35.join(pristineRoot, "graphify-out");
35005
+ if (!fs36.existsSync(pristinePath)) {
34222
35006
  throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
34223
35007
  }
34224
- if (!path33.isAbsolute(opts.worldClonePath)) {
35008
+ if (!path35.isAbsolute(opts.worldClonePath)) {
34225
35009
  throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
34226
35010
  }
34227
- if (!fs32.existsSync(opts.worldClonePath)) {
35011
+ if (!fs36.existsSync(opts.worldClonePath)) {
34228
35012
  throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
34229
35013
  }
34230
- const overlayPath = path33.join(opts.worldClonePath, "graphify-out");
34231
- if (fs32.existsSync(overlayPath)) {
34232
- fs32.rmSync(overlayPath, { recursive: true, force: true });
35014
+ const overlayPath = path35.join(opts.worldClonePath, "graphify-out");
35015
+ if (fs36.existsSync(overlayPath)) {
35016
+ fs36.rmSync(overlayPath, { recursive: true, force: true });
34233
35017
  }
34234
35018
  const useReflink = process.platform === "darwin";
34235
35019
  let strategy;
@@ -34247,7 +35031,7 @@ function createWorldOverlay(opts) {
34247
35031
  } else {
34248
35032
  strategy = "cp-r";
34249
35033
  }
34250
- if (strategy === "cp-r" || !fs32.existsSync(overlayPath)) {
35034
+ if (strategy === "cp-r" || !fs36.existsSync(overlayPath)) {
34251
35035
  try {
34252
35036
  execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
34253
35037
  stdio: ["ignore", "ignore", "pipe"]
@@ -34259,7 +35043,7 @@ function createWorldOverlay(opts) {
34259
35043
  throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
34260
35044
  }
34261
35045
  }
34262
- if (!fs32.existsSync(overlayPath)) {
35046
+ if (!fs36.existsSync(overlayPath)) {
34263
35047
  throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
34264
35048
  }
34265
35049
  const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
@@ -34273,12 +35057,12 @@ function createWorldOverlay(opts) {
34273
35057
 
34274
35058
  // ../core/dist/world/baseline-diff.js
34275
35059
  import { execFileSync as execFileSync6 } from "node:child_process";
34276
- import * as fs33 from "node:fs";
34277
- import * as os21 from "node:os";
34278
- import * as path34 from "node:path";
35060
+ import * as fs37 from "node:fs";
35061
+ import * as os23 from "node:os";
35062
+ import * as path36 from "node:path";
34279
35063
  var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
34280
- function expandHome2(p, homedir26) {
34281
- return p.replace(/^~(?=$|\/|\\)/, homedir26());
35064
+ function expandHome2(p, homedir28) {
35065
+ return p.replace(/^~(?=$|\/|\\)/, homedir28());
34282
35066
  }
34283
35067
  function sanitizeRepoFilename(name) {
34284
35068
  const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -34301,10 +35085,10 @@ ${stderr}`;
34301
35085
  }
34302
35086
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
34303
35087
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
34304
- const homedir26 = deps.homedir ?? (() => os21.homedir());
34305
- const baselineDir = path34.join(workspacePath, ".olam", "baseline");
35088
+ const homedir28 = deps.homedir ?? (() => os23.homedir());
35089
+ const baselineDir = path36.join(workspacePath, ".olam", "baseline");
34306
35090
  try {
34307
- fs33.mkdirSync(baselineDir, { recursive: true });
35091
+ fs37.mkdirSync(baselineDir, { recursive: true });
34308
35092
  } catch (err) {
34309
35093
  const msg = err instanceof Error ? err.message : String(err);
34310
35094
  console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
@@ -34316,9 +35100,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
34316
35100
  if (!repo.path)
34317
35101
  continue;
34318
35102
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
34319
- const outPath = path34.join(baselineDir, filename);
34320
- const repoPath = expandHome2(repo.path, homedir26);
34321
- if (!fs33.existsSync(repoPath)) {
35103
+ const outPath = path36.join(baselineDir, filename);
35104
+ const repoPath = expandHome2(repo.path, homedir28);
35105
+ if (!fs37.existsSync(repoPath)) {
34322
35106
  writeBaselineFile(outPath, `# repo: ${repo.name}
34323
35107
  # (skipped: path ${repoPath} does not exist)
34324
35108
  `);
@@ -34385,7 +35169,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
34385
35169
  }
34386
35170
  function writeBaselineFile(outPath, content) {
34387
35171
  try {
34388
- fs33.writeFileSync(outPath, content);
35172
+ fs37.writeFileSync(outPath, content);
34389
35173
  } catch (err) {
34390
35174
  const msg = err instanceof Error ? err.message : String(err);
34391
35175
  console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
@@ -34393,8 +35177,8 @@ function writeBaselineFile(outPath, content) {
34393
35177
  }
34394
35178
  function stripWorktreeEdits(repos, workspacePath) {
34395
35179
  for (const repo of repos) {
34396
- const worktreePath = path34.join(workspacePath, repo.name);
34397
- if (!fs33.existsSync(worktreePath))
35180
+ const worktreePath = path36.join(workspacePath, repo.name);
35181
+ if (!fs37.existsSync(worktreePath))
34398
35182
  continue;
34399
35183
  try {
34400
35184
  execFileSync6("git", ["checkout", "--", "."], {
@@ -34453,21 +35237,21 @@ function extractStderr(err) {
34453
35237
  }
34454
35238
  function carryUncommittedEdits(repos, workspacePath, deps = {}) {
34455
35239
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
34456
- const homedir26 = deps.homedir ?? (() => os21.homedir());
34457
- const existsSync40 = deps.existsSync ?? ((p) => fs33.existsSync(p));
34458
- const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs33.copyFileSync(src, dest));
34459
- const mkdirSync25 = deps.mkdirSync ?? ((dirPath, opts) => {
34460
- fs33.mkdirSync(dirPath, opts);
35240
+ const homedir28 = deps.homedir ?? (() => os23.homedir());
35241
+ const existsSync43 = deps.existsSync ?? ((p) => fs37.existsSync(p));
35242
+ const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs37.copyFileSync(src, dest));
35243
+ const mkdirSync28 = deps.mkdirSync ?? ((dirPath, opts) => {
35244
+ fs37.mkdirSync(dirPath, opts);
34461
35245
  });
34462
35246
  const plans = [];
34463
35247
  for (const repo of repos) {
34464
35248
  if (!repo.path)
34465
35249
  continue;
34466
- const repoPath = expandHome2(repo.path, homedir26);
34467
- const worktreePath = path34.join(workspacePath, repo.name);
34468
- if (!existsSync40(repoPath))
35250
+ const repoPath = expandHome2(repo.path, homedir28);
35251
+ const worktreePath = path36.join(workspacePath, repo.name);
35252
+ if (!existsSync43(repoPath))
34469
35253
  continue;
34470
- if (!existsSync40(worktreePath)) {
35254
+ if (!existsSync43(worktreePath)) {
34471
35255
  console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
34472
35256
  continue;
34473
35257
  }
@@ -34525,12 +35309,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
34525
35309
  }
34526
35310
  }
34527
35311
  for (const rel of plan.diff.untracked) {
34528
- const src = path34.join(plan.repoPath, rel);
34529
- const dest = path34.join(plan.worktreePath, rel);
34530
- if (!existsSync40(src))
35312
+ const src = path36.join(plan.repoPath, rel);
35313
+ const dest = path36.join(plan.worktreePath, rel);
35314
+ if (!existsSync43(src))
34531
35315
  continue;
34532
35316
  try {
34533
- mkdirSync25(path34.dirname(dest), { recursive: true });
35317
+ mkdirSync28(path36.dirname(dest), { recursive: true });
34534
35318
  copyFileSync9(src, dest);
34535
35319
  } catch (err) {
34536
35320
  const msg = err instanceof Error ? err.message : String(err);
@@ -34556,8 +35340,8 @@ function formatBaselineSummary(result) {
34556
35340
  }
34557
35341
 
34558
35342
  // ../core/dist/world/context-injection.js
34559
- import * as fs34 from "node:fs";
34560
- import * as path35 from "node:path";
35343
+ import * as fs38 from "node:fs";
35344
+ import * as path37 from "node:path";
34561
35345
 
34562
35346
  // ../core/dist/world/templates/_generated.js
34563
35347
  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';
@@ -34567,10 +35351,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
34567
35351
  // ../core/dist/world/context-injection.js
34568
35352
  function injectWorldContext(opts) {
34569
35353
  const { world } = opts;
34570
- const claudeDir2 = path35.join(world.workspacePath, ".claude");
34571
- fs34.mkdirSync(claudeDir2, { recursive: true });
35354
+ const claudeDir2 = path37.join(world.workspacePath, ".claude");
35355
+ fs38.mkdirSync(claudeDir2, { recursive: true });
34572
35356
  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));
34573
- fs34.writeFileSync(path35.join(claudeDir2, "CLAUDE.md"), content);
35357
+ fs38.writeFileSync(path37.join(claudeDir2, "CLAUDE.md"), content);
34574
35358
  writeOlamDocs(world.workspacePath);
34575
35359
  }
34576
35360
  function buildTaskBlock(opts) {
@@ -34644,10 +35428,10 @@ function buildExtraContextBlock(extra) {
34644
35428
  ${extra}`;
34645
35429
  }
34646
35430
  function writeOlamDocs(workspacePath) {
34647
- const docsDir = path35.join(workspacePath, ".olam", "docs");
34648
- fs34.mkdirSync(docsDir, { recursive: true });
34649
- fs34.writeFileSync(path35.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
34650
- fs34.writeFileSync(path35.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
35431
+ const docsDir = path37.join(workspacePath, ".olam", "docs");
35432
+ fs38.mkdirSync(docsDir, { recursive: true });
35433
+ fs38.writeFileSync(path37.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
35434
+ fs38.writeFileSync(path37.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
34651
35435
  }
34652
35436
  function formatTaskSource(ctx) {
34653
35437
  if (ctx.source === "linear" && ctx.ticketId) {
@@ -34661,9 +35445,9 @@ function formatTaskSource(ctx) {
34661
35445
  function hasPlanFile(world) {
34662
35446
  if (world.repos.length === 0)
34663
35447
  return false;
34664
- const plansDir = path35.join(world.workspacePath, world.repos[0], "docs", "plans");
35448
+ const plansDir = path37.join(world.workspacePath, world.repos[0], "docs", "plans");
34665
35449
  try {
34666
- return fs34.existsSync(plansDir) && fs34.readdirSync(plansDir).length > 0;
35450
+ return fs38.existsSync(plansDir) && fs38.readdirSync(plansDir).length > 0;
34667
35451
  } catch {
34668
35452
  return false;
34669
35453
  }
@@ -34891,7 +35675,7 @@ async function installStack(exec, repos, stacks) {
34891
35675
 
34892
35676
  // ../core/dist/world/stack-image.js
34893
35677
  import { execSync as execSync3 } from "node:child_process";
34894
- import * as crypto5 from "node:crypto";
35678
+ import * as crypto6 from "node:crypto";
34895
35679
  var BASE_IMAGE = "olam-devbox";
34896
35680
  var LABEL_PREFIX = "olam.stack-image";
34897
35681
  var MAX_TAG_LENGTH = 128;
@@ -34947,7 +35731,7 @@ function getImageDigest(imageRef) {
34947
35731
  cachedImageDigests.set(imageRef, short);
34948
35732
  return short;
34949
35733
  } catch {
34950
- const fallback = crypto5.createHash("sha256").update(imageRef).digest("hex").slice(0, 16);
35734
+ const fallback = crypto6.createHash("sha256").update(imageRef).digest("hex").slice(0, 16);
34951
35735
  cachedImageDigests.set(imageRef, fallback);
34952
35736
  return fallback;
34953
35737
  }
@@ -34958,7 +35742,7 @@ function getBaseImageDigest() {
34958
35742
  function sanitizeTag(raw) {
34959
35743
  let tag = raw.toLowerCase().replace(/[^a-z0-9._-]/g, "-");
34960
35744
  if (tag.length > MAX_TAG_LENGTH) {
34961
- const hash = crypto5.createHash("sha256").update(raw).digest("hex").slice(0, 12);
35745
+ const hash = crypto6.createHash("sha256").update(raw).digest("hex").slice(0, 12);
34962
35746
  tag = tag.slice(0, MAX_TAG_LENGTH - 13) + "_" + hash;
34963
35747
  }
34964
35748
  return tag;
@@ -35234,26 +36018,26 @@ function shellQuote(s) {
35234
36018
  init_repo_manifest();
35235
36019
 
35236
36020
  // ../core/dist/world/snapshot.js
35237
- import * as crypto6 from "node:crypto";
35238
- import * as fs35 from "node:fs";
35239
- import * as os22 from "node:os";
35240
- import * as path36 from "node:path";
36021
+ import * as crypto7 from "node:crypto";
36022
+ import * as fs39 from "node:fs";
36023
+ import * as os24 from "node:os";
36024
+ import * as path38 from "node:path";
35241
36025
  import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
35242
36026
  import { gunzipSync } from "node:zlib";
35243
36027
  function snapshotsDir() {
35244
- return process.env["OLAM_SNAPSHOTS_DIR"] ?? path36.join(os22.homedir(), ".olam", "snapshots");
36028
+ return process.env["OLAM_SNAPSHOTS_DIR"] ?? path38.join(os24.homedir(), ".olam", "snapshots");
35245
36029
  }
35246
36030
  function snapshotKindDirByWorkspace(workspace, arch, kind) {
35247
- return path36.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
36031
+ return path38.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
35248
36032
  }
35249
36033
  function cleanupLegacyByWorldDir(worldId) {
35250
- const legacyDir = path36.join(snapshotsDir(), worldId);
36034
+ const legacyDir = path38.join(snapshotsDir(), worldId);
35251
36035
  if (worldId === "by-workspace")
35252
36036
  return;
35253
- if (!fs35.existsSync(legacyDir))
36037
+ if (!fs39.existsSync(legacyDir))
35254
36038
  return;
35255
36039
  try {
35256
- fs35.rmSync(legacyDir, { recursive: true, force: true });
36040
+ fs39.rmSync(legacyDir, { recursive: true, force: true });
35257
36041
  } catch {
35258
36042
  }
35259
36043
  }
@@ -35262,7 +36046,7 @@ function manifestPath(tarPath) {
35262
36046
  }
35263
36047
  function hashBuffers(entries) {
35264
36048
  const sorted = [...entries].sort((a, b) => a.path.localeCompare(b.path));
35265
- const hash = crypto6.createHash("sha256");
36049
+ const hash = crypto7.createHash("sha256");
35266
36050
  for (const entry of sorted) {
35267
36051
  hash.update(entry.path);
35268
36052
  hash.update("\0");
@@ -35272,11 +36056,11 @@ function hashBuffers(entries) {
35272
36056
  return hash.digest("hex").slice(0, 12);
35273
36057
  }
35274
36058
  function computeGemsFingerprint(repoDir, imageDigest) {
35275
- const lockfile = path36.join(repoDir, "Gemfile.lock");
35276
- if (!fs35.existsSync(lockfile))
36059
+ const lockfile = path38.join(repoDir, "Gemfile.lock");
36060
+ if (!fs39.existsSync(lockfile))
35277
36061
  return null;
35278
36062
  const entries = [
35279
- { path: "Gemfile.lock", content: fs35.readFileSync(lockfile) }
36063
+ { path: "Gemfile.lock", content: fs39.readFileSync(lockfile) }
35280
36064
  ];
35281
36065
  if (imageDigest) {
35282
36066
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -35286,10 +36070,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
35286
36070
  function computeNodeFingerprint(repoDir, imageDigest) {
35287
36071
  const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
35288
36072
  for (const name of candidates) {
35289
- const lockfile = path36.join(repoDir, name);
35290
- if (fs35.existsSync(lockfile)) {
36073
+ const lockfile = path38.join(repoDir, name);
36074
+ if (fs39.existsSync(lockfile)) {
35291
36075
  const entries = [
35292
- { path: name, content: fs35.readFileSync(lockfile) }
36076
+ { path: name, content: fs39.readFileSync(lockfile) }
35293
36077
  ];
35294
36078
  if (imageDigest) {
35295
36079
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -35308,18 +36092,18 @@ function unpackTarballAtomic(srcPath, destDir) {
35308
36092
  detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
35309
36093
  };
35310
36094
  }
35311
- const parent = path36.dirname(destDir);
35312
- fs35.mkdirSync(parent, { recursive: true });
35313
- const tmpSuffix = `.tmp-${process.pid}-${crypto6.randomBytes(4).toString("hex")}`;
36095
+ const parent = path38.dirname(destDir);
36096
+ fs39.mkdirSync(parent, { recursive: true });
36097
+ const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
35314
36098
  const tmpDir = `${destDir}${tmpSuffix}`;
35315
36099
  try {
35316
- fs35.mkdirSync(tmpDir, { recursive: true });
36100
+ fs39.mkdirSync(tmpDir, { recursive: true });
35317
36101
  execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
35318
- fs35.renameSync(tmpDir, destDir);
36102
+ fs39.renameSync(tmpDir, destDir);
35319
36103
  return { ok: true, entryCount: validation.entries.length };
35320
36104
  } catch (err) {
35321
36105
  try {
35322
- fs35.rmSync(tmpDir, { recursive: true, force: true });
36106
+ fs39.rmSync(tmpDir, { recursive: true, force: true });
35323
36107
  } catch {
35324
36108
  }
35325
36109
  return {
@@ -35330,12 +36114,12 @@ function unpackTarballAtomic(srcPath, destDir) {
35330
36114
  }
35331
36115
  }
35332
36116
  function resolvesWithin(base, target) {
35333
- const resolved = path36.resolve(base, target);
35334
- const baseResolved = path36.resolve(base);
35335
- const rel = path36.relative(baseResolved, resolved);
36117
+ const resolved = path38.resolve(base, target);
36118
+ const baseResolved = path38.resolve(base);
36119
+ const rel = path38.relative(baseResolved, resolved);
35336
36120
  if (rel === "")
35337
36121
  return true;
35338
- return !rel.startsWith("..") && !path36.isAbsolute(rel);
36122
+ return !rel.startsWith("..") && !path38.isAbsolute(rel);
35339
36123
  }
35340
36124
  var TYPE_CHAR_TO_TYPE = {
35341
36125
  "-": "file",
@@ -35385,7 +36169,7 @@ function parseTarListLine(line) {
35385
36169
  function validateHardlinksBinary(tarPath, targetDir) {
35386
36170
  let raw;
35387
36171
  try {
35388
- raw = gunzipSync(fs35.readFileSync(tarPath));
36172
+ raw = gunzipSync(fs39.readFileSync(tarPath));
35389
36173
  } catch {
35390
36174
  return null;
35391
36175
  }
@@ -35400,7 +36184,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
35400
36184
  const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
35401
36185
  const linkNull = block.indexOf(0, 157);
35402
36186
  const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
35403
- if (linkname && (path36.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
36187
+ if (linkname && (path38.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
35404
36188
  return {
35405
36189
  valid: false,
35406
36190
  reason: "hardlink-escape",
@@ -35438,7 +36222,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
35438
36222
  const entry = parseTarListLine(line);
35439
36223
  if (!entry)
35440
36224
  continue;
35441
- if (path36.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
36225
+ if (path38.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
35442
36226
  return {
35443
36227
  valid: false,
35444
36228
  reason: "path-traversal",
@@ -35446,8 +36230,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
35446
36230
  };
35447
36231
  }
35448
36232
  if (entry.type === "symlink" && entry.linkname !== void 0) {
35449
- const symlinkParent = path36.join(targetDir, path36.dirname(entry.name));
35450
- if (path36.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path36.join(path36.dirname(entry.name), entry.linkname))) {
36233
+ const symlinkParent = path38.join(targetDir, path38.dirname(entry.name));
36234
+ if (path38.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path38.join(path38.dirname(entry.name), entry.linkname))) {
35451
36235
  return {
35452
36236
  valid: false,
35453
36237
  reason: "symlink-escape",
@@ -35457,7 +36241,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
35457
36241
  }
35458
36242
  }
35459
36243
  if (entry.type === "hardlink" && entry.linkname !== void 0) {
35460
- if (path36.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
36244
+ if (path38.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
35461
36245
  return {
35462
36246
  valid: false,
35463
36247
  reason: "hardlink-escape",
@@ -35490,8 +36274,8 @@ function restoreSnapshotsForRepos(input) {
35490
36274
  }
35491
36275
  const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
35492
36276
  const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
35493
- const tarPath = path36.join(archDir, tarFilename);
35494
- if (!fs35.existsSync(tarPath)) {
36277
+ const tarPath = path38.join(archDir, tarFilename);
36278
+ if (!fs39.existsSync(tarPath)) {
35495
36279
  outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
35496
36280
  continue;
35497
36281
  }
@@ -35506,9 +36290,9 @@ function restoreSnapshotsForRepos(input) {
35506
36290
  });
35507
36291
  continue;
35508
36292
  }
35509
- const targetDir = path36.join(repo.worktreeDir, targetSubpath);
36293
+ const targetDir = path38.join(repo.worktreeDir, targetSubpath);
35510
36294
  try {
35511
- fs35.rmSync(targetDir, { recursive: true, force: true });
36295
+ fs39.rmSync(targetDir, { recursive: true, force: true });
35512
36296
  } catch {
35513
36297
  }
35514
36298
  const result = unpackTarballAtomic(tarPath, targetDir);
@@ -35521,8 +36305,8 @@ function restoreSnapshotsForRepos(input) {
35521
36305
  fingerprint
35522
36306
  });
35523
36307
  try {
35524
- fs35.rmSync(tarPath, { force: true });
35525
- fs35.rmSync(manifestPath(tarPath), { force: true });
36308
+ fs39.rmSync(tarPath, { force: true });
36309
+ fs39.rmSync(manifestPath(tarPath), { force: true });
35526
36310
  } catch {
35527
36311
  }
35528
36312
  continue;
@@ -35538,10 +36322,10 @@ function restoreSnapshotsForRepos(input) {
35538
36322
  }
35539
36323
  function readManifest(tarPath) {
35540
36324
  const mPath = manifestPath(tarPath);
35541
- if (!fs35.existsSync(mPath))
36325
+ if (!fs39.existsSync(mPath))
35542
36326
  return null;
35543
36327
  try {
35544
- return JSON.parse(fs35.readFileSync(mPath, "utf-8"));
36328
+ return JSON.parse(fs39.readFileSync(mPath, "utf-8"));
35545
36329
  } catch {
35546
36330
  return null;
35547
36331
  }
@@ -35556,17 +36340,17 @@ function isPidAlive(pid) {
35556
36340
  }
35557
36341
  }
35558
36342
  function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
35559
- fs35.mkdirSync(dir, { recursive: true });
35560
- const lockPath = path36.join(dir, EVICT_LOCK_FILENAME);
36343
+ fs39.mkdirSync(dir, { recursive: true });
36344
+ const lockPath = path38.join(dir, EVICT_LOCK_FILENAME);
35561
36345
  let fd;
35562
36346
  try {
35563
- fd = fs35.openSync(lockPath, fs35.constants.O_WRONLY | fs35.constants.O_CREAT | fs35.constants.O_EXCL, 384);
36347
+ fd = fs39.openSync(lockPath, fs39.constants.O_WRONLY | fs39.constants.O_CREAT | fs39.constants.O_EXCL, 384);
35564
36348
  } catch (err) {
35565
36349
  if (err.code !== "EEXIST")
35566
36350
  return 0;
35567
36351
  let holderPid = null;
35568
36352
  try {
35569
- holderPid = parseInt(fs35.readFileSync(lockPath, "utf-8").trim(), 10);
36353
+ holderPid = parseInt(fs39.readFileSync(lockPath, "utf-8").trim(), 10);
35570
36354
  } catch {
35571
36355
  holderPid = null;
35572
36356
  }
@@ -35574,23 +36358,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
35574
36358
  return 0;
35575
36359
  }
35576
36360
  try {
35577
- fs35.unlinkSync(lockPath);
35578
- fd = fs35.openSync(lockPath, fs35.constants.O_WRONLY | fs35.constants.O_CREAT | fs35.constants.O_EXCL, 384);
36361
+ fs39.unlinkSync(lockPath);
36362
+ fd = fs39.openSync(lockPath, fs39.constants.O_WRONLY | fs39.constants.O_CREAT | fs39.constants.O_EXCL, 384);
35579
36363
  } catch {
35580
36364
  return 0;
35581
36365
  }
35582
36366
  }
35583
36367
  try {
35584
- fs35.writeSync(fd, `${process.pid}
36368
+ fs39.writeSync(fd, `${process.pid}
35585
36369
  `);
35586
36370
  } finally {
35587
- fs35.closeSync(fd);
36371
+ fs39.closeSync(fd);
35588
36372
  }
35589
36373
  try {
35590
36374
  return evictOldSnapshots(maxBytes, dir);
35591
36375
  } finally {
35592
36376
  try {
35593
- fs35.unlinkSync(lockPath);
36377
+ fs39.unlinkSync(lockPath);
35594
36378
  } catch {
35595
36379
  }
35596
36380
  }
@@ -35623,16 +36407,16 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
35623
36407
  }
35624
36408
  }
35625
36409
  function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
35626
- if (!fs35.existsSync(dir))
36410
+ if (!fs39.existsSync(dir))
35627
36411
  return 0;
35628
36412
  const allTars = [];
35629
36413
  const walk = (d) => {
35630
- for (const entry of fs35.readdirSync(d, { withFileTypes: true })) {
35631
- const full = path36.join(d, entry.name);
36414
+ for (const entry of fs39.readdirSync(d, { withFileTypes: true })) {
36415
+ const full = path38.join(d, entry.name);
35632
36416
  if (entry.isDirectory()) {
35633
36417
  walk(full);
35634
36418
  } else if (entry.name.endsWith(".tar.gz")) {
35635
- const stat = fs35.statSync(full);
36419
+ const stat = fs39.statSync(full);
35636
36420
  allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
35637
36421
  }
35638
36422
  }
@@ -35647,8 +36431,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
35647
36431
  for (const tar of allTars) {
35648
36432
  if (remaining <= maxBytes)
35649
36433
  break;
35650
- fs35.rmSync(tar.path, { force: true });
35651
- fs35.rmSync(manifestPath(tar.path), { force: true });
36434
+ fs39.rmSync(tar.path, { force: true });
36435
+ fs39.rmSync(manifestPath(tar.path), { force: true });
35652
36436
  freed += tar.size;
35653
36437
  remaining -= tar.size;
35654
36438
  }
@@ -35765,14 +36549,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
35765
36549
 
35766
36550
  // ../core/dist/world/olam-yaml.js
35767
36551
  init_repo_manifest();
35768
- import * as path37 from "node:path";
36552
+ import * as path39 from "node:path";
35769
36553
  import YAML2 from "yaml";
35770
36554
  function enrichReposWithManifests(repos, workspacePath) {
35771
36555
  return repos.map((repo) => {
35772
36556
  if (repo.manifest !== void 0 && repo.manifest !== null) {
35773
36557
  return repo;
35774
36558
  }
35775
- const repoDir = path37.join(workspacePath, repo.name);
36559
+ const repoDir = path39.join(workspacePath, repo.name);
35776
36560
  let manifest = null;
35777
36561
  try {
35778
36562
  manifest = loadRepoManifest(repoDir);
@@ -35787,8 +36571,8 @@ function enrichReposWithManifests(repos, workspacePath) {
35787
36571
  }
35788
36572
 
35789
36573
  // ../core/dist/policies/loader.js
35790
- import * as fs36 from "node:fs";
35791
- import * as path38 from "node:path";
36574
+ import * as fs40 from "node:fs";
36575
+ import * as path40 from "node:path";
35792
36576
  import { parse as parseYaml4 } from "yaml";
35793
36577
  function parseFrontmatter(content) {
35794
36578
  const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
@@ -35808,20 +36592,20 @@ function toStringArray(v) {
35808
36592
  return v.filter((x) => typeof x === "string");
35809
36593
  }
35810
36594
  function loadPolicies(workspaceRoot) {
35811
- const policiesDir = path38.join(workspaceRoot, ".olam", "policies");
35812
- if (!fs36.existsSync(policiesDir))
36595
+ const policiesDir = path40.join(workspaceRoot, ".olam", "policies");
36596
+ if (!fs40.existsSync(policiesDir))
35813
36597
  return [];
35814
36598
  let files;
35815
36599
  try {
35816
- files = fs36.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
36600
+ files = fs40.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
35817
36601
  } catch {
35818
36602
  return [];
35819
36603
  }
35820
36604
  const policies = [];
35821
36605
  for (const file of files) {
35822
- const filePath = path38.join(policiesDir, file);
36606
+ const filePath = path40.join(policiesDir, file);
35823
36607
  try {
35824
- const content = fs36.readFileSync(filePath, "utf8");
36608
+ const content = fs40.readFileSync(filePath, "utf8");
35825
36609
  const parsed = parseFrontmatter(content);
35826
36610
  if (!parsed) {
35827
36611
  console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
@@ -35905,7 +36689,7 @@ var TaskDispatchError = class extends Error {
35905
36689
  }
35906
36690
  };
35907
36691
  var DEFAULT_SLEEP = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
35908
- async function probeHealth(containerName, dockerExec, budgetMs, sleep4) {
36692
+ async function probeHealth(containerName, dockerExec, budgetMs, sleep5) {
35909
36693
  const deadline = Date.now() + budgetMs;
35910
36694
  const cadenceMs = 100;
35911
36695
  let lastErr = "";
@@ -35918,7 +36702,7 @@ async function probeHealth(containerName, dockerExec, budgetMs, sleep4) {
35918
36702
  } catch (err) {
35919
36703
  lastErr = err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200);
35920
36704
  }
35921
- await sleep4(cadenceMs);
36705
+ await sleep5(cadenceMs);
35922
36706
  }
35923
36707
  throw new TaskDispatchError(`container-cp /health did not return 200 within ${budgetMs}ms`, "health-probe", lastErr || "no response");
35924
36708
  }
@@ -35954,9 +36738,9 @@ function composeTaskPrompt(task, policies, formatPoliciesBrief2) {
35954
36738
  ${task}`;
35955
36739
  }
35956
36740
  async function autoDispatchTask(opts) {
35957
- const { containerName, task, policies, dockerExec, healthBudgetMs = 15e3, sleep: sleep4 = DEFAULT_SLEEP, logger: logger2 = console, formatPoliciesBrief: formatPoliciesBrief2 } = opts;
36741
+ const { containerName, task, policies, dockerExec, healthBudgetMs = 15e3, sleep: sleep5 = DEFAULT_SLEEP, logger: logger2 = console, formatPoliciesBrief: formatPoliciesBrief2 } = opts;
35958
36742
  const finalPrompt = composeTaskPrompt(task, policies, formatPoliciesBrief2);
35959
- await probeHealth(containerName, dockerExec, healthBudgetMs, sleep4);
36743
+ await probeHealth(containerName, dockerExec, healthBudgetMs, sleep5);
35960
36744
  startAgent(containerName, dockerExec);
35961
36745
  dispatch2(containerName, finalPrompt, dockerExec);
35962
36746
  logger2.log(`[world] Task auto-dispatched (${finalPrompt.length} chars)`);
@@ -35968,12 +36752,12 @@ init_store();
35968
36752
  init_bridge();
35969
36753
 
35970
36754
  // ../core/dist/global-config/runbook-resolver.js
35971
- import * as fs37 from "node:fs";
35972
- import * as os23 from "node:os";
35973
- import * as path39 from "node:path";
36755
+ import * as fs41 from "node:fs";
36756
+ import * as os25 from "node:os";
36757
+ import * as path41 from "node:path";
35974
36758
  function expandTilde(p) {
35975
36759
  if (p === "~" || p.startsWith("~/")) {
35976
- return path39.join(os23.homedir(), p.slice(1));
36760
+ return path41.join(os25.homedir(), p.slice(1));
35977
36761
  }
35978
36762
  return p;
35979
36763
  }
@@ -35985,7 +36769,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
35985
36769
  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.`);
35986
36770
  }
35987
36771
  const resolvedPath = expandTilde(entry.path);
35988
- if (!fs37.existsSync(resolvedPath)) {
36772
+ if (!fs41.existsSync(resolvedPath)) {
35989
36773
  throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
35990
36774
  }
35991
36775
  }
@@ -36001,19 +36785,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
36001
36785
  init_port_validator();
36002
36786
 
36003
36787
  // ../core/dist/world/bootstrap-hooks.js
36004
- import * as fs38 from "node:fs";
36005
- import * as path40 from "node:path";
36788
+ import * as fs42 from "node:fs";
36789
+ import * as path42 from "node:path";
36006
36790
  function runFixtureCopySeeds(seeds, workspacePath) {
36007
36791
  if (!seeds)
36008
36792
  return;
36009
36793
  for (const seed of seeds) {
36010
36794
  if (seed.type !== "fixture-copy")
36011
36795
  continue;
36012
- const srcAbs = path40.resolve(workspacePath, seed.repo, seed.src);
36013
- const destAbs = path40.resolve(workspacePath, seed.repo, seed.dest);
36014
- const destDir = path40.dirname(destAbs);
36015
- fs38.mkdirSync(destDir, { recursive: true });
36016
- fs38.cpSync(srcAbs, destAbs, { recursive: true, force: true });
36796
+ const srcAbs = path42.resolve(workspacePath, seed.repo, seed.src);
36797
+ const destAbs = path42.resolve(workspacePath, seed.repo, seed.dest);
36798
+ const destDir = path42.dirname(destAbs);
36799
+ fs42.mkdirSync(destDir, { recursive: true });
36800
+ fs42.cpSync(srcAbs, destAbs, { recursive: true, force: true });
36017
36801
  }
36018
36802
  }
36019
36803
  async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
@@ -36107,7 +36891,7 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
36107
36891
  const probeTimeoutMs = options.probeTimeoutMs ?? 3e4;
36108
36892
  const probeIntervalMs = options.probeIntervalMs ?? 1e3;
36109
36893
  const clock = options.clock ?? Date.now;
36110
- const sleep4 = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
36894
+ const sleep5 = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
36111
36895
  for (const repo of repos) {
36112
36896
  if (isPortBound(exec, containerName, repo.hostPort)) {
36113
36897
  throw new PortInUseError(repo.hostPort, repo.name, repo.manifestPath);
@@ -36132,7 +36916,7 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
36132
36916
  probeTimeoutMs,
36133
36917
  probeIntervalMs,
36134
36918
  clock,
36135
- sleep: sleep4
36919
+ sleep: sleep5
36136
36920
  })));
36137
36921
  return {
36138
36922
  sessionName,
@@ -36649,7 +37433,7 @@ ${detail}`);
36649
37433
  runbookSeeds = resolved.seeds;
36650
37434
  }
36651
37435
  const worldId = generateWorldId();
36652
- const workspacePath = path41.join(os24.homedir(), ".olam", "worlds", worldId);
37436
+ const workspacePath = path43.join(os26.homedir(), ".olam", "worlds", worldId);
36653
37437
  const portOffset = this.registry.getNextPortOffset();
36654
37438
  const branch = opts.branchName ?? `olam/${worldId}`;
36655
37439
  const repos = this.resolveReposWithWorkspace(opts);
@@ -36730,38 +37514,38 @@ ${detail}`);
36730
37514
  for (const repo of repos) {
36731
37515
  if (!repo.path)
36732
37516
  continue;
36733
- const sourceRoot = repo.path.replace(/^~/, os24.homedir());
36734
- const worktreeRoot = path41.join(workspacePath, repo.name);
36735
- if (!fs39.existsSync(sourceRoot) || !fs39.existsSync(worktreeRoot))
37517
+ const sourceRoot = repo.path.replace(/^~/, os26.homedir());
37518
+ const worktreeRoot = path43.join(workspacePath, repo.name);
37519
+ if (!fs43.existsSync(sourceRoot) || !fs43.existsSync(worktreeRoot))
36736
37520
  continue;
36737
37521
  let copied = 0;
36738
37522
  for (const pattern of RUNTIME_FILE_PATTERNS) {
36739
37523
  const matches2 = [];
36740
37524
  if (pattern.includes("*")) {
36741
- const [dir, glob] = [path41.dirname(pattern), path41.basename(pattern)];
36742
- const sourceDir = path41.join(sourceRoot, dir);
36743
- if (fs39.existsSync(sourceDir)) {
37525
+ const [dir, glob] = [path43.dirname(pattern), path43.basename(pattern)];
37526
+ const sourceDir = path43.join(sourceRoot, dir);
37527
+ if (fs43.existsSync(sourceDir)) {
36744
37528
  const ext = glob.replace(/^\*+/, "");
36745
37529
  try {
36746
- for (const entry of fs39.readdirSync(sourceDir)) {
37530
+ for (const entry of fs43.readdirSync(sourceDir)) {
36747
37531
  if (ext === "" || entry.endsWith(ext))
36748
- matches2.push(path41.join(dir, entry));
37532
+ matches2.push(path43.join(dir, entry));
36749
37533
  }
36750
37534
  } catch {
36751
37535
  }
36752
37536
  }
36753
- } else if (fs39.existsSync(path41.join(sourceRoot, pattern))) {
37537
+ } else if (fs43.existsSync(path43.join(sourceRoot, pattern))) {
36754
37538
  matches2.push(pattern);
36755
37539
  }
36756
37540
  for (const rel of matches2) {
36757
- const src = path41.join(sourceRoot, rel);
36758
- const dst = path41.join(worktreeRoot, rel);
37541
+ const src = path43.join(sourceRoot, rel);
37542
+ const dst = path43.join(worktreeRoot, rel);
36759
37543
  try {
36760
- const st = fs39.statSync(src);
37544
+ const st = fs43.statSync(src);
36761
37545
  if (!st.isFile())
36762
37546
  continue;
36763
- fs39.mkdirSync(path41.dirname(dst), { recursive: true });
36764
- fs39.copyFileSync(src, dst);
37547
+ fs43.mkdirSync(path43.dirname(dst), { recursive: true });
37548
+ fs43.copyFileSync(src, dst);
36765
37549
  copied++;
36766
37550
  } catch {
36767
37551
  }
@@ -36847,7 +37631,7 @@ ${detail}`);
36847
37631
  }
36848
37632
  const overlayAttachments = [];
36849
37633
  for (const repo of repos) {
36850
- const worldClonePath = path41.join(workspacePath, repo.name);
37634
+ const worldClonePath = path43.join(workspacePath, repo.name);
36851
37635
  try {
36852
37636
  const result = createWorldOverlay({
36853
37637
  workspace: repo.name,
@@ -36902,7 +37686,7 @@ ${detail}`);
36902
37686
  try {
36903
37687
  const hostExec = makeHostExecFn();
36904
37688
  for (const repo of repos) {
36905
- const repoDir = path41.join(workspacePath, repo.name);
37689
+ const repoDir = path43.join(workspacePath, repo.name);
36906
37690
  if (repo.stack && Object.keys(repo.stack).length > 0) {
36907
37691
  preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
36908
37692
  } else {
@@ -36946,10 +37730,10 @@ ${detail}`);
36946
37730
  const worldEnv = {};
36947
37731
  if (opts.task)
36948
37732
  worldEnv.OLAM_TASK = opts.task;
36949
- const r2CredsPath = path41.join(os24.homedir(), ".olam", "r2-credentials.json");
36950
- if (fs39.existsSync(r2CredsPath)) {
37733
+ const r2CredsPath = path43.join(os26.homedir(), ".olam", "r2-credentials.json");
37734
+ if (fs43.existsSync(r2CredsPath)) {
36951
37735
  try {
36952
- const r2Raw = fs39.readFileSync(r2CredsPath, "utf-8").trim();
37736
+ const r2Raw = fs43.readFileSync(r2CredsPath, "utf-8").trim();
36953
37737
  if (r2Raw.length > 0) {
36954
37738
  const r2 = JSON.parse(r2Raw);
36955
37739
  if (typeof r2.account_id === "string")
@@ -36966,10 +37750,10 @@ ${detail}`);
36966
37750
  } catch {
36967
37751
  }
36968
37752
  }
36969
- const keysYamlPath = path41.join(os24.homedir(), ".olam", "keys.yaml");
36970
- if (fs39.existsSync(keysYamlPath)) {
37753
+ const keysYamlPath = path43.join(os26.homedir(), ".olam", "keys.yaml");
37754
+ if (fs43.existsSync(keysYamlPath)) {
36971
37755
  try {
36972
- const keysRaw = fs39.readFileSync(keysYamlPath, "utf-8").trim();
37756
+ const keysRaw = fs43.readFileSync(keysYamlPath, "utf-8").trim();
36973
37757
  if (keysRaw.length > 0) {
36974
37758
  const parsed = YAML3.parse(keysRaw);
36975
37759
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
@@ -37028,10 +37812,10 @@ ${detail}`);
37028
37812
  worldEnv[k] = v;
37029
37813
  }
37030
37814
  for (const { repoName, relativePath, content } of fileWrites) {
37031
- const absPath = path41.join(workspacePath, repoName, relativePath);
37815
+ const absPath = path43.join(workspacePath, repoName, relativePath);
37032
37816
  try {
37033
- fs39.mkdirSync(path41.dirname(absPath), { recursive: true });
37034
- fs39.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
37817
+ fs43.mkdirSync(path43.dirname(absPath), { recursive: true });
37818
+ fs43.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
37035
37819
  mode: 384
37036
37820
  });
37037
37821
  console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
@@ -37202,7 +37986,7 @@ ${detail}`);
37202
37986
  imageDigest: void 0,
37203
37987
  repos: enrichedRepos.map((r) => ({
37204
37988
  name: r.name,
37205
- worktreeDir: path41.join(workspacePath, r.name)
37989
+ worktreeDir: path43.join(workspacePath, r.name)
37206
37990
  }))
37207
37991
  });
37208
37992
  for (const out of restoreResult.outcomes) {
@@ -37308,7 +38092,7 @@ ${detail}`);
37308
38092
  }
37309
38093
  if (opts.task) {
37310
38094
  const allPolicies = repos.flatMap((repo) => {
37311
- const repoWorktree = path41.join(workspacePath, repo.name);
38095
+ const repoWorktree = path43.join(workspacePath, repo.name);
37312
38096
  try {
37313
38097
  return loadPolicies(repoWorktree);
37314
38098
  } catch (err) {
@@ -37321,8 +38105,8 @@ ${detail}`);
37321
38105
  try {
37322
38106
  execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
37323
38107
  for (const repo of repos) {
37324
- const policiesDir = path41.join(workspacePath, repo.name, ".olam", "policies");
37325
- if (fs39.existsSync(policiesDir)) {
38108
+ const policiesDir = path43.join(workspacePath, repo.name, ".olam", "policies");
38109
+ if (fs43.existsSync(policiesDir)) {
37326
38110
  execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
37327
38111
  }
37328
38112
  }
@@ -37430,8 +38214,8 @@ ${detail}`);
37430
38214
  } catch {
37431
38215
  }
37432
38216
  try {
37433
- fs39.rmSync(world.workspacePath, { recursive: true, force: true });
37434
- if (fs39.existsSync(world.workspacePath)) {
38217
+ fs43.rmSync(world.workspacePath, { recursive: true, force: true });
38218
+ if (fs43.existsSync(world.workspacePath)) {
37435
38219
  console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
37436
38220
  }
37437
38221
  } catch (err) {
@@ -37540,14 +38324,14 @@ ${detail}`);
37540
38324
  }).filter((r) => r !== void 0);
37541
38325
  }
37542
38326
  transportPlanFile(planFilePath, workspacePath, repoNames) {
37543
- const planContent = fs39.readFileSync(planFilePath, "utf-8");
37544
- const planFileName = path41.basename(planFilePath);
38327
+ const planContent = fs43.readFileSync(planFilePath, "utf-8");
38328
+ const planFileName = path43.basename(planFilePath);
37545
38329
  const targetRepo = repoNames[0];
37546
38330
  if (!targetRepo)
37547
38331
  return;
37548
- const plansDir = path41.join(workspacePath, targetRepo, "docs", "plans");
37549
- fs39.mkdirSync(plansDir, { recursive: true });
37550
- fs39.writeFileSync(path41.join(plansDir, planFileName), planContent);
38332
+ const plansDir = path43.join(workspacePath, targetRepo, "docs", "plans");
38333
+ fs43.mkdirSync(plansDir, { recursive: true });
38334
+ fs43.writeFileSync(path43.join(plansDir, planFileName), planContent);
37551
38335
  }
37552
38336
  resolveServices(repos) {
37553
38337
  const services = [];
@@ -37850,7 +38634,7 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
37850
38634
  return { worldRoleName, password };
37851
38635
  }
37852
38636
  function defaultPasswordGenerator() {
37853
- return crypto7.randomBytes(24).toString("base64url");
38637
+ return crypto8.randomBytes(24).toString("base64url");
37854
38638
  }
37855
38639
  function escapeSqlLiteral(s) {
37856
38640
  return s.replace(/'/g, "''");
@@ -37981,8 +38765,8 @@ import * as http2 from "node:http";
37981
38765
 
37982
38766
  // ../core/dist/dashboard/server.js
37983
38767
  import * as http from "node:http";
37984
- import * as fs40 from "node:fs";
37985
- import * as path42 from "node:path";
38768
+ import * as fs44 from "node:fs";
38769
+ import * as path44 from "node:path";
37986
38770
  import { fileURLToPath as fileURLToPath2 } from "node:url";
37987
38771
 
37988
38772
  // ../core/dist/dashboard/serialize.js
@@ -38317,7 +39101,7 @@ function notFound(res) {
38317
39101
  }
38318
39102
  function openThoughtStore(workspacePath) {
38319
39103
  const dbPath = getWorldDbPath(workspacePath);
38320
- if (!fs40.existsSync(dbPath))
39104
+ if (!fs44.existsSync(dbPath))
38321
39105
  return null;
38322
39106
  return new ThoughtLocalStore(dbPath);
38323
39107
  }
@@ -38488,13 +39272,13 @@ function findSessionInWorld(registry2, sessionId) {
38488
39272
  }
38489
39273
  function createDashboardServer(opts) {
38490
39274
  const { port: port2, registry: registry2 } = opts;
38491
- const thisDir = path42.dirname(fileURLToPath2(import.meta.url));
38492
- const defaultPublicDir = path42.resolve(thisDir, "../../../control-plane/public");
39275
+ const thisDir = path44.dirname(fileURLToPath2(import.meta.url));
39276
+ const defaultPublicDir = path44.resolve(thisDir, "../../../control-plane/public");
38493
39277
  const publicDir = opts.publicDir ?? defaultPublicDir;
38494
- let hasPublicDir = fs40.existsSync(publicDir);
39278
+ let hasPublicDir = fs44.existsSync(publicDir);
38495
39279
  const server = http.createServer((req, res) => {
38496
39280
  if (!hasPublicDir) {
38497
- hasPublicDir = fs40.existsSync(publicDir);
39281
+ hasPublicDir = fs44.existsSync(publicDir);
38498
39282
  }
38499
39283
  const host = req.headers.host ?? `localhost:${port2}`;
38500
39284
  const url2 = new URL(req.url ?? "/", `http://${host}`);
@@ -38768,22 +39552,22 @@ function createDashboardServer(opts) {
38768
39552
  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>`);
38769
39553
  return;
38770
39554
  }
38771
- let filePath = path42.join(publicDir, pathname === "/" ? "index.html" : pathname);
39555
+ let filePath = path44.join(publicDir, pathname === "/" ? "index.html" : pathname);
38772
39556
  if (!filePath.startsWith(publicDir)) {
38773
39557
  notFound(res);
38774
39558
  return;
38775
39559
  }
38776
- if (fs40.existsSync(filePath) && fs40.statSync(filePath).isFile()) {
38777
- const ext = path42.extname(filePath);
39560
+ if (fs44.existsSync(filePath) && fs44.statSync(filePath).isFile()) {
39561
+ const ext = path44.extname(filePath);
38778
39562
  const contentType = MIME[ext] ?? "application/octet-stream";
38779
39563
  res.writeHead(200, { "Content-Type": contentType });
38780
- fs40.createReadStream(filePath).pipe(res);
39564
+ fs44.createReadStream(filePath).pipe(res);
38781
39565
  return;
38782
39566
  }
38783
- filePath = path42.join(publicDir, "index.html");
38784
- if (fs40.existsSync(filePath)) {
39567
+ filePath = path44.join(publicDir, "index.html");
39568
+ if (fs44.existsSync(filePath)) {
38785
39569
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
38786
- fs40.createReadStream(filePath).pipe(res);
39570
+ fs44.createReadStream(filePath).pipe(res);
38787
39571
  return;
38788
39572
  }
38789
39573
  notFound(res);
@@ -38793,17 +39577,17 @@ function createDashboardServer(opts) {
38793
39577
  }
38794
39578
 
38795
39579
  // ../core/dist/dashboard/state.js
38796
- import * as fs41 from "node:fs";
38797
- import * as os25 from "node:os";
38798
- import * as path43 from "node:path";
38799
- var STATE_PATH = path43.join(os25.homedir(), ".olam", "dashboard.json");
39580
+ import * as fs45 from "node:fs";
39581
+ import * as os27 from "node:os";
39582
+ import * as path45 from "node:path";
39583
+ var STATE_PATH = path45.join(os27.homedir(), ".olam", "dashboard.json");
38800
39584
  function saveDashboardState(state) {
38801
- fs41.mkdirSync(path43.dirname(STATE_PATH), { recursive: true });
38802
- fs41.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
39585
+ fs45.mkdirSync(path45.dirname(STATE_PATH), { recursive: true });
39586
+ fs45.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
38803
39587
  }
38804
39588
  function loadDashboardState() {
38805
39589
  try {
38806
- const raw = fs41.readFileSync(STATE_PATH, "utf-8");
39590
+ const raw = fs45.readFileSync(STATE_PATH, "utf-8");
38807
39591
  return JSON.parse(raw);
38808
39592
  } catch {
38809
39593
  return null;
@@ -38811,7 +39595,7 @@ function loadDashboardState() {
38811
39595
  }
38812
39596
  function clearDashboardState() {
38813
39597
  try {
38814
- fs41.unlinkSync(STATE_PATH);
39598
+ fs45.unlinkSync(STATE_PATH);
38815
39599
  } catch {
38816
39600
  }
38817
39601
  }
@@ -39091,8 +39875,8 @@ var PleriClient = class {
39091
39875
  };
39092
39876
 
39093
39877
  // ../mcp-server/src/env-loader.ts
39094
- import { readFileSync as readFileSync29, existsSync as existsSync39, statSync as statSync12 } from "node:fs";
39095
- import { join as join44, dirname as dirname24, resolve as resolve11 } from "node:path";
39878
+ import { readFileSync as readFileSync33, existsSync as existsSync42, statSync as statSync12 } from "node:fs";
39879
+ import { join as join46, dirname as dirname27, resolve as resolve11 } from "node:path";
39096
39880
  var PROJECT_MARKERS = [
39097
39881
  ".olam/config.yaml",
39098
39882
  ".olam/config.yml",
@@ -39104,26 +39888,26 @@ function findProjectRoot2(startDir) {
39104
39888
  const root = resolve11("/");
39105
39889
  while (true) {
39106
39890
  for (const marker of PROJECT_MARKERS) {
39107
- if (existsSync39(join44(dir, marker))) return dir;
39891
+ if (existsSync42(join46(dir, marker))) return dir;
39108
39892
  }
39109
- const pkg = join44(dir, "package.json");
39110
- if (existsSync39(pkg)) {
39893
+ const pkg = join46(dir, "package.json");
39894
+ if (existsSync42(pkg)) {
39111
39895
  try {
39112
- const json = JSON.parse(readFileSync29(pkg, "utf8"));
39896
+ const json = JSON.parse(readFileSync33(pkg, "utf8"));
39113
39897
  const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
39114
39898
  const hasOlamDep = json.dependencies && Object.keys(json.dependencies).some((k) => k.startsWith("@olam/")) || json.devDependencies && Object.keys(json.devDependencies).some((k) => k.startsWith("@olam/"));
39115
39899
  if (isOlamWorkspace || hasOlamDep) return dir;
39116
39900
  } catch {
39117
39901
  }
39118
39902
  }
39119
- const parent = dirname24(dir);
39903
+ const parent = dirname27(dir);
39120
39904
  if (parent === dir || parent === root) return null;
39121
39905
  dir = parent;
39122
39906
  }
39123
39907
  }
39124
- function parseEnvFile(path44) {
39908
+ function parseEnvFile(path46) {
39125
39909
  const out = {};
39126
- const raw = readFileSync29(path44, "utf8");
39910
+ const raw = readFileSync33(path46, "utf8");
39127
39911
  for (const line of raw.split(/\r?\n/)) {
39128
39912
  const trimmed = line.trim();
39129
39913
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -39146,8 +39930,8 @@ function loadProjectEnv(startDir = process.cwd()) {
39146
39930
  const filesRead = [];
39147
39931
  const merged = {};
39148
39932
  for (const name of [".env", ".env.local"]) {
39149
- const p = join44(root, name);
39150
- if (existsSync39(p) && statSync12(p).isFile()) {
39933
+ const p = join46(root, name);
39934
+ if (existsSync42(p) && statSync12(p).isFile()) {
39151
39935
  Object.assign(merged, parseEnvFile(p));
39152
39936
  filesRead.push(p);
39153
39937
  }