@pleri/olam-cli 0.1.205 → 0.1.207

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: path60, errorMaps, issueData } = params;
449
- const fullPath = [...path60, ...issueData.path || []];
448
+ const { data, path: path62, errorMaps, issueData } = params;
449
+ const fullPath = [...path62, ...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, path60, key) {
757
+ constructor(parent, value, path62, key) {
758
758
  this._cachedPath = [];
759
759
  this.parent = parent;
760
760
  this.data = value;
761
- this._path = path60;
761
+ this._path = path62;
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(path60) {
7336
- let input = path60;
7335
+ function removeDotSegments(path62) {
7336
+ let input = path62;
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 [path60, query] = wsComponent.resourceName.split("?");
7536
- wsComponent.path = path60 && path60 !== "/" ? path60 : void 0;
7535
+ const [path62, query] = wsComponent.resourceName.split("?");
7536
+ wsComponent.path = path62 && path62 !== "/" ? path62 : 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, fs60, exportName) {
10898
+ function addFormats(ajv, list, fs62, 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, fs60[f]);
10903
+ ajv.addFormat(f, fs62[f]);
10904
10904
  }
10905
10905
  module.exports = exports = formatsPlugin;
10906
10906
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -11053,7 +11053,7 @@ import YAML from "yaml";
11053
11053
  function bootstrapStepCmd(entry) {
11054
11054
  return typeof entry === "string" ? entry : entry.cmd;
11055
11055
  }
11056
- function refineForbiddenKeys(value, path60, ctx, rejectSource) {
11056
+ function refineForbiddenKeys(value, path62, ctx, rejectSource) {
11057
11057
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
11058
11058
  return;
11059
11059
  }
@@ -11061,12 +11061,12 @@ function refineForbiddenKeys(value, path60, ctx, rejectSource) {
11061
11061
  if (FORBIDDEN_KEYS.has(key)) {
11062
11062
  ctx.addIssue({
11063
11063
  code: external_exports2.ZodIssueCode.custom,
11064
- path: [...path60, key],
11064
+ path: [...path62, key],
11065
11065
  message: `forbidden key "${key}" (prototype-pollution surface)`
11066
11066
  });
11067
11067
  continue;
11068
11068
  }
11069
- if (rejectSource && path60.length === 0 && key === "source") {
11069
+ if (rejectSource && path62.length === 0 && key === "source") {
11070
11070
  ctx.addIssue({
11071
11071
  code: external_exports2.ZodIssueCode.custom,
11072
11072
  path: ["source"],
@@ -11074,21 +11074,21 @@ function refineForbiddenKeys(value, path60, ctx, rejectSource) {
11074
11074
  });
11075
11075
  continue;
11076
11076
  }
11077
- refineForbiddenKeys(value[key], [...path60, key], ctx, false);
11077
+ refineForbiddenKeys(value[key], [...path62, key], ctx, false);
11078
11078
  }
11079
11079
  }
11080
- function rejectForbiddenKeys(value, path60, rejectSource) {
11080
+ function rejectForbiddenKeys(value, path62, rejectSource) {
11081
11081
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
11082
11082
  return;
11083
11083
  }
11084
11084
  for (const key of Object.keys(value)) {
11085
11085
  if (FORBIDDEN_KEYS.has(key)) {
11086
- throw new Error(`[manifest] ${path60}: forbidden key "${key}" (prototype-pollution surface)`);
11086
+ throw new Error(`[manifest] ${path62}: forbidden key "${key}" (prototype-pollution surface)`);
11087
11087
  }
11088
11088
  if (rejectSource && key === "source") {
11089
- throw new Error(`[manifest] ${path60}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11089
+ throw new Error(`[manifest] ${path62}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
11090
11090
  }
11091
- rejectForbiddenKeys(value[key], `${path60}.${key}`, false);
11091
+ rejectForbiddenKeys(value[key], `${path62}.${key}`, false);
11092
11092
  }
11093
11093
  }
11094
11094
  function unknownTopLevelKeys(parsed) {
@@ -13873,8 +13873,8 @@ var init_provider3 = __esm({
13873
13873
  // -----------------------------------------------------------------------
13874
13874
  // Internal fetch helper
13875
13875
  // -----------------------------------------------------------------------
13876
- async request(path60, method, body) {
13877
- const url3 = `${this.config.workerUrl}${path60}`;
13876
+ async request(path62, method, body) {
13877
+ const url3 = `${this.config.workerUrl}${path62}`;
13878
13878
  const bearer = await this.config.mintToken();
13879
13879
  const headers = {
13880
13880
  Authorization: `Bearer ${bearer}`
@@ -14283,10 +14283,81 @@ function readGlobalConfig() {
14283
14283
  }
14284
14284
  }
14285
14285
  return validated;
14286
- } catch (err) {
14287
- throw new GlobalConfigReadError(configPath, err);
14286
+ } catch (strictErr) {
14287
+ const salvaged = quarantineGlobalConfig(migrated.value);
14288
+ if (salvaged !== null) {
14289
+ let backupPath = null;
14290
+ try {
14291
+ backupPath = `${configPath}.quarantine-${Date.now()}`;
14292
+ fs13.copyFileSync(configPath, backupPath);
14293
+ } catch {
14294
+ backupPath = null;
14295
+ }
14296
+ try {
14297
+ writeGlobalConfig(salvaged.value);
14298
+ } catch {
14299
+ }
14300
+ quarantineSink(configPath, { drops: salvaged.drops, backupPath });
14301
+ return salvaged.value;
14302
+ }
14303
+ throw new GlobalConfigReadError(configPath, strictErr);
14288
14304
  }
14289
14305
  }
14306
+ function quarantineGlobalConfig(migratedValue) {
14307
+ if (migratedValue === null || typeof migratedValue !== "object" || Array.isArray(migratedValue)) {
14308
+ return null;
14309
+ }
14310
+ const obj = migratedValue;
14311
+ const drops = [];
14312
+ const filterField = (field, schema, dedupeKeys) => {
14313
+ const v = obj[field];
14314
+ if (v === void 0)
14315
+ return [];
14316
+ if (!Array.isArray(v)) {
14317
+ drops.push({ field, entry: v, reason: `${field} is not an array` });
14318
+ return [];
14319
+ }
14320
+ const out = [];
14321
+ const seen = dedupeKeys.map(() => /* @__PURE__ */ new Set());
14322
+ for (const e of v) {
14323
+ const r = schema.safeParse(e);
14324
+ if (!r.success || r.data === void 0) {
14325
+ drops.push({ field, entry: e, reason: r.error?.issues[0]?.message ?? "invalid entry" });
14326
+ continue;
14327
+ }
14328
+ let dupeKey = null;
14329
+ for (let i = 0; i < dedupeKeys.length; i++) {
14330
+ const k = dedupeKeys[i](r.data);
14331
+ if (seen[i].has(k)) {
14332
+ dupeKey = k;
14333
+ break;
14334
+ }
14335
+ }
14336
+ if (dupeKey !== null) {
14337
+ drops.push({ field, entry: e, reason: `duplicate key "${dupeKey}"` });
14338
+ continue;
14339
+ }
14340
+ for (let i = 0; i < dedupeKeys.length; i++)
14341
+ seen[i].add(dedupeKeys[i](r.data));
14342
+ out.push(r.data);
14343
+ }
14344
+ return out;
14345
+ };
14346
+ const repos = filterField("repos", RepoEntrySchema, [(r) => r.name]);
14347
+ const runbooks = filterField("runbooks", RunbookSchema, [(r) => r.name]);
14348
+ const skillSources = filterField("skillSources", SkillSourceSchema, [
14349
+ (s) => s.id,
14350
+ (s) => s.name
14351
+ ]);
14352
+ const metaHooksDisabled = filterField("metaHooksDisabled", MetaHookBlockKindSchema, [
14353
+ (m) => m
14354
+ ]);
14355
+ const candidate = { schemaVersion: 1, repos, runbooks, skillSources, metaHooksDisabled };
14356
+ const final = GlobalConfigSchema.safeParse(candidate);
14357
+ if (!final.success)
14358
+ return null;
14359
+ return { value: final.data, drops };
14360
+ }
14290
14361
  function migrateSchemaVersion(parsed) {
14291
14362
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
14292
14363
  return { value: parsed, changed: false };
@@ -14306,11 +14377,26 @@ function writeGlobalConfig(config2) {
14306
14377
  fs13.writeFileSync(tmp, JSON.stringify(validated, null, 2) + "\n", { mode: 420 });
14307
14378
  fs13.renameSync(tmp, configPath);
14308
14379
  }
14309
- var GlobalConfigReadError;
14380
+ var quarantineSink, GlobalConfigReadError;
14310
14381
  var init_store2 = __esm({
14311
14382
  "../core/dist/global-config/store.js"() {
14312
14383
  "use strict";
14313
14384
  init_schema4();
14385
+ init_schema3();
14386
+ quarantineSink = (configPath, report) => {
14387
+ if (report.drops.length === 0)
14388
+ return;
14389
+ process.stderr.write(`\x1B[33m\u26A0 global config at ${configPath} had ${report.drops.length} invalid entr${report.drops.length === 1 ? "y" : "ies"} \u2014 quarantined (kept the rest):\x1B[0m
14390
+ `);
14391
+ for (const d of report.drops) {
14392
+ process.stderr.write(` \xB7 ${d.field}: ${d.reason}
14393
+ `);
14394
+ }
14395
+ if (report.backupPath) {
14396
+ process.stderr.write(` \u2192 original backed up to ${report.backupPath}
14397
+ `);
14398
+ }
14399
+ };
14314
14400
  GlobalConfigReadError = class extends Error {
14315
14401
  constructor(configPath, cause) {
14316
14402
  const msg = cause instanceof Error ? cause.message : String(cause);
@@ -14684,6 +14770,145 @@ var init_trust_audit_log = __esm({
14684
14770
  }
14685
14771
  });
14686
14772
 
14773
+ // ../core/dist/skill-sources/clone.js
14774
+ import { execFileSync as execFileSync2 } from "node:child_process";
14775
+ import * as fs17 from "node:fs";
14776
+ import * as os12 from "node:os";
14777
+ import * as path19 from "node:path";
14778
+ function skillSourcesRootDir() {
14779
+ const override = process.env["OLAM_SKILL_SOURCES_DIR"];
14780
+ if (override && override.length > 0)
14781
+ return override;
14782
+ return path19.join(os12.homedir(), ".olam", "state", "skill-sources");
14783
+ }
14784
+ function skillSourceClonePath(id) {
14785
+ return path19.join(skillSourcesRootDir(), id);
14786
+ }
14787
+ function runGit(args, cwd) {
14788
+ try {
14789
+ return execFileSync2("git", args, {
14790
+ cwd,
14791
+ encoding: "utf-8",
14792
+ stdio: ["ignore", "pipe", "pipe"]
14793
+ });
14794
+ } catch (err) {
14795
+ throw err;
14796
+ }
14797
+ }
14798
+ function cloneSkillSource(opts) {
14799
+ const clonePath = skillSourceClonePath(opts.id);
14800
+ if (fs17.existsSync(clonePath)) {
14801
+ throw new Error(`clone path "${clonePath}" already exists. Remove the existing skill-source first.`);
14802
+ }
14803
+ fs17.mkdirSync(skillSourcesRootDir(), { recursive: true });
14804
+ try {
14805
+ runGit(["clone", "--depth", "1", "--branch", opts.branch, opts.gitUrl, clonePath]);
14806
+ } catch (err) {
14807
+ if (fs17.existsSync(clonePath)) {
14808
+ fs17.rmSync(clonePath, { recursive: true, force: true });
14809
+ }
14810
+ throw new SkillSourceGitError("clone", opts.gitUrl, err);
14811
+ }
14812
+ let headSha;
14813
+ try {
14814
+ headSha = runGit(["rev-parse", "HEAD"], clonePath).trim();
14815
+ } catch (err) {
14816
+ throw new SkillSourceGitError("rev-parse", opts.gitUrl, err);
14817
+ }
14818
+ return { clonePath, headSha };
14819
+ }
14820
+ function pullSkillSource(opts) {
14821
+ const clonePath = skillSourceClonePath(opts.id);
14822
+ if (!fs17.existsSync(clonePath)) {
14823
+ throw new Error(`clone path "${clonePath}" does not exist. Run "olam skills source add" first.`);
14824
+ }
14825
+ try {
14826
+ runGit(["fetch", "origin", opts.branch], clonePath);
14827
+ runGit(["reset", "--hard", `origin/${opts.branch}`], clonePath);
14828
+ } catch (err) {
14829
+ throw new SkillSourceGitError("fetch/reset", opts.gitUrl, err);
14830
+ }
14831
+ try {
14832
+ const headSha = runGit(["rev-parse", "HEAD"], clonePath).trim();
14833
+ return { headSha };
14834
+ } catch (err) {
14835
+ throw new SkillSourceGitError("rev-parse", opts.gitUrl, err);
14836
+ }
14837
+ }
14838
+ function removeSkillSourceClone(id) {
14839
+ const clonePath = skillSourceClonePath(id);
14840
+ if (fs17.existsSync(clonePath)) {
14841
+ fs17.rmSync(clonePath, { recursive: true, force: true });
14842
+ }
14843
+ }
14844
+ var SkillSourceGitError;
14845
+ var init_clone = __esm({
14846
+ "../core/dist/skill-sources/clone.js"() {
14847
+ "use strict";
14848
+ SkillSourceGitError = class extends Error {
14849
+ op;
14850
+ gitUrl;
14851
+ constructor(op, gitUrl, cause) {
14852
+ const msg = cause instanceof Error ? cause.message : String(cause);
14853
+ super(`git ${op} failed for "${gitUrl}": ${msg}`);
14854
+ this.op = op;
14855
+ this.gitUrl = gitUrl;
14856
+ this.name = "SkillSourceGitError";
14857
+ this.cause = cause;
14858
+ }
14859
+ };
14860
+ }
14861
+ });
14862
+
14863
+ // ../core/dist/skill-sources/source-file.js
14864
+ import * as fs18 from "node:fs";
14865
+ import * as path20 from "node:path";
14866
+ function sourceSidecarPath(id) {
14867
+ return path20.join(skillSourceClonePath(id), SOURCE_SIDECAR_FILENAME);
14868
+ }
14869
+ function writeSourceSidecar(entry) {
14870
+ const clonePath = skillSourceClonePath(entry.id);
14871
+ if (!fs18.existsSync(clonePath))
14872
+ return false;
14873
+ try {
14874
+ const validated = SourceSidecarSchema.parse(entry);
14875
+ const target = sourceSidecarPath(entry.id);
14876
+ const tmp = `${target}.tmp-${process.pid}`;
14877
+ fs18.writeFileSync(tmp, JSON.stringify(validated, null, 2) + "\n", { mode: 420 });
14878
+ fs18.renameSync(tmp, target);
14879
+ return true;
14880
+ } catch {
14881
+ return false;
14882
+ }
14883
+ }
14884
+ function readSourceSidecar(id) {
14885
+ const target = sourceSidecarPath(id);
14886
+ let raw;
14887
+ try {
14888
+ raw = fs18.readFileSync(target, "utf-8");
14889
+ } catch {
14890
+ return null;
14891
+ }
14892
+ let parsed;
14893
+ try {
14894
+ parsed = JSON.parse(raw);
14895
+ } catch {
14896
+ return null;
14897
+ }
14898
+ const result = SourceSidecarSchema.safeParse(parsed);
14899
+ return result.success ? result.data : null;
14900
+ }
14901
+ var SOURCE_SIDECAR_FILENAME, SourceSidecarSchema;
14902
+ var init_source_file = __esm({
14903
+ "../core/dist/skill-sources/source-file.js"() {
14904
+ "use strict";
14905
+ init_schema3();
14906
+ init_clone();
14907
+ SOURCE_SIDECAR_FILENAME = ".olam-source.json";
14908
+ SourceSidecarSchema = SkillSourceSchema;
14909
+ }
14910
+ });
14911
+
14687
14912
  // ../core/dist/skill-sources/store.js
14688
14913
  import * as crypto3 from "node:crypto";
14689
14914
  function deriveSkillSourceId(gitUrl) {
@@ -14716,6 +14941,7 @@ function addSkillSource(entry) {
14716
14941
  addedAt: now
14717
14942
  };
14718
14943
  writeGlobalConfig({ ...config2, skillSources: [...config2.skillSources, newEntry] });
14944
+ writeSourceSidecar(newEntry);
14719
14945
  try {
14720
14946
  appendTrustAudit({
14721
14947
  gitUrl: redactUrl2(entry.gitUrl),
@@ -14833,6 +15059,7 @@ function updateSkillSource(id, patch) {
14833
15059
  const next = [...config2.skillSources];
14834
15060
  next[idx] = updated;
14835
15061
  writeGlobalConfig({ ...config2, skillSources: next });
15062
+ writeSourceSidecar(updated);
14836
15063
  return updated;
14837
15064
  }
14838
15065
  var PREFIX_PATTERN3;
@@ -14843,102 +15070,141 @@ var init_store3 = __esm({
14843
15070
  init_schema3();
14844
15071
  init_trust_audit_log();
14845
15072
  init_source_config_schema();
15073
+ init_source_file();
14846
15074
  PREFIX_PATTERN3 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
14847
15075
  }
14848
15076
  });
14849
15077
 
14850
- // ../core/dist/skill-sources/clone.js
14851
- import { execFileSync as execFileSync2 } from "node:child_process";
14852
- import * as fs17 from "node:fs";
14853
- import * as os12 from "node:os";
14854
- import * as path19 from "node:path";
14855
- function skillSourcesRootDir() {
14856
- const override = process.env["OLAM_SKILL_SOURCES_DIR"];
14857
- if (override && override.length > 0)
14858
- return override;
14859
- return path19.join(os12.homedir(), ".olam", "state", "skill-sources");
14860
- }
14861
- function skillSourceClonePath(id) {
14862
- return path19.join(skillSourcesRootDir(), id);
14863
- }
14864
- function runGit(args, cwd) {
15078
+ // ../core/dist/skill-sources/reconcile.js
15079
+ import { execFileSync as execFileSync3 } from "node:child_process";
15080
+ import * as fs19 from "node:fs";
15081
+ import * as path21 from "node:path";
15082
+ function gitRead(args, cwd) {
14865
15083
  try {
14866
- return execFileSync2("git", args, {
15084
+ return execFileSync3("git", args, {
14867
15085
  cwd,
14868
15086
  encoding: "utf-8",
14869
- stdio: ["ignore", "pipe", "pipe"]
14870
- });
14871
- } catch (err) {
14872
- throw err;
15087
+ stdio: ["ignore", "pipe", "ignore"]
15088
+ }).trim();
15089
+ } catch {
15090
+ return null;
14873
15091
  }
14874
15092
  }
14875
- function cloneSkillSource(opts) {
14876
- const clonePath = skillSourceClonePath(opts.id);
14877
- if (fs17.existsSync(clonePath)) {
14878
- throw new Error(`clone path "${clonePath}" already exists. Remove the existing skill-source first.`);
14879
- }
14880
- fs17.mkdirSync(skillSourcesRootDir(), { recursive: true });
15093
+ function nameFromGitUrl(gitUrl) {
15094
+ const tail = gitUrl.replace(/\.git$/, "").replace(/\/+$/, "").split(/[/:]/).filter((s) => s.length > 0).pop();
15095
+ if (!tail)
15096
+ return null;
15097
+ const sanitized = tail.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
15098
+ return NAME_PATTERN2.test(sanitized) ? sanitized : null;
15099
+ }
15100
+ function recoverFromGit(id, clonePath) {
15101
+ const gitUrl = gitRead(["remote", "get-url", "origin"], clonePath);
15102
+ if (!gitUrl)
15103
+ return null;
15104
+ const branch = gitRead(["symbolic-ref", "--short", "HEAD"], clonePath) ?? gitRead(["rev-parse", "--abbrev-ref", "HEAD"], clonePath) ?? "main";
15105
+ const headSha = gitRead(["rev-parse", "HEAD"], clonePath);
15106
+ let addedAt = 0;
14881
15107
  try {
14882
- runGit(["clone", "--depth", "1", "--branch", opts.branch, opts.gitUrl, clonePath]);
14883
- } catch (err) {
14884
- if (fs17.existsSync(clonePath)) {
14885
- fs17.rmSync(clonePath, { recursive: true, force: true });
14886
- }
14887
- throw new SkillSourceGitError("clone", opts.gitUrl, err);
15108
+ addedAt = Math.floor(fs19.statSync(clonePath).ctimeMs);
15109
+ } catch {
15110
+ addedAt = 0;
14888
15111
  }
14889
- let headSha;
15112
+ const entry = {
15113
+ id,
15114
+ name: nameFromGitUrl(gitUrl) ?? `source-${id}`,
15115
+ gitUrl,
15116
+ branch,
15117
+ addedAt,
15118
+ ...headSha && SHA_PATTERN.test(headSha) ? { lastPulledSha: headSha } : {}
15119
+ };
15120
+ return entry;
15121
+ }
15122
+ function listCloneIds() {
15123
+ const root = skillSourcesRootDir();
15124
+ let dirents;
14890
15125
  try {
14891
- headSha = runGit(["rev-parse", "HEAD"], clonePath).trim();
14892
- } catch (err) {
14893
- throw new SkillSourceGitError("rev-parse", opts.gitUrl, err);
15126
+ dirents = fs19.readdirSync(root, { withFileTypes: true });
15127
+ } catch {
15128
+ return [];
14894
15129
  }
14895
- return { clonePath, headSha };
15130
+ return dirents.filter((d) => d.isDirectory() && fs19.existsSync(path21.join(root, d.name, ".git"))).map((d) => d.name);
14896
15131
  }
14897
- function pullSkillSource(opts) {
14898
- const clonePath = skillSourceClonePath(opts.id);
14899
- if (!fs17.existsSync(clonePath)) {
14900
- throw new Error(`clone path "${clonePath}" does not exist. Run "olam skills source add" first.`);
15132
+ function reconcileSkillSources(opts = {}) {
15133
+ const config2 = readGlobalConfig();
15134
+ const existingById = new Map(config2.skillSources.map((s) => [s.id, s]));
15135
+ const diskIds = new Set(listCloneIds());
15136
+ const added = [];
15137
+ const registryOnly = [];
15138
+ const sidecarsBackfilled = [];
15139
+ const usedNames = /* @__PURE__ */ new Set();
15140
+ const ensureUniqueName = (entry) => {
15141
+ if (!usedNames.has(entry.name)) {
15142
+ usedNames.add(entry.name);
15143
+ return entry;
15144
+ }
15145
+ const suffixed = `${entry.name}-${entry.id.slice(0, 6)}`.slice(0, 64).replace(/-+$/g, "");
15146
+ usedNames.add(suffixed);
15147
+ return { ...entry, name: suffixed };
15148
+ };
15149
+ const next = [];
15150
+ for (const entry of config2.skillSources) {
15151
+ if (diskIds.has(entry.id)) {
15152
+ usedNames.add(entry.name);
15153
+ next.push(entry);
15154
+ } else {
15155
+ registryOnly.push(entry);
15156
+ if (!opts.prune) {
15157
+ usedNames.add(entry.name);
15158
+ next.push(entry);
15159
+ }
15160
+ }
14901
15161
  }
14902
- try {
14903
- runGit(["fetch", "origin", opts.branch], clonePath);
14904
- runGit(["reset", "--hard", `origin/${opts.branch}`], clonePath);
14905
- } catch (err) {
14906
- throw new SkillSourceGitError("fetch/reset", opts.gitUrl, err);
15162
+ for (const id of diskIds) {
15163
+ if (existingById.has(id)) {
15164
+ if (readSourceSidecar(id) === null && writeSourceSidecar(existingById.get(id))) {
15165
+ sidecarsBackfilled.push(id);
15166
+ }
15167
+ continue;
15168
+ }
15169
+ const sidecar = readSourceSidecar(id);
15170
+ const recovered = sidecar ? { ...sidecar, id } : recoverFromGit(id, skillSourceClonePath(id));
15171
+ if (recovered === null)
15172
+ continue;
15173
+ const unique = ensureUniqueName(recovered);
15174
+ next.push(unique);
15175
+ added.push(unique);
15176
+ if (sidecar === null && writeSourceSidecar(unique))
15177
+ sidecarsBackfilled.push(id);
14907
15178
  }
14908
- try {
14909
- const headSha = runGit(["rev-parse", "HEAD"], clonePath).trim();
14910
- return { headSha };
14911
- } catch (err) {
14912
- throw new SkillSourceGitError("rev-parse", opts.gitUrl, err);
15179
+ const pruned = opts.prune ? registryOnly : [];
15180
+ const changed = next.length !== config2.skillSources.length || next.some((e, i) => e !== config2.skillSources[i]);
15181
+ if (changed) {
15182
+ writeGlobalConfig({ ...config2, skillSources: next });
14913
15183
  }
15184
+ return { added, registryOnly, pruned, sidecarsBackfilled, changed };
14914
15185
  }
14915
- function removeSkillSourceClone(id) {
14916
- const clonePath = skillSourceClonePath(id);
14917
- if (fs17.existsSync(clonePath)) {
14918
- fs17.rmSync(clonePath, { recursive: true, force: true });
14919
- }
15186
+ function reconcileIfRegistryEmpty() {
15187
+ if (readGlobalConfig().skillSources.length > 0)
15188
+ return null;
15189
+ if (listCloneIds().length === 0)
15190
+ return null;
15191
+ return reconcileSkillSources();
14920
15192
  }
14921
- var SkillSourceGitError;
14922
- var init_clone = __esm({
14923
- "../core/dist/skill-sources/clone.js"() {
15193
+ var NAME_PATTERN2, SHA_PATTERN;
15194
+ var init_reconcile = __esm({
15195
+ "../core/dist/skill-sources/reconcile.js"() {
14924
15196
  "use strict";
14925
- SkillSourceGitError = class extends Error {
14926
- op;
14927
- gitUrl;
14928
- constructor(op, gitUrl, cause) {
14929
- const msg = cause instanceof Error ? cause.message : String(cause);
14930
- super(`git ${op} failed for "${gitUrl}": ${msg}`);
14931
- this.op = op;
14932
- this.gitUrl = gitUrl;
14933
- this.name = "SkillSourceGitError";
14934
- this.cause = cause;
14935
- }
14936
- };
15197
+ init_store2();
15198
+ init_schema3();
15199
+ init_clone();
15200
+ init_source_file();
15201
+ NAME_PATTERN2 = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
15202
+ SHA_PATTERN = /^[a-f0-9]{40}$/;
14937
15203
  }
14938
15204
  });
14939
15205
 
14940
15206
  // ../core/dist/skill-sources/hook-template.js
14941
- import * as fs18 from "node:fs";
15207
+ import * as fs20 from "node:fs";
14942
15208
  function buildSkillsHookEntry() {
14943
15209
  return {
14944
15210
  matcher: "",
@@ -14997,14 +15263,14 @@ function computeUninstall(settings) {
14997
15263
  return { status: "removed", settingsAfter: next };
14998
15264
  }
14999
15265
  function uninstallSkillsHookFromFile(filePath) {
15000
- if (!fs18.existsSync(filePath)) {
15266
+ if (!fs20.existsSync(filePath)) {
15001
15267
  return { status: "no-settings" };
15002
15268
  }
15003
- const raw = fs18.readFileSync(filePath, "utf-8");
15269
+ const raw = fs20.readFileSync(filePath, "utf-8");
15004
15270
  const settings = raw.trim() ? JSON.parse(raw) : {};
15005
15271
  const result = computeUninstall(settings);
15006
15272
  if (result.status === "removed" && result.settingsAfter) {
15007
- fs18.writeFileSync(filePath, JSON.stringify(result.settingsAfter, null, 2) + "\n");
15273
+ fs20.writeFileSync(filePath, JSON.stringify(result.settingsAfter, null, 2) + "\n");
15008
15274
  }
15009
15275
  return result;
15010
15276
  }
@@ -15020,8 +15286,8 @@ var init_hook_template = __esm({
15020
15286
  });
15021
15287
 
15022
15288
  // ../core/dist/world/merge-settings.js
15023
- import * as fs19 from "node:fs";
15024
- import * as path20 from "node:path";
15289
+ import * as fs21 from "node:fs";
15290
+ import * as path22 from "node:path";
15025
15291
  import * as crypto4 from "node:crypto";
15026
15292
  function mergeHomeSettingsJson(filePath, options) {
15027
15293
  let settings;
@@ -15051,11 +15317,12 @@ function mergeHomeSettingsJson(filePath, options) {
15051
15317
  return { status: "already-present", message: `hook already present at ${filePath}` };
15052
15318
  }
15053
15319
  } else {
15320
+ const filteredArr = options.ensureHook.staleSentinelPrefix ? dropStaleHooks(stageArr, options.ensureHook.staleSentinelPrefix, sentinel) : stageArr;
15054
15321
  settings = {
15055
15322
  ...settings,
15056
15323
  hooks: {
15057
15324
  ...settings.hooks,
15058
- [stage]: [...stageArr, entry]
15325
+ [stage]: [...filteredArr, entry]
15059
15326
  }
15060
15327
  };
15061
15328
  changed = true;
@@ -15081,14 +15348,32 @@ function mergeHomeSettingsJson(filePath, options) {
15081
15348
  return { status: "installed", message: `settings.json updated at ${filePath}` };
15082
15349
  }
15083
15350
  function readSettings(filePath) {
15084
- if (!fs19.existsSync(filePath)) {
15351
+ if (!fs21.existsSync(filePath)) {
15085
15352
  return {};
15086
15353
  }
15087
- const raw = fs19.readFileSync(filePath, "utf-8");
15354
+ const raw = fs21.readFileSync(filePath, "utf-8");
15088
15355
  if (!raw.trim())
15089
15356
  return {};
15090
15357
  return JSON.parse(raw);
15091
15358
  }
15359
+ function dropStaleHooks(matchers, stalePrefix, currentSentinel) {
15360
+ const out = [];
15361
+ for (const matcher of matchers) {
15362
+ const allCmds = [];
15363
+ if (typeof matcher.command === "string")
15364
+ allCmds.push(matcher.command);
15365
+ if (Array.isArray(matcher.hooks)) {
15366
+ for (const h of matcher.hooks) {
15367
+ if (typeof h.command === "string")
15368
+ allCmds.push(h.command);
15369
+ }
15370
+ }
15371
+ const isStale = allCmds.some((c) => c.includes(stalePrefix)) && !allCmds.some((c) => c.includes(currentSentinel));
15372
+ if (!isStale)
15373
+ out.push(matcher);
15374
+ }
15375
+ return out;
15376
+ }
15092
15377
  function isHookSentinelPresent(matchers, sentinel) {
15093
15378
  for (const matcher of matchers) {
15094
15379
  if (typeof matcher?.command === "string" && matcher.command.includes(sentinel)) {
@@ -15105,13 +15390,13 @@ function isHookSentinelPresent(matchers, sentinel) {
15105
15390
  return false;
15106
15391
  }
15107
15392
  function atomicWriteJson(filePath, data) {
15108
- const dir = path20.dirname(filePath);
15109
- fs19.mkdirSync(dir, { recursive: true });
15393
+ const dir = path22.dirname(filePath);
15394
+ fs21.mkdirSync(dir, { recursive: true });
15110
15395
  const rand = crypto4.randomBytes(6).toString("hex");
15111
15396
  const tmp = `${filePath}.tmp.${process.pid}.${rand}`;
15112
15397
  const json2 = JSON.stringify(data, null, 2) + "\n";
15113
- fs19.writeFileSync(tmp, json2, { mode: 420 });
15114
- fs19.renameSync(tmp, filePath);
15398
+ fs21.writeFileSync(tmp, json2, { mode: 420 });
15399
+ fs21.renameSync(tmp, filePath);
15115
15400
  }
15116
15401
  var init_merge_settings = __esm({
15117
15402
  "../core/dist/world/merge-settings.js"() {
@@ -15120,25 +15405,25 @@ var init_merge_settings = __esm({
15120
15405
  });
15121
15406
 
15122
15407
  // ../core/dist/skill-sources/hook-install.js
15123
- import * as fs20 from "node:fs";
15124
- import * as path21 from "node:path";
15408
+ import * as fs22 from "node:fs";
15409
+ import * as path23 from "node:path";
15125
15410
  import * as os13 from "node:os";
15126
15411
  function settingsPathFor(scope, cwd) {
15127
15412
  if (scope === "user") {
15128
- return path21.join(os13.homedir(), ".claude", "settings.json");
15413
+ return path23.join(os13.homedir(), ".claude", "settings.json");
15129
15414
  }
15130
- return path21.join(cwd ?? process.cwd(), ".claude", "settings.json");
15415
+ return path23.join(cwd ?? process.cwd(), ".claude", "settings.json");
15131
15416
  }
15132
15417
  function backupFile(filePath) {
15133
- if (!fs20.existsSync(filePath))
15418
+ if (!fs22.existsSync(filePath))
15134
15419
  return null;
15135
15420
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
15136
15421
  const backupPath = `${filePath}.olam-bak.${ts}`;
15137
- fs20.copyFileSync(filePath, backupPath);
15422
+ fs22.copyFileSync(filePath, backupPath);
15138
15423
  return backupPath;
15139
15424
  }
15140
15425
  function installSkillsHookToFile(filePath) {
15141
- fs20.mkdirSync(path21.dirname(filePath), { recursive: true });
15426
+ fs22.mkdirSync(path23.dirname(filePath), { recursive: true });
15142
15427
  const backupPath = backupFile(filePath);
15143
15428
  const result = mergeHomeSettingsJson(filePath, {
15144
15429
  ensureHook: {
@@ -15149,7 +15434,7 @@ function installSkillsHookToFile(filePath) {
15149
15434
  });
15150
15435
  if (result.status === "already-present" && backupPath) {
15151
15436
  try {
15152
- fs20.unlinkSync(backupPath);
15437
+ fs22.unlinkSync(backupPath);
15153
15438
  } catch {
15154
15439
  }
15155
15440
  return { status: "already-present", filePath, backupPath: null };
@@ -15157,11 +15442,11 @@ function installSkillsHookToFile(filePath) {
15157
15442
  return { status: result.status, filePath, backupPath };
15158
15443
  }
15159
15444
  function isSkillsHookInstalled(filePath) {
15160
- if (!fs20.existsSync(filePath))
15445
+ if (!fs22.existsSync(filePath))
15161
15446
  return false;
15162
15447
  let parsed;
15163
15448
  try {
15164
- parsed = JSON.parse(fs20.readFileSync(filePath, "utf-8"));
15449
+ parsed = JSON.parse(fs22.readFileSync(filePath, "utf-8"));
15165
15450
  } catch {
15166
15451
  return false;
15167
15452
  }
@@ -15199,36 +15484,36 @@ var init_hook_install = __esm({
15199
15484
  });
15200
15485
 
15201
15486
  // ../core/dist/skill-sources/migration-snapshot.js
15202
- import * as fs21 from "node:fs";
15487
+ import * as fs23 from "node:fs";
15203
15488
  import * as os14 from "node:os";
15204
- import * as path22 from "node:path";
15489
+ import * as path24 from "node:path";
15205
15490
  function claudeDirInternal() {
15206
15491
  const override = process.env["OLAM_CLAUDE_DIR"];
15207
15492
  if (override && override.length > 0)
15208
15493
  return override;
15209
- return path22.join(os14.homedir(), ".claude");
15494
+ return path24.join(os14.homedir(), ".claude");
15210
15495
  }
15211
15496
  function migrationSnapshotsDir() {
15212
15497
  const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
15213
15498
  if (override && override.length > 0)
15214
15499
  return override;
15215
- return path22.join(os14.homedir(), ".olam", "state", "migration-snapshots");
15500
+ return path24.join(os14.homedir(), ".olam", "state", "migration-snapshots");
15216
15501
  }
15217
15502
  function listToolboxManagedSymlinks(toolboxPath) {
15218
15503
  const claude = claudeDirInternal();
15219
15504
  const out = [];
15220
15505
  const BUCKETS2 = ["skills", "agents", "scripts", "rules", "commands"];
15221
15506
  for (const bucket of BUCKETS2) {
15222
- const dir = path22.join(claude, bucket);
15223
- if (!fs21.existsSync(dir))
15507
+ const dir = path24.join(claude, bucket);
15508
+ if (!fs23.existsSync(dir))
15224
15509
  continue;
15225
- for (const name of fs21.readdirSync(dir)) {
15226
- const link = path22.join(dir, name);
15510
+ for (const name of fs23.readdirSync(dir)) {
15511
+ const link = path24.join(dir, name);
15227
15512
  try {
15228
- const stat2 = fs21.lstatSync(link);
15513
+ const stat2 = fs23.lstatSync(link);
15229
15514
  if (!stat2.isSymbolicLink())
15230
15515
  continue;
15231
- const target = fs21.readlinkSync(link);
15516
+ const target = fs23.readlinkSync(link);
15232
15517
  if (target.startsWith(toolboxPath)) {
15233
15518
  out.push({ link, target });
15234
15519
  }
@@ -15241,25 +15526,25 @@ function listToolboxManagedSymlinks(toolboxPath) {
15241
15526
  function detectToolboxState(opts) {
15242
15527
  const claude = claudeDirInternal();
15243
15528
  const toolboxPath = opts.toolboxPath;
15244
- const namespace = opts.namespace ?? path22.basename(toolboxPath);
15245
- const atlasUserFile = path22.join(claude, ".atlas-user");
15246
- const atlasUser = fs21.existsSync(atlasUserFile) ? fs21.readFileSync(atlasUserFile, "utf-8").trim() || void 0 : void 0;
15529
+ const namespace = opts.namespace ?? path24.basename(toolboxPath);
15530
+ const atlasUserFile = path24.join(claude, ".atlas-user");
15531
+ const atlasUser = fs23.existsSync(atlasUserFile) ? fs23.readFileSync(atlasUserFile, "utf-8").trim() || void 0 : void 0;
15247
15532
  let subscriptionsJson;
15248
15533
  if (atlasUser) {
15249
- const sp = path22.join(toolboxPath, "members", atlasUser, "subscriptions.json");
15250
- if (fs21.existsSync(sp)) {
15534
+ const sp = path24.join(toolboxPath, "members", atlasUser, "subscriptions.json");
15535
+ if (fs23.existsSync(sp)) {
15251
15536
  try {
15252
- subscriptionsJson = JSON.parse(fs21.readFileSync(sp, "utf-8"));
15537
+ subscriptionsJson = JSON.parse(fs23.readFileSync(sp, "utf-8"));
15253
15538
  } catch {
15254
15539
  }
15255
15540
  }
15256
15541
  }
15257
15542
  const atlasManagedSymlinks = listToolboxManagedSymlinks(toolboxPath);
15258
15543
  let originalSessionStartHook;
15259
- const settingsPath = path22.join(claude, "settings.json");
15260
- if (fs21.existsSync(settingsPath)) {
15544
+ const settingsPath = path24.join(claude, "settings.json");
15545
+ if (fs23.existsSync(settingsPath)) {
15261
15546
  try {
15262
- const settings = JSON.parse(fs21.readFileSync(settingsPath, "utf-8"));
15547
+ const settings = JSON.parse(fs23.readFileSync(settingsPath, "utf-8"));
15263
15548
  const ss = settings?.hooks?.SessionStart;
15264
15549
  if (Array.isArray(ss))
15265
15550
  originalSessionStartHook = ss;
@@ -15282,21 +15567,21 @@ function detectToolboxState(opts) {
15282
15567
  }
15283
15568
  function writeMigrationSnapshot(snapshot) {
15284
15569
  const dir = migrationSnapshotsDir();
15285
- fs21.mkdirSync(dir, { recursive: true });
15570
+ fs23.mkdirSync(dir, { recursive: true });
15286
15571
  const stamp = snapshot.takenAt.replace(/[:.]/g, "-");
15287
- const file2 = path22.join(dir, `${snapshot.namespace}-${stamp}.json`);
15288
- fs21.writeFileSync(file2, JSON.stringify(snapshot, null, 2) + "\n", { mode: 420 });
15572
+ const file2 = path24.join(dir, `${snapshot.namespace}-${stamp}.json`);
15573
+ fs23.writeFileSync(file2, JSON.stringify(snapshot, null, 2) + "\n", { mode: 420 });
15289
15574
  return file2;
15290
15575
  }
15291
15576
  function readLatestMigrationSnapshot(opts = {}) {
15292
15577
  const dir = migrationSnapshotsDir();
15293
- if (!fs21.existsSync(dir))
15578
+ if (!fs23.existsSync(dir))
15294
15579
  return void 0;
15295
- const files = fs21.readdirSync(dir).filter((f) => f.endsWith(".json")).sort().reverse();
15580
+ const files = fs23.readdirSync(dir).filter((f) => f.endsWith(".json")).sort().reverse();
15296
15581
  for (const f of files) {
15297
- const full = path22.join(dir, f);
15582
+ const full = path24.join(dir, f);
15298
15583
  try {
15299
- const snapshot = JSON.parse(fs21.readFileSync(full, "utf-8"));
15584
+ const snapshot = JSON.parse(fs23.readFileSync(full, "utf-8"));
15300
15585
  if (snapshot.schemaVersion !== MIGRATION_SNAPSHOT_SCHEMA_VERSION)
15301
15586
  continue;
15302
15587
  if (typeof snapshot.atlasToolboxRepoPath !== "string")
@@ -15313,7 +15598,7 @@ function readLatestMigrationSnapshot(opts = {}) {
15313
15598
  return void 0;
15314
15599
  }
15315
15600
  function readMigrationSnapshotFromPath(p) {
15316
- return JSON.parse(fs21.readFileSync(p, "utf-8"));
15601
+ return JSON.parse(fs23.readFileSync(p, "utf-8"));
15317
15602
  }
15318
15603
  var MIGRATION_SNAPSHOT_SCHEMA_VERSION;
15319
15604
  var init_migration_snapshot = __esm({
@@ -15324,15 +15609,15 @@ var init_migration_snapshot = __esm({
15324
15609
  });
15325
15610
 
15326
15611
  // ../core/dist/skill-sync/artifact-resolver.js
15327
- import * as fs22 from "node:fs";
15328
- import * as path23 from "node:path";
15612
+ import * as fs24 from "node:fs";
15613
+ import * as path25 from "node:path";
15329
15614
  function resolveSubscriptions(opts) {
15330
15615
  const { clonePath, atlasUser } = opts;
15331
15616
  if (atlasUser) {
15332
- const subsPath = path23.join(clonePath, "members", atlasUser, "subscriptions.json");
15333
- if (fs22.existsSync(subsPath)) {
15617
+ const subsPath = path25.join(clonePath, "members", atlasUser, "subscriptions.json");
15618
+ if (fs24.existsSync(subsPath)) {
15334
15619
  try {
15335
- const parsed = JSON.parse(fs22.readFileSync(subsPath, "utf-8"));
15620
+ const parsed = JSON.parse(fs24.readFileSync(subsPath, "utf-8"));
15336
15621
  if (Array.isArray(parsed?.categories)) {
15337
15622
  return {
15338
15623
  categories: parsed.categories.filter((c) => typeof c === "string"),
@@ -15344,10 +15629,10 @@ function resolveSubscriptions(opts) {
15344
15629
  }
15345
15630
  }
15346
15631
  }
15347
- const catsPath = path23.join(clonePath, "shared", "categories.json");
15348
- if (fs22.existsSync(catsPath)) {
15632
+ const catsPath = path25.join(clonePath, "shared", "categories.json");
15633
+ if (fs24.existsSync(catsPath)) {
15349
15634
  try {
15350
- const parsed = JSON.parse(fs22.readFileSync(catsPath, "utf-8"));
15635
+ const parsed = JSON.parse(fs24.readFileSync(catsPath, "utf-8"));
15351
15636
  if (Array.isArray(parsed?.categories)) {
15352
15637
  return {
15353
15638
  categories: parsed.categories.map((c) => c.id).filter((id) => typeof id === "string"),
@@ -15358,14 +15643,14 @@ function resolveSubscriptions(opts) {
15358
15643
  } catch {
15359
15644
  }
15360
15645
  }
15361
- const sharedDir = path23.join(clonePath, "shared");
15646
+ const sharedDir = path25.join(clonePath, "shared");
15362
15647
  const cats = [];
15363
- if (fs22.existsSync(sharedDir)) {
15364
- for (const name of fs22.readdirSync(sharedDir)) {
15365
- const dir = path23.join(sharedDir, name);
15366
- if (!fs22.statSync(dir).isDirectory())
15648
+ if (fs24.existsSync(sharedDir)) {
15649
+ for (const name of fs24.readdirSync(sharedDir)) {
15650
+ const dir = path25.join(sharedDir, name);
15651
+ if (!fs24.statSync(dir).isDirectory())
15367
15652
  continue;
15368
- if (fs22.existsSync(path23.join(dir, "skills")) || fs22.existsSync(path23.join(dir, "agents"))) {
15653
+ if (fs24.existsSync(path25.join(dir, "skills")) || fs24.existsSync(path25.join(dir, "agents"))) {
15369
15654
  cats.push(name);
15370
15655
  }
15371
15656
  }
@@ -15373,29 +15658,29 @@ function resolveSubscriptions(opts) {
15373
15658
  return { categories: cats, fromSubscriptionsFile: false, atlasUser };
15374
15659
  }
15375
15660
  function listDirSafe(dir) {
15376
- if (!fs22.existsSync(dir))
15661
+ if (!fs24.existsSync(dir))
15377
15662
  return [];
15378
- return fs22.readdirSync(dir);
15663
+ return fs24.readdirSync(dir);
15379
15664
  }
15380
15665
  function resolveSkillsDir(opts) {
15381
15666
  const { sourceId, baseDir } = opts;
15382
15667
  const out = [];
15383
15668
  for (const name of listDirSafe(baseDir)) {
15384
- const subdir = path23.join(baseDir, name);
15385
- if (!fs22.statSync(subdir).isDirectory())
15669
+ const subdir = path25.join(baseDir, name);
15670
+ if (!fs24.statSync(subdir).isDirectory())
15386
15671
  continue;
15387
- if (!fs22.existsSync(path23.join(subdir, "SKILL.md")))
15672
+ if (!fs24.existsSync(path25.join(subdir, "SKILL.md")))
15388
15673
  continue;
15389
15674
  out.push({ kind: "skill", sourceId, sourcePath: subdir, deployBasename: name });
15390
- const subagentsDir = path23.join(subdir, "references", "agents");
15391
- if (fs22.existsSync(subagentsDir) && fs22.statSync(subagentsDir).isDirectory()) {
15675
+ const subagentsDir = path25.join(subdir, "references", "agents");
15676
+ if (fs24.existsSync(subagentsDir) && fs24.statSync(subagentsDir).isDirectory()) {
15392
15677
  for (const f of listDirSafe(subagentsDir)) {
15393
15678
  if (!f.endsWith(".md"))
15394
15679
  continue;
15395
15680
  out.push({
15396
15681
  kind: "subagent",
15397
15682
  sourceId,
15398
- sourcePath: path23.join(subagentsDir, f),
15683
+ sourcePath: path25.join(subagentsDir, f),
15399
15684
  deployBasename: f,
15400
15685
  parentSkill: name
15401
15686
  });
@@ -15408,8 +15693,8 @@ function resolveAgentsDir(opts) {
15408
15693
  const { sourceId, baseDir } = opts;
15409
15694
  const out = [];
15410
15695
  for (const name of listDirSafe(baseDir)) {
15411
- const full = path23.join(baseDir, name);
15412
- const stat2 = fs22.statSync(full);
15696
+ const full = path25.join(baseDir, name);
15697
+ const stat2 = fs24.statSync(full);
15413
15698
  if (stat2.isFile() && name.endsWith(".md")) {
15414
15699
  out.push({ kind: "agent", sourceId, sourcePath: full, deployBasename: name });
15415
15700
  } else if (stat2.isDirectory()) {
@@ -15419,7 +15704,7 @@ function resolveAgentsDir(opts) {
15419
15704
  out.push({
15420
15705
  kind: "agent",
15421
15706
  sourceId,
15422
- sourcePath: path23.join(full, f),
15707
+ sourcePath: path25.join(full, f),
15423
15708
  deployBasename: `${name}-${f}`
15424
15709
  });
15425
15710
  }
@@ -15431,8 +15716,8 @@ function resolveScriptsDir(opts) {
15431
15716
  const { sourceId, baseDir } = opts;
15432
15717
  const out = [];
15433
15718
  for (const name of listDirSafe(baseDir)) {
15434
- const full = path23.join(baseDir, name);
15435
- const stat2 = fs22.statSync(full);
15719
+ const full = path25.join(baseDir, name);
15720
+ const stat2 = fs24.statSync(full);
15436
15721
  if (stat2.isFile() && name.endsWith(".sh")) {
15437
15722
  out.push({ kind: "script", sourceId, sourcePath: full, deployBasename: name });
15438
15723
  } else if (stat2.isDirectory()) {
@@ -15447,8 +15732,8 @@ function resolveRulesDir(opts) {
15447
15732
  for (const name of listDirSafe(baseDir)) {
15448
15733
  if (!name.endsWith(".md"))
15449
15734
  continue;
15450
- const full = path23.join(baseDir, name);
15451
- if (!fs22.statSync(full).isFile())
15735
+ const full = path25.join(baseDir, name);
15736
+ if (!fs24.statSync(full).isFile())
15452
15737
  continue;
15453
15738
  out.push({ kind: "rule", sourceId, sourcePath: full, deployBasename: name });
15454
15739
  }
@@ -15460,8 +15745,8 @@ function resolveJsonDir(opts) {
15460
15745
  for (const name of listDirSafe(baseDir)) {
15461
15746
  if (!name.endsWith(".json"))
15462
15747
  continue;
15463
- const full = path23.join(baseDir, name);
15464
- if (!fs22.statSync(full).isFile())
15748
+ const full = path25.join(baseDir, name);
15749
+ if (!fs24.statSync(full).isFile())
15465
15750
  continue;
15466
15751
  out.push({ kind, sourceId, sourcePath: full, deployBasename: name });
15467
15752
  }
@@ -15473,8 +15758,8 @@ function resolveOverlaysDir(opts) {
15473
15758
  for (const name of listDirSafe(baseDir)) {
15474
15759
  if (!name.endsWith(".md"))
15475
15760
  continue;
15476
- const full = path23.join(baseDir, name);
15477
- if (!fs22.statSync(full).isFile())
15761
+ const full = path25.join(baseDir, name);
15762
+ if (!fs24.statSync(full).isFile())
15478
15763
  continue;
15479
15764
  const deployBasename = name.replace(/\.md$/, "");
15480
15765
  out.push({
@@ -15492,33 +15777,33 @@ function resolveSourceArtifacts(opts) {
15492
15777
  const subscription = resolveSubscriptions({ clonePath, atlasUser });
15493
15778
  const artifacts = [];
15494
15779
  for (const cat of subscription.categories) {
15495
- const catDir = path23.join(clonePath, "shared", cat);
15496
- if (!fs22.existsSync(catDir))
15780
+ const catDir = path25.join(clonePath, "shared", cat);
15781
+ if (!fs24.existsSync(catDir))
15497
15782
  continue;
15498
- artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path23.join(catDir, "skills") }));
15499
- artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path23.join(catDir, "agents") }));
15500
- artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path23.join(catDir, "scripts") }));
15501
- artifacts.push(...resolveRulesDir({ sourceId, baseDir: path23.join(catDir, "rules") }));
15502
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path23.join(catDir, "hooks"), kind: "hook" }));
15503
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path23.join(catDir, "permissions"), kind: "permission" }));
15783
+ artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path25.join(catDir, "skills") }));
15784
+ artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path25.join(catDir, "agents") }));
15785
+ artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path25.join(catDir, "scripts") }));
15786
+ artifacts.push(...resolveRulesDir({ sourceId, baseDir: path25.join(catDir, "rules") }));
15787
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path25.join(catDir, "hooks"), kind: "hook" }));
15788
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path25.join(catDir, "permissions"), kind: "permission" }));
15504
15789
  }
15505
15790
  if (atlasUser) {
15506
- const memberRoot = path23.join(clonePath, "members", atlasUser);
15507
- if (fs22.existsSync(memberRoot)) {
15508
- artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path23.join(memberRoot, "skills") }));
15509
- artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path23.join(memberRoot, "agents") }));
15510
- artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path23.join(memberRoot, "scripts") }));
15511
- artifacts.push(...resolveRulesDir({ sourceId, baseDir: path23.join(memberRoot, "rules") }));
15512
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path23.join(memberRoot, "hooks"), kind: "hook" }));
15513
- artifacts.push(...resolveJsonDir({ sourceId, baseDir: path23.join(memberRoot, "permissions"), kind: "permission" }));
15791
+ const memberRoot = path25.join(clonePath, "members", atlasUser);
15792
+ if (fs24.existsSync(memberRoot)) {
15793
+ artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path25.join(memberRoot, "skills") }));
15794
+ artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path25.join(memberRoot, "agents") }));
15795
+ artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path25.join(memberRoot, "scripts") }));
15796
+ artifacts.push(...resolveRulesDir({ sourceId, baseDir: path25.join(memberRoot, "rules") }));
15797
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path25.join(memberRoot, "hooks"), kind: "hook" }));
15798
+ artifacts.push(...resolveJsonDir({ sourceId, baseDir: path25.join(memberRoot, "permissions"), kind: "permission" }));
15514
15799
  artifacts.push(...resolveOverlaysDir({
15515
15800
  sourceId,
15516
- baseDir: path23.join(memberRoot, "skills.overrides"),
15801
+ baseDir: path25.join(memberRoot, "skills.overrides"),
15517
15802
  targetKind: "skill"
15518
15803
  }));
15519
15804
  artifacts.push(...resolveOverlaysDir({
15520
15805
  sourceId,
15521
- baseDir: path23.join(memberRoot, "agents.overrides"),
15806
+ baseDir: path25.join(memberRoot, "agents.overrides"),
15522
15807
  targetKind: "agent"
15523
15808
  }));
15524
15809
  }
@@ -15584,14 +15869,14 @@ var init_shim_targets = __esm({
15584
15869
  });
15585
15870
 
15586
15871
  // ../core/dist/skill-sync/symlink-deployer.js
15587
- import * as fs23 from "node:fs";
15872
+ import * as fs25 from "node:fs";
15588
15873
  import * as os15 from "node:os";
15589
- import * as path24 from "node:path";
15874
+ import * as path26 from "node:path";
15590
15875
  function claudeDir() {
15591
15876
  const override = process.env["OLAM_CLAUDE_DIR"];
15592
15877
  if (override && override.length > 0)
15593
15878
  return override;
15594
- return path24.join(os15.homedir(), ".claude");
15879
+ return path26.join(os15.homedir(), ".claude");
15595
15880
  }
15596
15881
  function bucketFor(kind) {
15597
15882
  switch (kind) {
@@ -15651,15 +15936,15 @@ function detectCollisions(artifacts) {
15651
15936
  function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, expectedAgentWinnerNames) {
15652
15937
  const shadowBackups = [];
15653
15938
  for (const bucket of BUCKETS) {
15654
- const dir = path24.join(claude, bucket);
15655
- if (!fs23.existsSync(dir))
15939
+ const dir = path26.join(claude, bucket);
15940
+ if (!fs25.existsSync(dir))
15656
15941
  continue;
15657
- for (const name of fs23.readdirSync(dir)) {
15942
+ for (const name of fs25.readdirSync(dir)) {
15658
15943
  if (name === ".olam-merged")
15659
15944
  continue;
15660
- const p = path24.join(dir, name);
15945
+ const p = path26.join(dir, name);
15661
15946
  try {
15662
- const stat2 = fs23.lstatSync(p);
15947
+ const stat2 = fs25.lstatSync(p);
15663
15948
  if (stat2.isSymbolicLink()) {
15664
15949
  if (bucket === "scripts" && overlayReferences !== void 0) {
15665
15950
  const refs = overlayReferences.get(name);
@@ -15680,7 +15965,7 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, e
15680
15965
  `);
15681
15966
  }
15682
15967
  }
15683
- fs23.unlinkSync(p);
15968
+ fs25.unlinkSync(p);
15684
15969
  } else if (bucket === "agents" && stat2.isFile() && !name.includes(".shadow-backup-")) {
15685
15970
  const hasWinner = expectedAgentWinnerNames !== void 0 ? expectedAgentWinnerNames.has(name) : true;
15686
15971
  if (hasWinner) {
@@ -15697,34 +15982,34 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, e
15697
15982
  function shadowBackup(link) {
15698
15983
  const epoch = Math.floor(Date.now() / 1e3);
15699
15984
  const backup = `${link}.shadow-backup-${epoch}`;
15700
- fs23.renameSync(link, backup);
15985
+ fs25.renameSync(link, backup);
15701
15986
  return backup;
15702
15987
  }
15703
15988
  function linkIfNeeded(target, link) {
15704
15989
  try {
15705
- const existing = fs23.readlinkSync(link);
15990
+ const existing = fs25.readlinkSync(link);
15706
15991
  if (existing === target)
15707
15992
  return { created: false };
15708
15993
  } catch {
15709
15994
  }
15710
15995
  let isLink = false;
15711
15996
  try {
15712
- isLink = fs23.lstatSync(link).isSymbolicLink();
15997
+ isLink = fs25.lstatSync(link).isSymbolicLink();
15713
15998
  } catch {
15714
15999
  }
15715
16000
  let backup;
15716
16001
  if (isLink) {
15717
- fs23.unlinkSync(link);
15718
- } else if (fs23.existsSync(link)) {
16002
+ fs25.unlinkSync(link);
16003
+ } else if (fs25.existsSync(link)) {
15719
16004
  backup = shadowBackup(link);
15720
16005
  }
15721
- fs23.symlinkSync(target, link);
16006
+ fs25.symlinkSync(target, link);
15722
16007
  return { created: true, shadowBackup: backup };
15723
16008
  }
15724
16009
  function deployArtifacts(artifacts, opts) {
15725
16010
  const claude = claudeDir();
15726
16011
  for (const bucket of BUCKETS) {
15727
- fs23.mkdirSync(path24.join(claude, bucket), { recursive: true });
16012
+ fs25.mkdirSync(path26.join(claude, bucket), { recursive: true });
15728
16013
  }
15729
16014
  const { winners, collisions } = detectCollisions(artifacts);
15730
16015
  const expectedAgentWinnerNames = new Set(winners.filter((a) => a.kind === "agent").map((a) => a.deployBasename));
@@ -15734,11 +16019,11 @@ function deployArtifacts(artifacts, opts) {
15734
16019
  const bucket = bucketFor(artifact.kind);
15735
16020
  if (!bucket)
15736
16021
  continue;
15737
- const linkPath = path24.join(claude, bucket, artifact.deployBasename);
16022
+ const linkPath = path26.join(claude, bucket, artifact.deployBasename);
15738
16023
  if (artifact.kind === "agent" && artifact.resolvedContent !== void 0) {
15739
16024
  const tmpPath = `${linkPath}.tmp-${process.pid}-${Date.now()}`;
15740
- fs23.writeFileSync(tmpPath, artifact.resolvedContent);
15741
- fs23.renameSync(tmpPath, linkPath);
16025
+ fs25.writeFileSync(tmpPath, artifact.resolvedContent);
16026
+ fs25.renameSync(tmpPath, linkPath);
15742
16027
  result.linked += 1;
15743
16028
  continue;
15744
16029
  }
@@ -15760,7 +16045,7 @@ var init_symlink_deployer = __esm({
15760
16045
  });
15761
16046
 
15762
16047
  // ../core/dist/meta-hooks/memory-recall.js
15763
- import * as fs24 from "node:fs";
16048
+ import * as fs26 from "node:fs";
15764
16049
  function buildMemoryRecallHookEntry() {
15765
16050
  return {
15766
16051
  matcher: OLAM_META_MEMORY_RECALL_MATCHER,
@@ -15835,7 +16120,7 @@ var init_memory_recall = __esm({
15835
16120
  });
15836
16121
 
15837
16122
  // ../core/dist/meta-hooks/memory-classify.js
15838
- import * as fs25 from "node:fs";
16123
+ import * as fs27 from "node:fs";
15839
16124
  function buildMemoryClassifyHookEntry() {
15840
16125
  return {
15841
16126
  matcher: OLAM_META_MEMORY_CLASSIFY_MATCHER,
@@ -15910,7 +16195,7 @@ var init_memory_classify = __esm({
15910
16195
  });
15911
16196
 
15912
16197
  // ../core/dist/meta-hooks/model-router.js
15913
- import * as fs26 from "node:fs";
16198
+ import * as fs28 from "node:fs";
15914
16199
  function buildModelRouterHookEntry() {
15915
16200
  return {
15916
16201
  hooks: [
@@ -15984,9 +16269,9 @@ var init_model_router = __esm({
15984
16269
  });
15985
16270
 
15986
16271
  // ../core/dist/meta-hooks/model-router-deploy.js
15987
- import { existsSync as existsSync30, mkdirSync as mkdirSync16, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
16272
+ import { existsSync as existsSync32, mkdirSync as mkdirSync16, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
15988
16273
  import { homedir as homedir18 } from "node:os";
15989
- import { dirname as dirname13, join as join27, resolve as resolve7 } from "node:path";
16274
+ import { dirname as dirname13, join as join29, resolve as resolve7 } from "node:path";
15990
16275
  import { fileURLToPath as fileURLToPath3 } from "node:url";
15991
16276
  function resolveModelRouterSourcePath() {
15992
16277
  const here = dirname13(fileURLToPath3(import.meta.url));
@@ -16000,28 +16285,28 @@ function resolveModelRouterSourcePath() {
16000
16285
  resolve7(here, "..", "..", "hooks", MODEL_ROUTER_SCRIPT_BASENAME)
16001
16286
  ];
16002
16287
  for (const candidate of candidates) {
16003
- if (existsSync30(candidate))
16288
+ if (existsSync32(candidate))
16004
16289
  return candidate;
16005
16290
  }
16006
16291
  return candidates[0];
16007
16292
  }
16008
16293
  function deployModelRouterScript(opts = {}) {
16009
- const targetDir = opts.targetDir ?? join27(homedir18(), ".claude", "hooks");
16010
- const targetPath = join27(targetDir, MODEL_ROUTER_SCRIPT_BASENAME);
16294
+ const targetDir = opts.targetDir ?? join29(homedir18(), ".claude", "hooks");
16295
+ const targetPath = join29(targetDir, MODEL_ROUTER_SCRIPT_BASENAME);
16011
16296
  const sourcePath = opts.sourcePath ?? resolveModelRouterSourcePath();
16012
- if (!existsSync30(sourcePath)) {
16297
+ if (!existsSync32(sourcePath)) {
16013
16298
  return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "source-missing", targetPath };
16014
16299
  }
16015
- const newContent = readFileSync22(sourcePath, "utf8");
16016
- if (existsSync30(targetPath)) {
16017
- const existing = readFileSync22(targetPath, "utf8");
16300
+ const newContent = readFileSync23(sourcePath, "utf8");
16301
+ if (existsSync32(targetPath)) {
16302
+ const existing = readFileSync23(targetPath, "utf8");
16018
16303
  if (existing === newContent) {
16019
16304
  return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "unchanged", targetPath };
16020
16305
  }
16021
16306
  }
16022
16307
  if (opts.dryRun !== true) {
16023
16308
  mkdirSync16(dirname13(targetPath), { recursive: true });
16024
- writeFileSync14(targetPath, newContent, { mode: 493 });
16309
+ writeFileSync15(targetPath, newContent, { mode: 493 });
16025
16310
  }
16026
16311
  return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "written", targetPath };
16027
16312
  }
@@ -16045,26 +16330,26 @@ var init_meta_hooks = __esm({
16045
16330
  });
16046
16331
 
16047
16332
  // ../core/dist/skill-sync/settings-merger.js
16048
- import * as fs27 from "node:fs";
16333
+ import * as fs29 from "node:fs";
16049
16334
  import * as os16 from "node:os";
16050
- import * as path25 from "node:path";
16335
+ import * as path27 from "node:path";
16051
16336
  function claudeSettingsPath() {
16052
16337
  const override = process.env["OLAM_CLAUDE_SETTINGS_PATH"];
16053
16338
  if (override && override.length > 0)
16054
16339
  return override;
16055
- return path25.join(claudeDirInternal2(), "settings.json");
16340
+ return path27.join(claudeDirInternal2(), "settings.json");
16056
16341
  }
16057
16342
  function claudeDirInternal2() {
16058
16343
  const override = process.env["OLAM_CLAUDE_DIR"];
16059
16344
  if (override && override.length > 0)
16060
16345
  return override;
16061
- return path25.join(os16.homedir(), ".claude");
16346
+ return path27.join(os16.homedir(), ".claude");
16062
16347
  }
16063
16348
  function settingsBackupDir() {
16064
16349
  const override = process.env["OLAM_SETTINGS_BACKUP_DIR"];
16065
16350
  if (override && override.length > 0)
16066
16351
  return override;
16067
- return path25.join(os16.homedir(), ".olam", "state", "settings-backups");
16352
+ return path27.join(os16.homedir(), ".olam", "state", "settings-backups");
16068
16353
  }
16069
16354
  function dedupeByMatcher(entries) {
16070
16355
  const map2 = /* @__PURE__ */ new Map();
@@ -16114,28 +16399,28 @@ function tagOlam(entry) {
16114
16399
  return { ...entry, [OLAM_SKILLS_MARKER]: true };
16115
16400
  }
16116
16401
  function readJson(file2) {
16117
- return JSON.parse(fs27.readFileSync(file2, "utf-8"));
16402
+ return JSON.parse(fs29.readFileSync(file2, "utf-8"));
16118
16403
  }
16119
16404
  function rotateBackups(backupDir) {
16120
- if (!fs27.existsSync(backupDir))
16405
+ if (!fs29.existsSync(backupDir))
16121
16406
  return;
16122
- const files = fs27.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path25.join(backupDir, f), mtime: fs27.statSync(path25.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
16407
+ const files = fs29.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path27.join(backupDir, f), mtime: fs29.statSync(path27.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
16123
16408
  for (const f of files.slice(BACKUP_RETENTION)) {
16124
16409
  try {
16125
- fs27.unlinkSync(f.full);
16410
+ fs29.unlinkSync(f.full);
16126
16411
  } catch {
16127
16412
  }
16128
16413
  }
16129
16414
  }
16130
16415
  function backupSettings() {
16131
16416
  const src = claudeSettingsPath();
16132
- if (!fs27.existsSync(src))
16417
+ if (!fs29.existsSync(src))
16133
16418
  return void 0;
16134
16419
  const dir = settingsBackupDir();
16135
- fs27.mkdirSync(dir, { recursive: true });
16420
+ fs29.mkdirSync(dir, { recursive: true });
16136
16421
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
16137
- const dest = path25.join(dir, `settings-${stamp}.json`);
16138
- fs27.copyFileSync(src, dest);
16422
+ const dest = path27.join(dir, `settings-${stamp}.json`);
16423
+ fs29.copyFileSync(src, dest);
16139
16424
  rotateBackups(dir);
16140
16425
  return dest;
16141
16426
  }
@@ -16143,7 +16428,7 @@ function mergeSettings(input) {
16143
16428
  const settingsPath = claudeSettingsPath();
16144
16429
  const backupPath = backupSettings();
16145
16430
  let base = {};
16146
- if (fs27.existsSync(settingsPath)) {
16431
+ if (fs29.existsSync(settingsPath)) {
16147
16432
  try {
16148
16433
  base = readJson(settingsPath);
16149
16434
  } catch {
@@ -16211,10 +16496,10 @@ function mergeSettings(input) {
16211
16496
  ...input.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
16212
16497
  }
16213
16498
  };
16214
- fs27.mkdirSync(path25.dirname(settingsPath), { recursive: true });
16499
+ fs29.mkdirSync(path27.dirname(settingsPath), { recursive: true });
16215
16500
  const tmp = `${settingsPath}.tmp-${process.pid}`;
16216
- fs27.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
16217
- fs27.renameSync(tmp, settingsPath);
16501
+ fs29.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
16502
+ fs29.renameSync(tmp, settingsPath);
16218
16503
  return { backupPath, hooksAdded, permissionsCount: permSet.size, dualWriteDeduped, dualWriteDroppedCommands };
16219
16504
  }
16220
16505
  var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
@@ -16270,17 +16555,17 @@ var init_schema5 = __esm({
16270
16555
  });
16271
16556
 
16272
16557
  // ../core/dist/skill-sync/per-project-override.js
16273
- import { execFileSync as execFileSync3 } from "node:child_process";
16274
- import * as fs28 from "node:fs";
16275
- import * as path26 from "node:path";
16558
+ import { execFileSync as execFileSync4 } from "node:child_process";
16559
+ import * as fs30 from "node:fs";
16560
+ import * as path28 from "node:path";
16276
16561
  import { parse as parseYaml3 } from "yaml";
16277
16562
  function findProjectOverride(startDir) {
16278
- let dir = path26.resolve(startDir);
16279
- const root = path26.parse(dir).root;
16563
+ let dir = path28.resolve(startDir);
16564
+ const root = path28.parse(dir).root;
16280
16565
  while (true) {
16281
- const candidate = path26.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
16282
- if (fs28.existsSync(candidate) && fs28.statSync(candidate).isFile()) {
16283
- const raw = fs28.readFileSync(candidate, "utf-8");
16566
+ const candidate = path28.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
16567
+ if (fs30.existsSync(candidate) && fs30.statSync(candidate).isFile()) {
16568
+ const raw = fs30.readFileSync(candidate, "utf-8");
16284
16569
  let parsed;
16285
16570
  try {
16286
16571
  parsed = parseYaml3(raw);
@@ -16293,7 +16578,7 @@ function findProjectOverride(startDir) {
16293
16578
  }
16294
16579
  if (dir === root)
16295
16580
  return void 0;
16296
- dir = path26.dirname(dir);
16581
+ dir = path28.dirname(dir);
16297
16582
  }
16298
16583
  }
16299
16584
  function applyOverrideToArtifacts(artifacts, override) {
@@ -16313,7 +16598,7 @@ function applyPinToClone(opts) {
16313
16598
  if (ref.startsWith("-")) {
16314
16599
  throw new Error(`refuses ref "${ref}" \u2014 must not start with "-" (would be parsed as a git option)`);
16315
16600
  }
16316
- execFileSync3("git", ["-C", clonePath, "checkout", "-q", ref], {
16601
+ execFileSync4("git", ["-C", clonePath, "checkout", "-q", ref], {
16317
16602
  stdio: ["ignore", "ignore", "pipe"]
16318
16603
  });
16319
16604
  }
@@ -16323,7 +16608,7 @@ function restoreCloneToBranchHead(opts) {
16323
16608
  return;
16324
16609
  }
16325
16610
  try {
16326
- execFileSync3("git", ["-C", clonePath, "checkout", "-q", branch], {
16611
+ execFileSync4("git", ["-C", clonePath, "checkout", "-q", branch], {
16327
16612
  stdio: ["ignore", "ignore", "pipe"]
16328
16613
  });
16329
16614
  } catch {
@@ -16334,14 +16619,14 @@ var init_per_project_override = __esm({
16334
16619
  "../core/dist/skill-sync/per-project-override.js"() {
16335
16620
  "use strict";
16336
16621
  init_schema5();
16337
- PROJECT_OVERRIDE_RELATIVE_PATH = path26.join(".olam", "skill-overrides.yaml");
16622
+ PROJECT_OVERRIDE_RELATIVE_PATH = path28.join(".olam", "skill-overrides.yaml");
16338
16623
  }
16339
16624
  });
16340
16625
 
16341
16626
  // ../core/dist/lib/file-lock.js
16342
- import * as fs29 from "node:fs";
16627
+ import * as fs31 from "node:fs";
16343
16628
  import * as os17 from "node:os";
16344
- import * as path27 from "node:path";
16629
+ import * as path29 from "node:path";
16345
16630
  function defaultIsPidAlive(pid) {
16346
16631
  try {
16347
16632
  process.kill(pid, 0);
@@ -16356,7 +16641,7 @@ function sleep3(ms) {
16356
16641
  }
16357
16642
  function readLockMeta(lockPath) {
16358
16643
  try {
16359
- const raw = fs29.readFileSync(lockPath, "utf-8");
16644
+ const raw = fs31.readFileSync(lockPath, "utf-8");
16360
16645
  const parsed = JSON.parse(raw);
16361
16646
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
16362
16647
  return parsed;
@@ -16375,12 +16660,12 @@ function isLockStale(meta3, opts) {
16375
16660
  }
16376
16661
  function tryAcquireOnce(lockPath, meta3, opts) {
16377
16662
  try {
16378
- fs29.mkdirSync(path27.dirname(lockPath), { recursive: true });
16379
- const fd = fs29.openSync(lockPath, "wx", 384);
16663
+ fs31.mkdirSync(path29.dirname(lockPath), { recursive: true });
16664
+ const fd = fs31.openSync(lockPath, "wx", 384);
16380
16665
  try {
16381
- fs29.writeSync(fd, JSON.stringify(meta3));
16666
+ fs31.writeSync(fd, JSON.stringify(meta3));
16382
16667
  } finally {
16383
- fs29.closeSync(fd);
16668
+ fs31.closeSync(fd);
16384
16669
  }
16385
16670
  return true;
16386
16671
  } catch (err) {
@@ -16390,14 +16675,14 @@ function tryAcquireOnce(lockPath, meta3, opts) {
16390
16675
  const existing = readLockMeta(lockPath);
16391
16676
  if (existing === void 0) {
16392
16677
  try {
16393
- fs29.unlinkSync(lockPath);
16678
+ fs31.unlinkSync(lockPath);
16394
16679
  } catch {
16395
16680
  }
16396
16681
  return tryAcquireOnce(lockPath, meta3, opts);
16397
16682
  }
16398
16683
  if (isLockStale(existing, opts)) {
16399
16684
  try {
16400
- fs29.unlinkSync(lockPath);
16685
+ fs31.unlinkSync(lockPath);
16401
16686
  } catch {
16402
16687
  }
16403
16688
  return tryAcquireOnce(lockPath, meta3, opts);
@@ -16407,7 +16692,7 @@ function tryAcquireOnce(lockPath, meta3, opts) {
16407
16692
  }
16408
16693
  async function acquireFileLock(lockDir, options = {}) {
16409
16694
  const lockFilename = options.lockFilename ?? DEFAULT_LOCK_FILENAME;
16410
- const lockPath = path27.join(lockDir, lockFilename);
16695
+ const lockPath = path29.join(lockDir, lockFilename);
16411
16696
  const acquireTimeoutMs = options.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS;
16412
16697
  const staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS;
16413
16698
  const now = options.now ?? Date.now;
@@ -16427,7 +16712,7 @@ async function acquireFileLock(lockDir, options = {}) {
16427
16712
  lockPath,
16428
16713
  release: () => {
16429
16714
  try {
16430
- fs29.unlinkSync(lockPath);
16715
+ fs31.unlinkSync(lockPath);
16431
16716
  } catch {
16432
16717
  }
16433
16718
  }
@@ -16467,13 +16752,13 @@ var init_file_lock = __esm({
16467
16752
  });
16468
16753
 
16469
16754
  // ../core/dist/lib/min-version-filter.js
16470
- import { existsSync as existsSync33, readFileSync as readFileSync26 } from "node:fs";
16755
+ import { existsSync as existsSync35, readFileSync as readFileSync27 } from "node:fs";
16471
16756
  function readOlamMinVersion(filepath) {
16472
- if (!existsSync33(filepath))
16757
+ if (!existsSync35(filepath))
16473
16758
  return void 0;
16474
16759
  let text;
16475
16760
  try {
16476
- text = readFileSync26(filepath, "utf8");
16761
+ text = readFileSync27(filepath, "utf8");
16477
16762
  } catch {
16478
16763
  return void 0;
16479
16764
  }
@@ -16531,11 +16816,11 @@ var init_min_version_filter = __esm({
16531
16816
  });
16532
16817
 
16533
16818
  // ../core/dist/skill-sync/overlay-scan.js
16534
- import * as fs30 from "node:fs";
16535
- import * as path28 from "node:path";
16819
+ import * as fs32 from "node:fs";
16820
+ import * as path30 from "node:path";
16536
16821
  function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
16537
16822
  const result = /* @__PURE__ */ new Map();
16538
- if (!fs30.existsSync(overlayRoot)) {
16823
+ if (!fs32.existsSync(overlayRoot)) {
16539
16824
  return result;
16540
16825
  }
16541
16826
  if (basenames.length === 0) {
@@ -16544,13 +16829,13 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
16544
16829
  const mdFiles = [];
16545
16830
  let overlayRootReal;
16546
16831
  try {
16547
- overlayRootReal = fs30.realpathSync(overlayRoot);
16832
+ overlayRootReal = fs32.realpathSync(overlayRoot);
16548
16833
  } catch {
16549
16834
  return result;
16550
16835
  }
16551
16836
  for (const subdir of OVERRIDE_SUBDIRS) {
16552
- const dir = path28.join(overlayRoot, subdir);
16553
- if (!fs30.existsSync(dir))
16837
+ const dir = path30.join(overlayRoot, subdir);
16838
+ if (!fs32.existsSync(dir))
16554
16839
  continue;
16555
16840
  walkMarkdown(dir, mdFiles, caps.maxFiles);
16556
16841
  }
@@ -16558,25 +16843,25 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
16558
16843
  for (const filepath of mdFiles) {
16559
16844
  let realFile;
16560
16845
  try {
16561
- realFile = fs30.realpathSync(filepath);
16846
+ realFile = fs32.realpathSync(filepath);
16562
16847
  } catch (err) {
16563
16848
  const code = err.code;
16564
16849
  if (code === "ENOENT" || code === "EACCES")
16565
16850
  continue;
16566
16851
  throw err;
16567
16852
  }
16568
- const rel = path28.relative(overlayRootReal, realFile);
16569
- if (rel.startsWith("..") || path28.isAbsolute(rel)) {
16853
+ const rel = path30.relative(overlayRootReal, realFile);
16854
+ if (rel.startsWith("..") || path30.isAbsolute(rel)) {
16570
16855
  continue;
16571
16856
  }
16572
16857
  let content;
16573
16858
  try {
16574
- const stat2 = fs30.statSync(filepath);
16859
+ const stat2 = fs32.statSync(filepath);
16575
16860
  totalBytes += stat2.size;
16576
16861
  if (totalBytes > caps.maxTotalBytes) {
16577
16862
  throw new Error(`[overlay-scan] aborted: overlay tree exceeds ${caps.maxTotalBytes} total bytes. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
16578
16863
  }
16579
- content = fs30.readFileSync(filepath, "utf8");
16864
+ content = fs32.readFileSync(filepath, "utf8");
16580
16865
  } catch (err) {
16581
16866
  const code = err.code;
16582
16867
  if (code === "ENOENT" || code === "EACCES") {
@@ -16584,7 +16869,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
16584
16869
  }
16585
16870
  throw err;
16586
16871
  }
16587
- const relpath = path28.relative(overlayRoot, filepath).split(path28.sep).join("/");
16872
+ const relpath = path30.relative(overlayRoot, filepath).split(path30.sep).join("/");
16588
16873
  for (const basename6 of basenames) {
16589
16874
  if (content.includes(basename6)) {
16590
16875
  const list = result.get(basename6) ?? [];
@@ -16598,7 +16883,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
16598
16883
  function walkMarkdown(dir, out, cap) {
16599
16884
  let entries;
16600
16885
  try {
16601
- entries = fs30.readdirSync(dir, { withFileTypes: true });
16886
+ entries = fs32.readdirSync(dir, { withFileTypes: true });
16602
16887
  } catch (err) {
16603
16888
  if (err.code === "ENOENT")
16604
16889
  return;
@@ -16608,7 +16893,7 @@ function walkMarkdown(dir, out, cap) {
16608
16893
  if (out.length >= cap) {
16609
16894
  throw new Error(`[overlay-scan] aborted: overlay tree contains > ${cap} markdown files. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
16610
16895
  }
16611
- const full = path28.join(dir, entry.name);
16896
+ const full = path30.join(dir, entry.name);
16612
16897
  if (entry.isSymbolicLink())
16613
16898
  continue;
16614
16899
  if (entry.isDirectory()) {
@@ -16633,12 +16918,12 @@ var init_overlay_scan = __esm({
16633
16918
  });
16634
16919
 
16635
16920
  // ../core/dist/skill-sync/settings-json-lock.js
16636
- import * as fs31 from "node:fs";
16921
+ import * as fs33 from "node:fs";
16637
16922
  import * as os18 from "node:os";
16638
- import * as path29 from "node:path";
16923
+ import * as path31 from "node:path";
16639
16924
  function defaultSettingsJsonLockPath() {
16640
- const stateDir = process.env["OLAM_STATE_DIR"] ?? path29.join(os18.homedir(), ".olam", "state");
16641
- return path29.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
16925
+ const stateDir = process.env["OLAM_STATE_DIR"] ?? path31.join(os18.homedir(), ".olam", "state");
16926
+ return path31.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
16642
16927
  }
16643
16928
  function defaultIsPidAlive2(pid) {
16644
16929
  try {
@@ -16654,7 +16939,7 @@ function sleep4(ms) {
16654
16939
  }
16655
16940
  function readLockMeta2(lockPath) {
16656
16941
  try {
16657
- const raw = fs31.readFileSync(lockPath, "utf-8");
16942
+ const raw = fs33.readFileSync(lockPath, "utf-8");
16658
16943
  const parsed = JSON.parse(raw);
16659
16944
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
16660
16945
  return parsed;
@@ -16677,12 +16962,12 @@ function isLockStale2(meta3, opts) {
16677
16962
  function tryAcquireOnce2(lockPath, meta3, opts) {
16678
16963
  for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
16679
16964
  try {
16680
- fs31.mkdirSync(path29.dirname(lockPath), { recursive: true });
16681
- const fd = fs31.openSync(lockPath, "wx", 384);
16965
+ fs33.mkdirSync(path31.dirname(lockPath), { recursive: true });
16966
+ const fd = fs33.openSync(lockPath, "wx", 384);
16682
16967
  try {
16683
- fs31.writeSync(fd, JSON.stringify(meta3));
16968
+ fs33.writeSync(fd, JSON.stringify(meta3));
16684
16969
  } finally {
16685
- fs31.closeSync(fd);
16970
+ fs33.closeSync(fd);
16686
16971
  }
16687
16972
  return true;
16688
16973
  } catch (err) {
@@ -16700,9 +16985,9 @@ function tryAcquireOnce2(lockPath, meta3, opts) {
16700
16985
  }
16701
16986
  const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
16702
16987
  try {
16703
- fs31.renameSync(lockPath, victimPath);
16988
+ fs33.renameSync(lockPath, victimPath);
16704
16989
  try {
16705
- fs31.unlinkSync(victimPath);
16990
+ fs33.unlinkSync(victimPath);
16706
16991
  } catch {
16707
16992
  }
16708
16993
  } catch (err) {
@@ -16734,7 +17019,7 @@ async function acquireSettingsJsonLock(options = {}) {
16734
17019
  lockPath,
16735
17020
  release: () => {
16736
17021
  try {
16737
- fs31.unlinkSync(lockPath);
17022
+ fs33.unlinkSync(lockPath);
16738
17023
  } catch {
16739
17024
  }
16740
17025
  }
@@ -16837,14 +17122,14 @@ var init_services_status = __esm({
16837
17122
 
16838
17123
  // ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
16839
17124
  import * as crypto5 from "node:crypto";
16840
- import * as fs32 from "node:fs";
17125
+ import * as fs34 from "node:fs";
16841
17126
  import * as os19 from "node:os";
16842
- import * as path30 from "node:path";
17127
+ import * as path32 from "node:path";
16843
17128
  function migrationSnapshotsDir2() {
16844
17129
  const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
16845
17130
  if (override && override.length > 0)
16846
17131
  return override;
16847
- return path30.join(os19.homedir(), ".olam", "state", "migration-snapshots");
17132
+ return path32.join(os19.homedir(), ".olam", "state", "migration-snapshots");
16848
17133
  }
16849
17134
  function writeMetaHooksSnapshot(originalSettings) {
16850
17135
  const snapshot = {
@@ -16855,11 +17140,11 @@ function writeMetaHooksSnapshot(originalSettings) {
16855
17140
  };
16856
17141
  const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
16857
17142
  const dir = migrationSnapshotsDir2();
16858
- fs32.mkdirSync(dir, { recursive: true });
17143
+ fs34.mkdirSync(dir, { recursive: true });
16859
17144
  const stamp = validated.takenAt.replace(/[:.]/g, "-");
16860
17145
  const rand = crypto5.randomBytes(3).toString("hex");
16861
- const file2 = path30.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
16862
- fs32.writeFileSync(file2, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
17146
+ const file2 = path32.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
17147
+ fs34.writeFileSync(file2, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
16863
17148
  return file2;
16864
17149
  }
16865
17150
  var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
@@ -17149,7 +17434,7 @@ var init_meta_hook_injector = __esm({
17149
17434
 
17150
17435
  // ../core/dist/lib/markdown-merger.js
17151
17436
  import { createHash as createHash5 } from "node:crypto";
17152
- import { readFileSync as readFileSync30, existsSync as existsSync36, statSync as statSync8 } from "node:fs";
17437
+ import { readFileSync as readFileSync31, existsSync as existsSync38, statSync as statSync9 } from "node:fs";
17153
17438
  function parseFrontmatter(text) {
17154
17439
  const match = FM_RE2.exec(text);
17155
17440
  if (match === null)
@@ -17278,9 +17563,9 @@ function mergeMarkdown(upstreamText, overlayText, labelForError, upstreamPath, o
17278
17563
  return { merged: fmBlock !== "" ? fmBlock + mergedBody : mergedBody };
17279
17564
  }
17280
17565
  function sha256OfPath(p) {
17281
- if (!existsSync36(p) || !statSync8(p).isFile())
17566
+ if (!existsSync38(p) || !statSync9(p).isFile())
17282
17567
  return "MISSING";
17283
- return createHash5("sha256").update(readFileSync30(p)).digest("hex");
17568
+ return createHash5("sha256").update(readFileSync31(p)).digest("hex");
17284
17569
  }
17285
17570
  var FM_RE2, H2_RE;
17286
17571
  var init_markdown_merger = __esm({
@@ -17292,44 +17577,44 @@ var init_markdown_merger = __esm({
17292
17577
  });
17293
17578
 
17294
17579
  // ../core/dist/skill-sync/managed-merge.js
17295
- import * as fs33 from "node:fs";
17296
- import * as path31 from "node:path";
17580
+ import * as fs35 from "node:fs";
17581
+ import * as path33 from "node:path";
17297
17582
  function materializeMergedSkill(opts) {
17298
17583
  const { sourceId, sourcePath, deployBasename, mergedContent, claudeDir: claudeDir2 } = opts;
17299
- const managedDir = path31.join(claudeDir2, ".olam-merged", sourceId, deployBasename);
17300
- const sourceRoot = path31.resolve(path31.join(claudeDir2, ".olam-merged", sourceId));
17301
- const managedResolved = path31.resolve(managedDir);
17302
- if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path31.sep))) {
17584
+ const managedDir = path33.join(claudeDir2, ".olam-merged", sourceId, deployBasename);
17585
+ const sourceRoot = path33.resolve(path33.join(claudeDir2, ".olam-merged", sourceId));
17586
+ const managedResolved = path33.resolve(managedDir);
17587
+ if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path33.sep))) {
17303
17588
  throw new Error(`[managed-merge] refusing to materialize: deployBasename "${deployBasename}" escapes managed root "${sourceRoot}" (resolved to "${managedResolved}")`);
17304
17589
  }
17305
- fs33.mkdirSync(managedDir, { recursive: true });
17306
- const skillMdPath = path31.join(managedDir, "SKILL.md");
17590
+ fs35.mkdirSync(managedDir, { recursive: true });
17591
+ const skillMdPath = path33.join(managedDir, "SKILL.md");
17307
17592
  const tmpPath = `${skillMdPath}.tmp-${process.pid}-${Date.now()}`;
17308
- fs33.writeFileSync(tmpPath, mergedContent);
17309
- fs33.renameSync(tmpPath, skillMdPath);
17310
- const baseEntries = fs33.readdirSync(sourcePath);
17593
+ fs35.writeFileSync(tmpPath, mergedContent);
17594
+ fs35.renameSync(tmpPath, skillMdPath);
17595
+ const baseEntries = fs35.readdirSync(sourcePath);
17311
17596
  for (const entry of baseEntries) {
17312
17597
  if (entry === "SKILL.md")
17313
17598
  continue;
17314
- const linkPath = path31.join(managedDir, entry);
17315
- const targetAbsolute = path31.join(sourcePath, entry);
17316
- const targetRelative = path31.relative(managedDir, targetAbsolute);
17599
+ const linkPath = path33.join(managedDir, entry);
17600
+ const targetAbsolute = path33.join(sourcePath, entry);
17601
+ const targetRelative = path33.relative(managedDir, targetAbsolute);
17317
17602
  try {
17318
- fs33.lstatSync(linkPath);
17319
- fs33.rmSync(linkPath, { recursive: true, force: true });
17603
+ fs35.lstatSync(linkPath);
17604
+ fs35.rmSync(linkPath, { recursive: true, force: true });
17320
17605
  } catch {
17321
17606
  }
17322
- fs33.symlinkSync(targetRelative, linkPath);
17607
+ fs35.symlinkSync(targetRelative, linkPath);
17323
17608
  }
17324
- const managedEntries = fs33.readdirSync(managedDir);
17609
+ const managedEntries = fs35.readdirSync(managedDir);
17325
17610
  const baseEntrySet = new Set(baseEntries);
17326
17611
  for (const entry of managedEntries) {
17327
17612
  if (entry === "SKILL.md")
17328
17613
  continue;
17329
17614
  if (!baseEntrySet.has(entry)) {
17330
- const stalePath = path31.join(managedDir, entry);
17615
+ const stalePath = path33.join(managedDir, entry);
17331
17616
  try {
17332
- fs33.rmSync(stalePath, { recursive: true, force: true });
17617
+ fs35.rmSync(stalePath, { recursive: true, force: true });
17333
17618
  } catch {
17334
17619
  }
17335
17620
  }
@@ -17337,7 +17622,7 @@ function materializeMergedSkill(opts) {
17337
17622
  return managedDir;
17338
17623
  }
17339
17624
  function cleanMergedDir(claudeDir2) {
17340
- fs33.rmSync(path31.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
17625
+ fs35.rmSync(path33.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
17341
17626
  }
17342
17627
  var init_managed_merge = __esm({
17343
17628
  "../core/dist/skill-sync/managed-merge.js"() {
@@ -17435,8 +17720,8 @@ var init_prefix_rules = __esm({
17435
17720
  });
17436
17721
 
17437
17722
  // ../core/dist/skill-sync/prefix-deploy.js
17438
- import * as fs34 from "node:fs";
17439
- import * as path32 from "node:path";
17723
+ import * as fs36 from "node:fs";
17724
+ import * as path34 from "node:path";
17440
17725
  function buildSourcePrefixMap(sources) {
17441
17726
  const byId = /* @__PURE__ */ new Map();
17442
17727
  const scopeById = /* @__PURE__ */ new Map();
@@ -17490,8 +17775,8 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
17490
17775
  continue;
17491
17776
  }
17492
17777
  if (artifact.kind === "skill") {
17493
- const skillMdPath = path32.join(artifact.sourcePath, "SKILL.md");
17494
- const content = fs34.readFileSync(skillMdPath);
17778
+ const skillMdPath = path34.join(artifact.sourcePath, "SKILL.md");
17779
+ const content = fs36.readFileSync(skillMdPath);
17495
17780
  const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
17496
17781
  const managedDir = materializeMergedSkill({
17497
17782
  sourceId: artifact.sourceId,
@@ -17503,7 +17788,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
17503
17788
  artifact.sourcePath = managedDir;
17504
17789
  artifact.deployBasename = renamed;
17505
17790
  } else {
17506
- const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs34.readFileSync(artifact.sourcePath);
17791
+ const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs36.readFileSync(artifact.sourcePath);
17507
17792
  const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
17508
17793
  artifact.resolvedContent = rewritten;
17509
17794
  artifact.deployBasename = renamed;
@@ -17548,19 +17833,19 @@ var init_prefix_deploy = __esm({
17548
17833
  });
17549
17834
 
17550
17835
  // ../core/dist/skill-sync/resolve-source-config.js
17551
- import { readFileSync as readFileSync32, existsSync as existsSync37 } from "node:fs";
17552
- import { join as join36 } from "node:path";
17836
+ import { readFileSync as readFileSync33, existsSync as existsSync39 } from "node:fs";
17837
+ import { join as join38 } from "node:path";
17553
17838
  import { parse as parseYaml4 } from "yaml";
17554
17839
  function sourceConfigPath(clonePath) {
17555
- return join36(clonePath, "shared", "source-config.yaml");
17840
+ return join38(clonePath, "shared", "source-config.yaml");
17556
17841
  }
17557
17842
  function readSourceConfig(clonePath, sourceId) {
17558
- const path60 = sourceConfigPath(clonePath);
17559
- if (!existsSync37(path60))
17843
+ const path62 = sourceConfigPath(clonePath);
17844
+ if (!existsSync39(path62))
17560
17845
  return void 0;
17561
17846
  let raw;
17562
17847
  try {
17563
- raw = readFileSync32(path60, "utf-8");
17848
+ raw = readFileSync33(path62, "utf-8");
17564
17849
  } catch (err) {
17565
17850
  emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
17566
17851
  return void 0;
@@ -17655,16 +17940,16 @@ var init_resolve_source_config = __esm({
17655
17940
  });
17656
17941
 
17657
17942
  // ../core/dist/skill-sync/engine.js
17658
- import * as fs35 from "node:fs";
17943
+ import * as fs37 from "node:fs";
17659
17944
  import * as os20 from "node:os";
17660
- import * as path33 from "node:path";
17945
+ import * as path35 from "node:path";
17661
17946
  function resolveAtlasUser(override) {
17662
17947
  if (override)
17663
17948
  return override;
17664
- const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path33.join(os20.homedir(), ".claude");
17665
- const f = path33.join(claudeDir2, ".atlas-user");
17666
- if (fs35.existsSync(f)) {
17667
- return fs35.readFileSync(f, "utf-8").trim() || void 0;
17949
+ const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path35.join(os20.homedir(), ".claude");
17950
+ const f = path35.join(claudeDir2, ".atlas-user");
17951
+ if (fs37.existsSync(f)) {
17952
+ return fs37.readFileSync(f, "utf-8").trim() || void 0;
17668
17953
  }
17669
17954
  return void 0;
17670
17955
  }
@@ -17676,7 +17961,7 @@ async function syncSkills(opts = {}) {
17676
17961
  const perSource = [];
17677
17962
  for (const source of sources) {
17678
17963
  const clonePath = skillSourceClonePath(source.id);
17679
- if (!fs35.existsSync(clonePath))
17964
+ if (!fs37.existsSync(clonePath))
17680
17965
  continue;
17681
17966
  const { artifacts, subscription } = await withFileLock(clonePath, () => {
17682
17967
  const pinRef = projectOverride?.override.pin?.[source.id];
@@ -17716,7 +18001,7 @@ async function syncSkills(opts = {}) {
17716
18001
  const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
17717
18002
  const effectiveSources = sources.map((s) => {
17718
18003
  const clonePath = skillSourceClonePath(s.id);
17719
- const sourceConfig = fs35.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
18004
+ const sourceConfig = fs37.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
17720
18005
  const eff = resolveEffectivePrefix(s, sourceConfig);
17721
18006
  const entry = {
17722
18007
  id: s.id,
@@ -17822,13 +18107,13 @@ async function syncSkills(opts = {}) {
17822
18107
  let baseContent;
17823
18108
  let basePath;
17824
18109
  if (overlay.targetKind === "skill") {
17825
- basePath = path33.join(base.sourcePath, "SKILL.md");
17826
- baseContent = fs35.readFileSync(basePath, "utf-8");
18110
+ basePath = path35.join(base.sourcePath, "SKILL.md");
18111
+ baseContent = fs37.readFileSync(basePath, "utf-8");
17827
18112
  } else {
17828
18113
  basePath = base.sourcePath;
17829
- baseContent = fs35.readFileSync(basePath, "utf-8");
18114
+ baseContent = fs37.readFileSync(basePath, "utf-8");
17830
18115
  }
17831
- const overlayContent = fs35.readFileSync(overlay.sourcePath, "utf-8");
18116
+ const overlayContent = fs37.readFileSync(overlay.sourcePath, "utf-8");
17832
18117
  const label = `${overlay.sourceId}/${overlay.deployBasename}`;
17833
18118
  const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
17834
18119
  if ("error" in mergeResult) {
@@ -17889,7 +18174,7 @@ async function syncSkills(opts = {}) {
17889
18174
  summary.collisions = detectCollisions(baseArtifacts).collisions;
17890
18175
  return summary;
17891
18176
  }
17892
- const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path33.join(os20.homedir(), ".claude");
18177
+ const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path35.join(os20.homedir(), ".claude");
17893
18178
  const overlayReferences = scanOverlayReferences(claudeDirPath, SHIM_TARGETS.map((t) => t.basename));
17894
18179
  summary.deploy = deployArtifacts(baseArtifacts, {
17895
18180
  installedOlamVersion,
@@ -17925,19 +18210,19 @@ async function injectMetaHooksIntoSettings(opts) {
17925
18210
  const result = await withSettingsJsonLock(() => {
17926
18211
  let currentSettings = {};
17927
18212
  let settingsExisted = false;
17928
- if (fs35.existsSync(settingsFile)) {
18213
+ if (fs37.existsSync(settingsFile)) {
17929
18214
  settingsExisted = true;
17930
18215
  try {
17931
- const raw = fs35.readFileSync(settingsFile, "utf-8");
18216
+ const raw = fs37.readFileSync(settingsFile, "utf-8");
17932
18217
  currentSettings = raw.trim() ? JSON.parse(raw) : {};
17933
18218
  } catch {
17934
18219
  try {
17935
- const raw = fs35.readFileSync(settingsFile);
17936
- const bakDir = path33.join(path33.dirname(settingsFile), ".malformed-backups");
17937
- fs35.mkdirSync(bakDir, { recursive: true });
18220
+ const raw = fs37.readFileSync(settingsFile);
18221
+ const bakDir = path35.join(path35.dirname(settingsFile), ".malformed-backups");
18222
+ fs37.mkdirSync(bakDir, { recursive: true });
17938
18223
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
17939
- const bakFile = path33.join(bakDir, `settings.json.malformed.${stamp}.bak`);
17940
- fs35.writeFileSync(bakFile, raw, { mode: 384 });
18224
+ const bakFile = path35.join(bakDir, `settings.json.malformed.${stamp}.bak`);
18225
+ fs37.writeFileSync(bakFile, raw, { mode: 384 });
17941
18226
  snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
17942
18227
  } catch (bakErr) {
17943
18228
  snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
@@ -17977,10 +18262,10 @@ async function injectMetaHooksIntoSettings(opts) {
17977
18262
  } catch {
17978
18263
  }
17979
18264
  }
17980
- fs35.mkdirSync(path33.dirname(settingsFile), { recursive: true });
18265
+ fs37.mkdirSync(path35.dirname(settingsFile), { recursive: true });
17981
18266
  const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
17982
- fs35.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
17983
- fs35.renameSync(tmpPath, settingsFile);
18267
+ fs37.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
18268
+ fs37.renameSync(tmpPath, settingsFile);
17984
18269
  return inject;
17985
18270
  }, { reason: `syncSkills meta-hook injection (mode=${mode})` });
17986
18271
  let scriptDeploy;
@@ -17988,7 +18273,7 @@ async function injectMetaHooksIntoSettings(opts) {
17988
18273
  if (modelRouterTargeted) {
17989
18274
  try {
17990
18275
  scriptDeploy = deployModelRouterScript({
17991
- targetDir: path33.join(claudeDir(), "hooks")
18276
+ targetDir: path35.join(claudeDir(), "hooks")
17992
18277
  });
17993
18278
  } catch (err) {
17994
18279
  scriptDeploy = {
@@ -18039,19 +18324,19 @@ var init_engine = __esm({
18039
18324
  });
18040
18325
 
18041
18326
  // ../core/dist/skill-sync/shadow-backup-manager.js
18042
- import * as fs36 from "node:fs";
18043
- import * as path34 from "node:path";
18327
+ import * as fs38 from "node:fs";
18328
+ import * as path36 from "node:path";
18044
18329
  function listShadowBackups(opts = {}) {
18045
18330
  const claude = opts.claudeDirOverride ?? claudeDir();
18046
18331
  const now = opts.now ?? Date.now();
18047
18332
  const out = [];
18048
18333
  for (const bucket of SHADOW_BACKUP_BUCKETS) {
18049
- const bucketDir = path34.join(claude, bucket);
18050
- if (!fs36.existsSync(bucketDir))
18334
+ const bucketDir = path36.join(claude, bucket);
18335
+ if (!fs38.existsSync(bucketDir))
18051
18336
  continue;
18052
18337
  let entries;
18053
18338
  try {
18054
- entries = fs36.readdirSync(bucketDir);
18339
+ entries = fs38.readdirSync(bucketDir);
18055
18340
  } catch {
18056
18341
  continue;
18057
18342
  }
@@ -18062,11 +18347,11 @@ function listShadowBackups(opts = {}) {
18062
18347
  const epochSeconds = Number.parseInt(match[1], 10);
18063
18348
  if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
18064
18349
  continue;
18065
- const full = path34.join(bucketDir, name);
18350
+ const full = path36.join(bucketDir, name);
18066
18351
  let sizeBytes = 0;
18067
18352
  let isDir = false;
18068
18353
  try {
18069
- const st = fs36.statSync(full);
18354
+ const st = fs38.statSync(full);
18070
18355
  isDir = st.isDirectory();
18071
18356
  if (!isDir)
18072
18357
  sizeBytes = st.size;
@@ -18079,7 +18364,7 @@ function listShadowBackups(opts = {}) {
18079
18364
  bucket,
18080
18365
  basename: name,
18081
18366
  originalBasename,
18082
- originalPath: path34.join(bucketDir, originalBasename),
18367
+ originalPath: path36.join(bucketDir, originalBasename),
18083
18368
  epochSeconds,
18084
18369
  ageMs: now - epochSeconds * 1e3,
18085
18370
  sizeBytes,
@@ -18124,9 +18409,9 @@ function pruneShadowBackups(opts) {
18124
18409
  if (!opts.dryRun) {
18125
18410
  try {
18126
18411
  if (b.isDir) {
18127
- fs36.rmSync(b.path, { recursive: true, force: true });
18412
+ fs38.rmSync(b.path, { recursive: true, force: true });
18128
18413
  } else {
18129
- fs36.unlinkSync(b.path);
18414
+ fs38.unlinkSync(b.path);
18130
18415
  }
18131
18416
  } catch {
18132
18417
  skipped.push(b);
@@ -18138,29 +18423,29 @@ function pruneShadowBackups(opts) {
18138
18423
  return { deleted, skipped };
18139
18424
  }
18140
18425
  function restoreShadowBackup(opts) {
18141
- const abs = path34.resolve(opts.backupPath);
18142
- if (!fs36.existsSync(abs)) {
18426
+ const abs = path36.resolve(opts.backupPath);
18427
+ if (!fs38.existsSync(abs)) {
18143
18428
  throw new Error(`backup file not found: ${abs}`);
18144
18429
  }
18145
- const basename6 = path34.basename(abs);
18430
+ const basename6 = path36.basename(abs);
18146
18431
  const match = SHADOW_BACKUP_SUFFIX_RE.exec(basename6);
18147
18432
  if (!match) {
18148
18433
  throw new Error(`not a shadow-backup file (basename "${basename6}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
18149
18434
  }
18150
18435
  const originalBasename = basename6.slice(0, basename6.length - match[0].length);
18151
- const originalPath = path34.join(path34.dirname(abs), originalBasename);
18152
- if (fs36.existsSync(originalPath) && !opts.force) {
18436
+ const originalPath = path36.join(path36.dirname(abs), originalBasename);
18437
+ if (fs38.existsSync(originalPath) && !opts.force) {
18153
18438
  throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
18154
18439
  }
18155
- if (opts.force && fs36.existsSync(originalPath)) {
18156
- const existingStat = fs36.statSync(originalPath);
18440
+ if (opts.force && fs38.existsSync(originalPath)) {
18441
+ const existingStat = fs38.statSync(originalPath);
18157
18442
  if (existingStat.isDirectory()) {
18158
- fs36.rmSync(originalPath, { recursive: true, force: true });
18443
+ fs38.rmSync(originalPath, { recursive: true, force: true });
18159
18444
  } else {
18160
- fs36.unlinkSync(originalPath);
18445
+ fs38.unlinkSync(originalPath);
18161
18446
  }
18162
18447
  }
18163
- fs36.renameSync(abs, originalPath);
18448
+ fs38.renameSync(abs, originalPath);
18164
18449
  return { restoredTo: originalPath };
18165
18450
  }
18166
18451
  var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
@@ -18174,14 +18459,14 @@ var init_shadow_backup_manager = __esm({
18174
18459
  });
18175
18460
 
18176
18461
  // ../core/dist/skill-sources/doctor-checks.js
18177
- import * as fs37 from "node:fs";
18178
- import * as path35 from "node:path";
18462
+ import * as fs39 from "node:fs";
18463
+ import * as path37 from "node:path";
18179
18464
  import * as os21 from "node:os";
18180
18465
  function claudeDirInternal3() {
18181
18466
  const override = process.env["OLAM_CLAUDE_DIR"];
18182
18467
  if (override && override.length > 0)
18183
18468
  return override;
18184
- return path35.join(os21.homedir(), ".claude");
18469
+ return path37.join(os21.homedir(), ".claude");
18185
18470
  }
18186
18471
  function checkStateFileParse() {
18187
18472
  const filePath = globalConfigPath();
@@ -18190,11 +18475,11 @@ function checkStateFileParse() {
18190
18475
  healthy: true,
18191
18476
  description: `~/.olam state file (${filePath})`
18192
18477
  };
18193
- if (!fs37.existsSync(filePath)) {
18478
+ if (!fs39.existsSync(filePath)) {
18194
18479
  result.details = ["(file does not yet exist \u2014 will be created on first write)"];
18195
18480
  return result;
18196
18481
  }
18197
- const raw = fs37.readFileSync(filePath, "utf-8");
18482
+ const raw = fs39.readFileSync(filePath, "utf-8");
18198
18483
  let parsed;
18199
18484
  try {
18200
18485
  parsed = JSON.parse(raw);
@@ -18204,8 +18489,8 @@ function checkStateFileParse() {
18204
18489
  result.details = [err instanceof Error ? err.message : String(err)];
18205
18490
  result.repair = () => {
18206
18491
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
18207
- fs37.renameSync(filePath, aside);
18208
- fs37.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
18492
+ fs39.renameSync(filePath, aside);
18493
+ fs39.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
18209
18494
  };
18210
18495
  return result;
18211
18496
  }
@@ -18214,18 +18499,20 @@ function checkStateFileParse() {
18214
18499
  result.healthy = false;
18215
18500
  result.issue = "state file does not match GlobalConfigSchema";
18216
18501
  result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
18502
+ const salvaged = quarantineGlobalConfig(parsed);
18503
+ const droppedCount = salvaged?.drops.length ?? 0;
18504
+ if (salvaged !== null) {
18505
+ result.details.push(`auto-fix will keep ${salvaged.value.skillSources.length} skill-source(s), ${salvaged.value.repos.length} repo(s), ${salvaged.value.runbooks.length} runbook(s); dropping ${droppedCount} invalid entr${droppedCount === 1 ? "y" : "ies"}.`);
18506
+ } else {
18507
+ result.details.push("auto-fix cannot salvage any entries (top-level corruption) \u2014 will reset to empty.");
18508
+ }
18217
18509
  result.repair = () => {
18218
18510
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
18219
- fs37.copyFileSync(filePath, aside);
18511
+ fs39.copyFileSync(filePath, aside);
18220
18512
  const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
18221
- const next = {
18222
- ...base,
18223
- schemaVersion: 1,
18224
- repos: [],
18225
- runbooks: [],
18226
- skillSources: []
18227
- };
18228
- fs37.writeFileSync(filePath, JSON.stringify(next, null, 2));
18513
+ const recovered = quarantineGlobalConfig(parsed);
18514
+ const next = recovered !== null ? { ...base, ...recovered.value } : { ...base, schemaVersion: 1, repos: [], runbooks: [], skillSources: [] };
18515
+ fs39.writeFileSync(filePath, JSON.stringify(next, null, 2));
18229
18516
  };
18230
18517
  return result;
18231
18518
  }
@@ -18236,16 +18523,16 @@ function checkDanglingSymlinks() {
18236
18523
  const buckets = ["commands", "agents", "skills", "scripts", "rules"];
18237
18524
  const dangling = [];
18238
18525
  for (const bucket of buckets) {
18239
- const dir = path35.join(claude, bucket);
18240
- if (!fs37.existsSync(dir))
18526
+ const dir = path37.join(claude, bucket);
18527
+ if (!fs39.existsSync(dir))
18241
18528
  continue;
18242
- for (const name of fs37.readdirSync(dir)) {
18243
- const linkPath = path35.join(dir, name);
18529
+ for (const name of fs39.readdirSync(dir)) {
18530
+ const linkPath = path37.join(dir, name);
18244
18531
  try {
18245
- const lst = fs37.lstatSync(linkPath);
18532
+ const lst = fs39.lstatSync(linkPath);
18246
18533
  if (!lst.isSymbolicLink())
18247
18534
  continue;
18248
- if (!fs37.existsSync(linkPath)) {
18535
+ if (!fs39.existsSync(linkPath)) {
18249
18536
  dangling.push(linkPath);
18250
18537
  }
18251
18538
  } catch {
@@ -18263,7 +18550,7 @@ function checkDanglingSymlinks() {
18263
18550
  result.repair = () => {
18264
18551
  for (const p of dangling) {
18265
18552
  try {
18266
- fs37.unlinkSync(p);
18553
+ fs39.unlinkSync(p);
18267
18554
  } catch {
18268
18555
  }
18269
18556
  }
@@ -18278,19 +18565,19 @@ function checkOrphanedSnapshots() {
18278
18565
  healthy: true,
18279
18566
  description: `orphaned migration snapshots under ${dir}`
18280
18567
  };
18281
- if (!fs37.existsSync(dir)) {
18568
+ if (!fs39.existsSync(dir)) {
18282
18569
  return result;
18283
18570
  }
18284
18571
  const orphans = [];
18285
- for (const name of fs37.readdirSync(dir)) {
18572
+ for (const name of fs39.readdirSync(dir)) {
18286
18573
  if (!name.endsWith(".json"))
18287
18574
  continue;
18288
- const full = path35.join(dir, name);
18575
+ const full = path37.join(dir, name);
18289
18576
  try {
18290
- const stat2 = fs37.statSync(full);
18577
+ const stat2 = fs39.statSync(full);
18291
18578
  if (!stat2.isFile())
18292
18579
  continue;
18293
- const raw = fs37.readFileSync(full, "utf-8");
18580
+ const raw = fs39.readFileSync(full, "utf-8");
18294
18581
  let parsed;
18295
18582
  try {
18296
18583
  parsed = JSON.parse(raw);
@@ -18315,7 +18602,7 @@ function checkOrphanedSnapshots() {
18315
18602
  result.repair = () => {
18316
18603
  for (const o of orphans) {
18317
18604
  try {
18318
- fs37.unlinkSync(o.path);
18605
+ fs39.unlinkSync(o.path);
18319
18606
  } catch {
18320
18607
  }
18321
18608
  }
@@ -18330,12 +18617,12 @@ function checkSentinelDrift() {
18330
18617
  healthy: true,
18331
18618
  description: `olam-skills sentinel block in ${filePath}`
18332
18619
  };
18333
- if (!fs37.existsSync(filePath)) {
18620
+ if (!fs39.existsSync(filePath)) {
18334
18621
  return result;
18335
18622
  }
18336
18623
  let parsed;
18337
18624
  try {
18338
- parsed = JSON.parse(fs37.readFileSync(filePath, "utf-8"));
18625
+ parsed = JSON.parse(fs39.readFileSync(filePath, "utf-8"));
18339
18626
  } catch {
18340
18627
  return result;
18341
18628
  }
@@ -18376,7 +18663,7 @@ function checkSentinelDrift() {
18376
18663
  backupSettings();
18377
18664
  } catch {
18378
18665
  }
18379
- const next = JSON.parse(fs37.readFileSync(filePath, "utf-8"));
18666
+ const next = JSON.parse(fs39.readFileSync(filePath, "utf-8"));
18380
18667
  if (!next.hooks)
18381
18668
  return;
18382
18669
  for (const stage of Object.keys(next.hooks)) {
@@ -18399,7 +18686,7 @@ function checkSentinelDrift() {
18399
18686
  return bad === void 0;
18400
18687
  });
18401
18688
  }
18402
- fs37.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
18689
+ fs39.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
18403
18690
  };
18404
18691
  }
18405
18692
  return result;
@@ -18423,8 +18710,8 @@ function checkMemberNameMissing() {
18423
18710
  return result;
18424
18711
  }
18425
18712
  const claudeDir2 = claudeDirInternal3();
18426
- const atlasUserPath = path35.join(claudeDir2, ".atlas-user");
18427
- const value = fs37.existsSync(atlasUserPath) ? fs37.readFileSync(atlasUserPath, "utf-8").trim() : "";
18713
+ const atlasUserPath = path37.join(claudeDir2, ".atlas-user");
18714
+ const value = fs39.existsSync(atlasUserPath) ? fs39.readFileSync(atlasUserPath, "utf-8").trim() : "";
18428
18715
  if (value.length > 0) {
18429
18716
  result.details = [`atlas-user: ${value}`];
18430
18717
  return result;
@@ -18432,10 +18719,10 @@ function checkMemberNameMissing() {
18432
18719
  result.healthy = false;
18433
18720
  result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
18434
18721
  const clonePath = skillSourceClonePath(atlasSource.id);
18435
- const membersDir = path35.join(clonePath, "members");
18436
- const existing = fs37.existsSync(membersDir) ? fs37.readdirSync(membersDir).filter((e) => {
18722
+ const membersDir = path37.join(clonePath, "members");
18723
+ const existing = fs39.existsSync(membersDir) ? fs39.readdirSync(membersDir).filter((e) => {
18437
18724
  try {
18438
- return fs37.statSync(path35.join(membersDir, e)).isDirectory();
18725
+ return fs39.statSync(path37.join(membersDir, e)).isDirectory();
18439
18726
  } catch {
18440
18727
  return false;
18441
18728
  }
@@ -18449,8 +18736,8 @@ function checkMemberNameMissing() {
18449
18736
  }
18450
18737
  function checkMemberOverlayDrift() {
18451
18738
  const claudeDir2 = claudeDirInternal3();
18452
- const atlasUserPath = path35.join(claudeDir2, ".atlas-user");
18453
- const atlasUser = fs37.existsSync(atlasUserPath) ? fs37.readFileSync(atlasUserPath, "utf-8").trim() : "";
18739
+ const atlasUserPath = path37.join(claudeDir2, ".atlas-user");
18740
+ const atlasUser = fs39.existsSync(atlasUserPath) ? fs39.readFileSync(atlasUserPath, "utf-8").trim() : "";
18454
18741
  if (atlasUser.length === 0) {
18455
18742
  return [];
18456
18743
  }
@@ -18466,26 +18753,26 @@ function checkMemberOverlayDrift() {
18466
18753
  const clonePath = skillSourceClonePath(atlasSource.id);
18467
18754
  const results = [];
18468
18755
  for (const kind of ["skills", "agents"]) {
18469
- const localRoot = path35.join(claudeDir2, `${kind}.overrides`);
18470
- if (!fs37.existsSync(localRoot))
18756
+ const localRoot = path37.join(claudeDir2, `${kind}.overrides`);
18757
+ if (!fs39.existsSync(localRoot))
18471
18758
  continue;
18472
18759
  let entries;
18473
18760
  try {
18474
- entries = fs37.readdirSync(localRoot);
18761
+ entries = fs39.readdirSync(localRoot);
18475
18762
  } catch {
18476
18763
  continue;
18477
18764
  }
18478
18765
  for (const entry of entries) {
18479
- const localFile = path35.join(localRoot, entry);
18766
+ const localFile = path37.join(localRoot, entry);
18480
18767
  let stat2;
18481
18768
  try {
18482
- stat2 = fs37.statSync(localFile);
18769
+ stat2 = fs39.statSync(localFile);
18483
18770
  } catch {
18484
18771
  continue;
18485
18772
  }
18486
18773
  if (!stat2.isFile())
18487
18774
  continue;
18488
- const cloneFile = path35.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
18775
+ const cloneFile = path37.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
18489
18776
  const localSha = sha256OfPath(localFile);
18490
18777
  const cloneSha = sha256OfPath(cloneFile);
18491
18778
  if (localSha === cloneSha) {
@@ -18540,16 +18827,16 @@ var init_doctor_checks = __esm({
18540
18827
  });
18541
18828
 
18542
18829
  // ../core/dist/skill-sync/detect-pull-deploy-drift.js
18543
- import * as fs38 from "node:fs";
18544
- import * as path36 from "node:path";
18830
+ import * as fs40 from "node:fs";
18831
+ import * as path38 from "node:path";
18545
18832
  function deployedSymlinkBasenames(bucketDir) {
18546
18833
  const result = /* @__PURE__ */ new Set();
18547
- if (!fs38.existsSync(bucketDir))
18834
+ if (!fs40.existsSync(bucketDir))
18548
18835
  return result;
18549
- for (const name of fs38.readdirSync(bucketDir)) {
18550
- const p = path36.join(bucketDir, name);
18836
+ for (const name of fs40.readdirSync(bucketDir)) {
18837
+ const p = path38.join(bucketDir, name);
18551
18838
  try {
18552
- if (fs38.lstatSync(p).isSymbolicLink()) {
18839
+ if (fs40.lstatSync(p).isSymbolicLink()) {
18553
18840
  result.add(name);
18554
18841
  }
18555
18842
  } catch {
@@ -18560,7 +18847,7 @@ function deployedSymlinkBasenames(bucketDir) {
18560
18847
  function detectPullDeployDrift(opts) {
18561
18848
  const { clonePath, sourceId, atlasUser } = opts;
18562
18849
  const { artifacts } = resolveSourceArtifacts({ sourceId, clonePath, atlasUser });
18563
- const sourceConfig = fs38.existsSync(clonePath) ? readSourceConfig(clonePath, sourceId) : void 0;
18850
+ const sourceConfig = fs40.existsSync(clonePath) ? readSourceConfig(clonePath, sourceId) : void 0;
18564
18851
  const eff = resolveEffectivePrefix(opts.operatorSource ?? {}, sourceConfig);
18565
18852
  const prefixEntry = { id: sourceId };
18566
18853
  if (eff.prefix !== void 0)
@@ -18597,7 +18884,7 @@ function detectPullDeployDrift(opts) {
18597
18884
  let total = 0;
18598
18885
  for (const kind of Object.keys(KIND_TO_BUCKET)) {
18599
18886
  const bucket = KIND_TO_BUCKET[kind];
18600
- const bucketDir = path36.join(claude, bucket);
18887
+ const bucketDir = path38.join(claude, bucket);
18601
18888
  const deployed = deployedSymlinkBasenames(bucketDir);
18602
18889
  const cloneBasenames = cloneByKind[kind];
18603
18890
  const added = [];
@@ -18648,11 +18935,13 @@ __export(skill_sources_exports, {
18648
18935
  PROJECT_OVERRIDE_RELATIVE_PATH: () => PROJECT_OVERRIDE_RELATIVE_PATH,
18649
18936
  SKILL_SOURCES_AUDIT_LOG_FILENAME: () => SKILL_SOURCES_AUDIT_LOG_FILENAME,
18650
18937
  SKILL_SOURCE_ID_LENGTH: () => SKILL_SOURCE_ID_LENGTH,
18938
+ SOURCE_SIDECAR_FILENAME: () => SOURCE_SIDECAR_FILENAME,
18651
18939
  SkillOverrideSchema: () => SkillOverrideSchema,
18652
18940
  SkillSourceGitError: () => SkillSourceGitError,
18653
18941
  SkillSourceSchema: () => SkillSourceSchema,
18654
18942
  SourceConfigSchema: () => SourceConfigSchema,
18655
18943
  SourceConfigSnapshotSchema: () => SourceConfigSnapshotSchema,
18944
+ SourceSidecarSchema: () => SourceSidecarSchema,
18656
18945
  TrustActionSchema: () => TrustActionSchema,
18657
18946
  TrustAuditEntrySchema: () => TrustAuditEntrySchema,
18658
18947
  TrustMethodSchema: () => TrustMethodSchema,
@@ -18694,7 +18983,10 @@ __export(skill_sources_exports, {
18694
18983
  readLatestMigrationSnapshot: () => readLatestMigrationSnapshot,
18695
18984
  readMigrationSnapshotFromPath: () => readMigrationSnapshotFromPath,
18696
18985
  readSourceConfig: () => readSourceConfig,
18986
+ readSourceSidecar: () => readSourceSidecar,
18697
18987
  readTrustAuditLog: () => readTrustAuditLog,
18988
+ reconcileIfRegistryEmpty: () => reconcileIfRegistryEmpty,
18989
+ reconcileSkillSources: () => reconcileSkillSources,
18698
18990
  redactUrl: () => redactUrl2,
18699
18991
  removeSkillSource: () => removeSkillSource,
18700
18992
  removeSkillSourceClone: () => removeSkillSourceClone,
@@ -18713,11 +19005,13 @@ __export(skill_sources_exports, {
18713
19005
  skillsHookSettingsPathFor: () => settingsPathFor,
18714
19006
  sourceConfigPath: () => sourceConfigPath,
18715
19007
  sourceConfigsEqual: () => sourceConfigsEqual,
19008
+ sourceSidecarPath: () => sourceSidecarPath,
18716
19009
  syncSkills: () => syncSkills,
18717
19010
  uninstallSkillsHookFromFile: () => uninstallSkillsHookFromFile,
18718
19011
  updateSkillSource: () => updateSkillSource,
18719
19012
  withFileLock: () => withFileLock,
18720
- writeMigrationSnapshot: () => writeMigrationSnapshot
19013
+ writeMigrationSnapshot: () => writeMigrationSnapshot,
19014
+ writeSourceSidecar: () => writeSourceSidecar
18721
19015
  });
18722
19016
  var init_skill_sources = __esm({
18723
19017
  "../core/dist/skill-sources/index.js"() {
@@ -18725,6 +19019,8 @@ var init_skill_sources = __esm({
18725
19019
  init_schema3();
18726
19020
  init_store3();
18727
19021
  init_clone();
19022
+ init_source_file();
19023
+ init_reconcile();
18728
19024
  init_hook_template();
18729
19025
  init_hook_install();
18730
19026
  init_migration_snapshot();
@@ -19530,10 +19826,10 @@ function mergeDefs(...defs) {
19530
19826
  function cloneDef(schema) {
19531
19827
  return mergeDefs(schema._zod.def);
19532
19828
  }
19533
- function getElementAtPath(obj, path60) {
19534
- if (!path60)
19829
+ function getElementAtPath(obj, path62) {
19830
+ if (!path62)
19535
19831
  return obj;
19536
- return path60.reduce((acc, key) => acc?.[key], obj);
19832
+ return path62.reduce((acc, key) => acc?.[key], obj);
19537
19833
  }
19538
19834
  function promiseAllObject(promisesObj) {
19539
19835
  const keys = Object.keys(promisesObj);
@@ -19942,11 +20238,11 @@ function explicitlyAborted(x, startIndex = 0) {
19942
20238
  }
19943
20239
  return false;
19944
20240
  }
19945
- function prefixIssues(path60, issues) {
20241
+ function prefixIssues(path62, issues) {
19946
20242
  return issues.map((iss) => {
19947
20243
  var _a3;
19948
20244
  (_a3 = iss).path ?? (_a3.path = []);
19949
- iss.path.unshift(path60);
20245
+ iss.path.unshift(path62);
19950
20246
  return iss;
19951
20247
  });
19952
20248
  }
@@ -20093,16 +20389,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
20093
20389
  }
20094
20390
  function formatError(error51, mapper = (issue2) => issue2.message) {
20095
20391
  const fieldErrors = { _errors: [] };
20096
- const processError = (error52, path60 = []) => {
20392
+ const processError = (error52, path62 = []) => {
20097
20393
  for (const issue2 of error52.issues) {
20098
20394
  if (issue2.code === "invalid_union" && issue2.errors.length) {
20099
- issue2.errors.map((issues) => processError({ issues }, [...path60, ...issue2.path]));
20395
+ issue2.errors.map((issues) => processError({ issues }, [...path62, ...issue2.path]));
20100
20396
  } else if (issue2.code === "invalid_key") {
20101
- processError({ issues: issue2.issues }, [...path60, ...issue2.path]);
20397
+ processError({ issues: issue2.issues }, [...path62, ...issue2.path]);
20102
20398
  } else if (issue2.code === "invalid_element") {
20103
- processError({ issues: issue2.issues }, [...path60, ...issue2.path]);
20399
+ processError({ issues: issue2.issues }, [...path62, ...issue2.path]);
20104
20400
  } else {
20105
- const fullpath = [...path60, ...issue2.path];
20401
+ const fullpath = [...path62, ...issue2.path];
20106
20402
  if (fullpath.length === 0) {
20107
20403
  fieldErrors._errors.push(mapper(issue2));
20108
20404
  } else {
@@ -20129,17 +20425,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
20129
20425
  }
20130
20426
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
20131
20427
  const result = { errors: [] };
20132
- const processError = (error52, path60 = []) => {
20428
+ const processError = (error52, path62 = []) => {
20133
20429
  var _a3, _b;
20134
20430
  for (const issue2 of error52.issues) {
20135
20431
  if (issue2.code === "invalid_union" && issue2.errors.length) {
20136
- issue2.errors.map((issues) => processError({ issues }, [...path60, ...issue2.path]));
20432
+ issue2.errors.map((issues) => processError({ issues }, [...path62, ...issue2.path]));
20137
20433
  } else if (issue2.code === "invalid_key") {
20138
- processError({ issues: issue2.issues }, [...path60, ...issue2.path]);
20434
+ processError({ issues: issue2.issues }, [...path62, ...issue2.path]);
20139
20435
  } else if (issue2.code === "invalid_element") {
20140
- processError({ issues: issue2.issues }, [...path60, ...issue2.path]);
20436
+ processError({ issues: issue2.issues }, [...path62, ...issue2.path]);
20141
20437
  } else {
20142
- const fullpath = [...path60, ...issue2.path];
20438
+ const fullpath = [...path62, ...issue2.path];
20143
20439
  if (fullpath.length === 0) {
20144
20440
  result.errors.push(mapper(issue2));
20145
20441
  continue;
@@ -20171,8 +20467,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
20171
20467
  }
20172
20468
  function toDotPath(_path) {
20173
20469
  const segs = [];
20174
- const path60 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
20175
- for (const seg of path60) {
20470
+ const path62 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
20471
+ for (const seg of path62) {
20176
20472
  if (typeof seg === "number")
20177
20473
  segs.push(`[${seg}]`);
20178
20474
  else if (typeof seg === "symbol")
@@ -32864,13 +33160,13 @@ function resolveRef(ref, ctx) {
32864
33160
  if (!ref.startsWith("#")) {
32865
33161
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
32866
33162
  }
32867
- const path60 = ref.slice(1).split("/").filter(Boolean);
32868
- if (path60.length === 0) {
33163
+ const path62 = ref.slice(1).split("/").filter(Boolean);
33164
+ if (path62.length === 0) {
32869
33165
  return ctx.rootSchema;
32870
33166
  }
32871
33167
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
32872
- if (path60[0] === defsKey) {
32873
- const key = path60[1];
33168
+ if (path62[0] === defsKey) {
33169
+ const key = path62[1];
32874
33170
  if (!key || !ctx.defs[key]) {
32875
33171
  throw new Error(`Reference not found: ${ref}`);
32876
33172
  }
@@ -39370,8 +39666,8 @@ var initSkill = defineSkill({
39370
39666
  // ../mcp-server/src/lib/validated-tool.ts
39371
39667
  function formatIssues(issues) {
39372
39668
  return issues.map((issue2) => {
39373
- const path60 = issue2.path.length > 0 ? issue2.path.join(".") : "<root>";
39374
- return `${path60}: ${issue2.message}`;
39669
+ const path62 = issue2.path.length > 0 ? issue2.path.join(".") : "<root>";
39670
+ return `${path62}: ${issue2.message}`;
39375
39671
  }).join("; ");
39376
39672
  }
39377
39673
  function validatedTool(server, skill, name, handler) {
@@ -39722,8 +40018,8 @@ var AuthClient = class {
39722
40018
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
39723
40019
  }
39724
40020
  }
39725
- async request(method, path60, body, attempt = 0) {
39726
- const url3 = `${this.baseUrl}${path60}`;
40021
+ async request(method, path62, body, attempt = 0) {
40022
+ const url3 = `${this.baseUrl}${path62}`;
39727
40023
  const controller = new AbortController();
39728
40024
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
39729
40025
  const headers = {};
@@ -39741,7 +40037,7 @@ var AuthClient = class {
39741
40037
  } catch (err) {
39742
40038
  if (attempt < RETRY_COUNT && isTransient(err)) {
39743
40039
  await sleep(RETRY_BACKOFF_MS * (attempt + 1));
39744
- return this.request(method, path60, body, attempt + 1);
40040
+ return this.request(method, path62, body, attempt + 1);
39745
40041
  }
39746
40042
  throw err;
39747
40043
  } finally {
@@ -40740,12 +41036,12 @@ function register3(server, _ctx, _initError) {
40740
41036
  registry2.close();
40741
41037
  }
40742
41038
  try {
40743
- const { default: fs60 } = await import("node:fs");
41039
+ const { default: fs62 } = await import("node:fs");
40744
41040
  const { default: os36 } = await import("node:os");
40745
- const { default: path60 } = await import("node:path");
40746
- const tokenPath = path60.join(os36.homedir(), ".olam", "host-cp.token");
40747
- if (fs60.existsSync(tokenPath)) {
40748
- const token = fs60.readFileSync(tokenPath, "utf-8").trim();
41041
+ const { default: path62 } = await import("node:path");
41042
+ const tokenPath = path62.join(os36.homedir(), ".olam", "host-cp.token");
41043
+ if (fs62.existsSync(tokenPath)) {
41044
+ const token = fs62.readFileSync(tokenPath, "utf-8").trim();
40749
41045
  await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
40750
41046
  method: "POST",
40751
41047
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
@@ -41050,10 +41346,10 @@ function extractMcpConfig(claudeJsonPath) {
41050
41346
  }
41051
41347
  return { mcpServers, secrets };
41052
41348
  }
41053
- function readOptional(path60) {
41054
- if (!existsSync7(path60)) return null;
41349
+ function readOptional(path62) {
41350
+ if (!existsSync7(path62)) return null;
41055
41351
  try {
41056
- return readFileSync5(path60, "utf8");
41352
+ return readFileSync5(path62, "utf8");
41057
41353
  } catch {
41058
41354
  return null;
41059
41355
  }
@@ -44232,10 +44528,10 @@ async function writeManifest(args) {
44232
44528
  capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
44233
44529
  shots: entries
44234
44530
  };
44235
- const path60 = join14(args.outDir, "manifest.json");
44236
- await writeFile(path60, `${JSON.stringify(manifest, null, 2)}
44531
+ const path62 = join14(args.outDir, "manifest.json");
44532
+ await writeFile(path62, `${JSON.stringify(manifest, null, 2)}
44237
44533
  `, "utf8");
44238
- return { path: path60, manifest };
44534
+ return { path: path62, manifest };
44239
44535
  }
44240
44536
 
44241
44537
  // ../mcp-server/src/tools/_capture/proxy.ts
@@ -44489,9 +44785,9 @@ async function startProxy(opts) {
44489
44785
  const liveCompiled = verified.allowedPaths.map(compileGlob);
44490
44786
  const target = parseRequestTarget(req);
44491
44787
  if (!target) return httpReject(400, "invalid_target");
44492
- const path60 = target.pathname;
44493
- if (!liveCompiled.some((re) => re.test(path60))) {
44494
- return httpReject(403, "outside_allow_list", { path: path60 });
44788
+ const path62 = target.pathname;
44789
+ if (!liveCompiled.some((re) => re.test(path62))) {
44790
+ return httpReject(403, "outside_allow_list", { path: path62 });
44495
44791
  }
44496
44792
  const headerWorld = req.headers[WORLD_ASSERT_HEADER];
44497
44793
  const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
@@ -45331,14 +45627,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
45331
45627
  await page.waitForTimeout(shot.afterLoadMs);
45332
45628
  }
45333
45629
  const ext = format === "jpeg" ? "jpg" : "png";
45334
- const path60 = join15(outDir, `${shot.name}.${ext}`);
45630
+ const path62 = join15(outDir, `${shot.name}.${ext}`);
45335
45631
  await page.screenshot({
45336
- path: path60,
45632
+ path: path62,
45337
45633
  type: format,
45338
45634
  ...format === "jpeg" ? { quality: jpegQuality } : {},
45339
45635
  fullPage: false
45340
45636
  });
45341
- return { name: shot.name, path: path60, urlRedacted: redactUrl(shot.url), viewport };
45637
+ return { name: shot.name, path: path62, urlRedacted: redactUrl(shot.url), viewport };
45342
45638
  } finally {
45343
45639
  await context.close();
45344
45640
  }
@@ -45770,9 +46066,9 @@ import { join as join17 } from "node:path";
45770
46066
  var PLACEHOLDER_ANTHROPIC_API_KEY = "olam-vault-routed-placeholder-stripped-by-proxy";
45771
46067
  var DEFAULT_WEB_TASK_MODEL = "claude-opus-4-7";
45772
46068
  var AnthropicBaseUrlMissingError = class extends Error {
45773
- constructor(path60, cause) {
46069
+ constructor(path62, cause) {
45774
46070
  super(
45775
- `vault base URL is not resolvable from "${path60}" (${cause}). The web-task model call routes through olam's auth-worker vault, not a raw API key \u2014 this host has no vault base URL configured. Run \`olam auth login\` (or set OLAM_ANTHROPIC_BASE_URL) so the path-encoded /auth/<sub>/<secret> base exists.`
46071
+ `vault base URL is not resolvable from "${path62}" (${cause}). The web-task model call routes through olam's auth-worker vault, not a raw API key \u2014 this host has no vault base URL configured. Run \`olam auth login\` (or set OLAM_ANTHROPIC_BASE_URL) so the path-encoded /auth/<sub>/<secret> base exists.`
45776
46072
  );
45777
46073
  this.name = "AnthropicBaseUrlMissingError";
45778
46074
  }
@@ -46671,12 +46967,12 @@ function openUrl(url3) {
46671
46967
  var HOST_CP_URL = "http://127.0.0.1:19000";
46672
46968
  async function readHostCpToken2() {
46673
46969
  try {
46674
- const { default: fs60 } = await import("node:fs");
46970
+ const { default: fs62 } = await import("node:fs");
46675
46971
  const { default: os36 } = await import("node:os");
46676
- const { default: path60 } = await import("node:path");
46677
- const tp = path60.join(os36.homedir(), ".olam", "host-cp.token");
46678
- if (!fs60.existsSync(tp)) return { token: null };
46679
- return { token: fs60.readFileSync(tp, "utf-8").trim() };
46972
+ const { default: path62 } = await import("node:path");
46973
+ const tp = path62.join(os36.homedir(), ".olam", "host-cp.token");
46974
+ if (!fs62.existsSync(tp)) return { token: null };
46975
+ return { token: fs62.readFileSync(tp, "utf-8").trim() };
46680
46976
  } catch {
46681
46977
  return { token: null };
46682
46978
  }
@@ -46970,9 +47266,9 @@ function register22(server, _ctx, _initError) {
46970
47266
  }]
46971
47267
  };
46972
47268
  });
46973
- validatedTool(server, repoAddSkill, "olam_repo_add", async ({ name, path: path60, description, defaultBranch }) => {
47269
+ validatedTool(server, repoAddSkill, "olam_repo_add", async ({ name, path: path62, description, defaultBranch }) => {
46974
47270
  try {
46975
- const entry = addRepo({ name, path: path60, description, defaultBranch });
47271
+ const entry = addRepo({ name, path: path62, description, defaultBranch });
46976
47272
  return {
46977
47273
  content: [{
46978
47274
  type: "text",
@@ -47008,9 +47304,9 @@ function register22(server, _ctx, _initError) {
47008
47304
  };
47009
47305
  }
47010
47306
  });
47011
- validatedTool(server, repoUpdateSkill, "olam_repo_update", async ({ name, path: path60, description, defaultBranch }) => {
47307
+ validatedTool(server, repoUpdateSkill, "olam_repo_update", async ({ name, path: path62, description, defaultBranch }) => {
47012
47308
  try {
47013
- const entry = updateRepo(name, { path: path60, description, defaultBranch });
47309
+ const entry = updateRepo(name, { path: path62, description, defaultBranch });
47014
47310
  return {
47015
47311
  content: [{
47016
47312
  type: "text",
@@ -47035,9 +47331,9 @@ __export(process_port_exports, {
47035
47331
  register: () => register23,
47036
47332
  resolveHostCpToken: () => resolveHostCpToken
47037
47333
  });
47038
- import fs39 from "node:fs";
47334
+ import fs41 from "node:fs";
47039
47335
  import os22 from "node:os";
47040
- import path37 from "node:path";
47336
+ import path39 from "node:path";
47041
47337
 
47042
47338
  // ../skill-runtime/dist/skills/process-list.js
47043
47339
  init_v3();
@@ -47082,8 +47378,8 @@ var HOST_CP_BASE = "http://127.0.0.1:19000";
47082
47378
  function resolveHostCpToken() {
47083
47379
  const envToken = process.env["OLAM_HOST_CP_TOKEN"];
47084
47380
  if (envToken) return envToken;
47085
- const tokenPath = path37.join(os22.homedir(), ".olam", "host-cp.token");
47086
- if (fs39.existsSync(tokenPath)) return fs39.readFileSync(tokenPath, "utf-8").trim();
47381
+ const tokenPath = path39.join(os22.homedir(), ".olam", "host-cp.token");
47382
+ if (fs41.existsSync(tokenPath)) return fs41.readFileSync(tokenPath, "utf-8").trim();
47087
47383
  return null;
47088
47384
  }
47089
47385
  function tokenMissingError() {
@@ -47606,8 +47902,8 @@ __export(skills_exports, {
47606
47902
  register: () => register26
47607
47903
  });
47608
47904
  init_skill_sources();
47609
- import * as fs40 from "node:fs";
47610
- import * as path38 from "node:path";
47905
+ import * as fs42 from "node:fs";
47906
+ import * as path40 from "node:path";
47611
47907
 
47612
47908
  // ../skill-runtime/dist/skills/skills-sync.js
47613
47909
  init_v3();
@@ -47688,14 +47984,14 @@ function listDeployed() {
47688
47984
  );
47689
47985
  const entries = [];
47690
47986
  for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
47691
- const bucketDir = path38.join(dir, bucket);
47692
- if (!fs40.existsSync(bucketDir)) continue;
47693
- for (const name of fs40.readdirSync(bucketDir)) {
47694
- const full = path38.join(bucketDir, name);
47987
+ const bucketDir = path40.join(dir, bucket);
47988
+ if (!fs42.existsSync(bucketDir)) continue;
47989
+ for (const name of fs42.readdirSync(bucketDir)) {
47990
+ const full = path40.join(bucketDir, name);
47695
47991
  try {
47696
- const stat2 = fs40.lstatSync(full);
47992
+ const stat2 = fs42.lstatSync(full);
47697
47993
  if (!stat2.isSymbolicLink()) continue;
47698
- const target = fs40.readlinkSync(full);
47994
+ const target = fs42.readlinkSync(full);
47699
47995
  let sourceId;
47700
47996
  for (const [clonePath, id] of sourcePaths.entries()) {
47701
47997
  if (target.startsWith(clonePath)) {
@@ -47783,15 +48079,15 @@ function deriveModeId(name, taken) {
47783
48079
 
47784
48080
  // ../core/dist/ree-modes/store.js
47785
48081
  init_skill_sources();
47786
- import * as fs42 from "node:fs";
48082
+ import * as fs44 from "node:fs";
47787
48083
  import * as os24 from "node:os";
47788
- import * as path40 from "node:path";
48084
+ import * as path42 from "node:path";
47789
48085
 
47790
48086
  // ../core/dist/ree-modes/registry.js
47791
48087
  init_v3();
47792
- import * as fs41 from "node:fs";
48088
+ import * as fs43 from "node:fs";
47793
48089
  import * as os23 from "node:os";
47794
- import * as path39 from "node:path";
48090
+ import * as path41 from "node:path";
47795
48091
  var CadenceStatusSchema = external_exports2.enum(["running", "stopped"]);
47796
48092
  var CadenceEntrySchema = external_exports2.object({
47797
48093
  /** Unique cadence id (modeId + short timestamp). */
@@ -47813,18 +48109,18 @@ function olamRootDir() {
47813
48109
  const override = process.env["OLAM_STATE_DIR"];
47814
48110
  if (override && override.length > 0)
47815
48111
  return override;
47816
- return path39.join(os23.homedir(), ".olam");
48112
+ return path41.join(os23.homedir(), ".olam");
47817
48113
  }
47818
48114
  function cadenceRegistryPath() {
47819
- return path39.join(olamRootDir(), "ree-cadences.json");
48115
+ return path41.join(olamRootDir(), "ree-cadences.json");
47820
48116
  }
47821
48117
  function readCadenceRegistry() {
47822
48118
  const file2 = cadenceRegistryPath();
47823
- if (!fs41.existsSync(file2))
48119
+ if (!fs43.existsSync(file2))
47824
48120
  return { cadences: [] };
47825
48121
  let raw;
47826
48122
  try {
47827
- raw = JSON.parse(fs41.readFileSync(file2, "utf-8"));
48123
+ raw = JSON.parse(fs43.readFileSync(file2, "utf-8"));
47828
48124
  } catch {
47829
48125
  return { cadences: [] };
47830
48126
  }
@@ -47833,10 +48129,10 @@ function readCadenceRegistry() {
47833
48129
  }
47834
48130
  function writeCadenceRegistry(registry2) {
47835
48131
  const file2 = cadenceRegistryPath();
47836
- fs41.mkdirSync(path39.dirname(file2), { recursive: true });
48132
+ fs43.mkdirSync(path41.dirname(file2), { recursive: true });
47837
48133
  const tmp = `${file2}.tmp-${process.pid}`;
47838
- fs41.writeFileSync(tmp, JSON.stringify(registry2, null, 2) + "\n", "utf-8");
47839
- fs41.renameSync(tmp, file2);
48134
+ fs43.writeFileSync(tmp, JSON.stringify(registry2, null, 2) + "\n", "utf-8");
48135
+ fs43.renameSync(tmp, file2);
47840
48136
  }
47841
48137
  function startCadence(input) {
47842
48138
  const now = input.now ?? /* @__PURE__ */ new Date();
@@ -47880,18 +48176,18 @@ function claudeRootDir() {
47880
48176
  const override = process.env["OLAM_CLAUDE_DIR"];
47881
48177
  if (override && override.length > 0)
47882
48178
  return override;
47883
- return path40.join(os24.homedir(), ".claude");
48179
+ return path42.join(os24.homedir(), ".claude");
47884
48180
  }
47885
48181
  function localModesDir() {
47886
- return path40.join(claudeRootDir(), "ree-modes.local");
48182
+ return path42.join(claudeRootDir(), "ree-modes.local");
47887
48183
  }
47888
48184
  var SOURCE_CATALOG_RELATIVE_PATH = "shared/engineering/skills/ree-cadence/references/modes.md";
47889
48185
  function findSourceCatalogPath(opts) {
47890
48186
  if (opts && "_testCatalogPath" in opts)
47891
48187
  return opts._testCatalogPath ?? null;
47892
48188
  for (const source of listSkillSources()) {
47893
- const candidate = path40.join(skillSourceClonePath(source.id), SOURCE_CATALOG_RELATIVE_PATH);
47894
- if (fs42.existsSync(candidate))
48189
+ const candidate = path42.join(skillSourceClonePath(source.id), SOURCE_CATALOG_RELATIVE_PATH);
48190
+ if (fs44.existsSync(candidate))
47895
48191
  return candidate;
47896
48192
  }
47897
48193
  return null;
@@ -47941,16 +48237,16 @@ function parseModeCatalog(content, origin) {
47941
48237
  }
47942
48238
  function loadLocalModes() {
47943
48239
  const dir = localModesDir();
47944
- if (!fs42.existsSync(dir))
48240
+ if (!fs44.existsSync(dir))
47945
48241
  return [];
47946
48242
  const out = [];
47947
- for (const entry of fs42.readdirSync(dir).sort()) {
48243
+ for (const entry of fs44.readdirSync(dir).sort()) {
47948
48244
  if (!entry.endsWith(".md"))
47949
48245
  continue;
47950
- const full = path40.join(dir, entry);
48246
+ const full = path42.join(dir, entry);
47951
48247
  let content;
47952
48248
  try {
47953
- content = fs42.readFileSync(full, "utf-8");
48249
+ content = fs44.readFileSync(full, "utf-8");
47954
48250
  } catch {
47955
48251
  continue;
47956
48252
  }
@@ -47966,7 +48262,7 @@ function loadSourceModes(opts) {
47966
48262
  return [];
47967
48263
  let content;
47968
48264
  try {
47969
- content = fs42.readFileSync(catalogPath, "utf-8");
48265
+ content = fs44.readFileSync(catalogPath, "utf-8");
47970
48266
  } catch {
47971
48267
  return [];
47972
48268
  }
@@ -48033,12 +48329,12 @@ function createLocalMode(input) {
48033
48329
  id = deriveModeId(name, taken);
48034
48330
  }
48035
48331
  const dir = localModesDir();
48036
- fs42.mkdirSync(dir, { recursive: true });
48037
- const file2 = path40.join(dir, `${id}.md`);
48038
- if (fs42.existsSync(file2)) {
48332
+ fs44.mkdirSync(dir, { recursive: true });
48333
+ const file2 = path42.join(dir, `${id}.md`);
48334
+ if (fs44.existsSync(file2)) {
48039
48335
  throw new Error(`local mode file already exists: ${file2}`);
48040
48336
  }
48041
- fs42.writeFileSync(file2, scaffoldModeBlock({ id, name, instruction }), "utf-8");
48337
+ fs44.writeFileSync(file2, scaffoldModeBlock({ id, name, instruction }), "utf-8");
48042
48338
  return { id, name, origin: "local", path: file2 };
48043
48339
  }
48044
48340
  function renameLocalMode(oldId, newId) {
@@ -48049,8 +48345,8 @@ function renameLocalMode(oldId, newId) {
48049
48345
  throw new Error(`invalid new id "${newId}" \u2014 must match ${MODE_ID_RE}.`);
48050
48346
  }
48051
48347
  const dir = localModesDir();
48052
- const oldFile = path40.join(dir, `${oldId}.md`);
48053
- if (!fs42.existsSync(oldFile)) {
48348
+ const oldFile = path42.join(dir, `${oldId}.md`);
48349
+ if (!fs44.existsSync(oldFile)) {
48054
48350
  const isSource = loadSourceModes().some((m) => m.id === oldId);
48055
48351
  if (isSource) {
48056
48352
  throw new Error(`"${oldId}" is a source built-in mode, not a local one \u2014 it can't be renamed directly. Create a local override (olam skills ree-modes add) and promote it instead.`);
@@ -48060,11 +48356,11 @@ function renameLocalMode(oldId, newId) {
48060
48356
  if (takenModeIds().has(newId)) {
48061
48357
  throw new Error(`target id "${newId}" already exists (source or local).`);
48062
48358
  }
48063
- const content = fs42.readFileSync(oldFile, "utf-8");
48359
+ const content = fs44.readFileSync(oldFile, "utf-8");
48064
48360
  const rewritten = content.replace(new RegExp(`^## ${escapeRegex2(oldId)} \u2014 `, "m"), `## ${newId} \u2014 `);
48065
- const newFile = path40.join(dir, `${newId}.md`);
48066
- fs42.writeFileSync(newFile, rewritten, "utf-8");
48067
- fs42.rmSync(oldFile);
48361
+ const newFile = path42.join(dir, `${newId}.md`);
48362
+ fs44.writeFileSync(newFile, rewritten, "utf-8");
48363
+ fs44.rmSync(oldFile);
48068
48364
  const danglingCadences = listCadences({ runningOnly: true }).filter((c) => c.modeId === oldId).map((c) => c.id);
48069
48365
  return { from: oldId, to: newId, origin: "local", path: newFile, danglingCadences };
48070
48366
  }
@@ -48084,8 +48380,8 @@ function deriveNameFromInstruction(instruction) {
48084
48380
  }
48085
48381
 
48086
48382
  // ../core/dist/ree-modes/promote.js
48087
- import * as fs43 from "node:fs";
48088
- import * as path41 from "node:path";
48383
+ import * as fs45 from "node:fs";
48384
+ import * as path43 from "node:path";
48089
48385
 
48090
48386
  // ../core/dist/ree-modes/disambiguation.js
48091
48387
  var PICKER_THRESHOLD = 4;
@@ -48260,13 +48556,13 @@ var skills_search_exports = {};
48260
48556
  __export(skills_search_exports, {
48261
48557
  register: () => register28
48262
48558
  });
48263
- import * as path43 from "node:path";
48559
+ import * as path45 from "node:path";
48264
48560
  import * as os26 from "node:os";
48265
48561
 
48266
48562
  // ../mcp-server/src/lib/skills-index.mjs
48267
48563
  import { createRequire as createRequire5 } from "node:module";
48268
- import * as fs44 from "node:fs";
48269
- import * as path42 from "node:path";
48564
+ import * as fs46 from "node:fs";
48565
+ import * as path44 from "node:path";
48270
48566
  import * as os25 from "node:os";
48271
48567
  var VECTOR_DIM = 256;
48272
48568
  var SCHEMA_VERSION3 = "1";
@@ -48356,7 +48652,7 @@ function bufferToVector(buf) {
48356
48652
  return vec;
48357
48653
  }
48358
48654
  function openIndex(dbPath) {
48359
- if (!fs44.existsSync(dbPath)) {
48655
+ if (!fs46.existsSync(dbPath)) {
48360
48656
  throw new Error(
48361
48657
  `skills index not found at ${dbPath}. Run \`node scripts/skills-index-build.mjs --out ${dbPath}\` first.`
48362
48658
  );
@@ -48398,8 +48694,8 @@ function searchIndex(dbPath, query, k = 5) {
48398
48694
  db.close();
48399
48695
  }
48400
48696
  }
48401
- var DEFAULT_DB_PATH = path42.join(os25.homedir(), ".olam", "skills.vec.db");
48402
- var DEFAULT_SOURCE_DIR = path42.join(os25.homedir(), ".claude", "skills");
48697
+ var DEFAULT_DB_PATH = path44.join(os25.homedir(), ".olam", "skills.vec.db");
48698
+ var DEFAULT_SOURCE_DIR = path44.join(os25.homedir(), ".claude", "skills");
48403
48699
 
48404
48700
  // ../skill-runtime/dist/skills/skills-search.js
48405
48701
  init_v3();
@@ -48418,7 +48714,7 @@ var skillsSearchSkill = defineSkill({
48418
48714
  function defaultDbPath() {
48419
48715
  const override = process.env["SKILLS_INDEX_PATH"];
48420
48716
  if (override) return override;
48421
- return path43.join(os26.homedir(), ".olam", "skills.vec.db");
48717
+ return path45.join(os26.homedir(), ".olam", "skills.vec.db");
48422
48718
  }
48423
48719
  function asMessage10(err) {
48424
48720
  return err instanceof Error ? err.message : String(err);
@@ -48462,8 +48758,8 @@ function port() {
48462
48758
  const n = Number.parseInt(env, 10);
48463
48759
  return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
48464
48760
  }
48465
- function url2(path60) {
48466
- return `http://127.0.0.1:${port()}${path60}`;
48761
+ function url2(path62) {
48762
+ return `http://127.0.0.1:${port()}${path62}`;
48467
48763
  }
48468
48764
  function kgServiceHealthUrl() {
48469
48765
  return url2("/health");
@@ -48692,12 +48988,12 @@ __export(kg_install_hook_exports, {
48692
48988
  register: () => register31
48693
48989
  });
48694
48990
  init_merge_settings();
48695
- import * as fs45 from "node:fs";
48696
- import * as path44 from "node:path";
48991
+ import * as fs47 from "node:fs";
48992
+ import * as path46 from "node:path";
48697
48993
  import * as os27 from "node:os";
48698
48994
 
48699
48995
  // ../core/dist/kg/hook-template.js
48700
- var KG_HOOK_SENTINEL = "kg-service-v2-classifier-hook";
48996
+ var KG_HOOK_SENTINEL = "kg-service-v3-classifier-hook";
48701
48997
  function defaultUrl(flavor) {
48702
48998
  if (flavor === "host")
48703
48999
  return "http://127.0.0.1:9997/classify";
@@ -48711,10 +49007,20 @@ function buildHookCommand(opts) {
48711
49007
  const emitContext = `python3 -c 'import json,sys,os
48712
49008
  try:
48713
49009
  d=json.loads(sys.stdin.read())
48714
- if d.get("route") and d["route"] != "grep":
49010
+ route=d.get("route","")
49011
+ if route:
49012
+ if route in ("kg","both"):
49013
+ label=d.get("top_match") or d.get("reason","")
49014
+ layer=d.get("layer","?")
49015
+ nodes=d.get("nodes_matched",0)
49016
+ saved=(d.get("savings") or {}).get("saved_tokens_est",0)
49017
+ saved_k=round(saved/1000)
49018
+ sys.stderr.write(f"\\x1b[32m\\u29bf\\u29bf\\x1b[0m KG hit \\u2713 {label} \\u2192 L{layer}/{route} \\u00b7 {nodes} nodes \\u00b7 \\x1b[32m~{saved_k}k tokens saved\\x1b[0m\\n")
49019
+ else:
49020
+ sys.stderr.write("\\U0001f50d Grep used\\n")
49021
+ if route and route != "grep":
48715
49022
  label=d.get("top_match") or d.get("reason","")
48716
49023
  layer=d.get("layer","?")
48717
- route=d["route"]
48718
49024
  nodes=d.get("nodes_matched",0)
48719
49025
  saved=(d.get("savings") or {}).get("saved_tokens_est",0)
48720
49026
  saved_k=round(saved/1000)
@@ -48725,7 +49031,6 @@ try:
48725
49031
  rel=any(k in ql for k in ("call","caller","import","uses","used","reference","who "))
48726
49032
  g="olam kg mirror graph \\"" + sym + "\\" --workspace <ws>"
48727
49033
  hint=g + (" --relates" if rel else "") + " (where X is defined; add --relates for what calls/imports it; --repo <name> to browse a repo)"
48728
- sys.stderr.write(f"\\x1b[32m\\u2713 KG hit\\x1b[0m \\"{q}\\" \\u2192 L{layer}/{route} \\u00b7 {nodes} nodes \\u00b7 ~{saved_k}k tokens saved\\n")
48729
49034
  print(json.dumps({"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":f"[kg-classifier L{layer}|{route}] {label[:140]}\\n\\u21b3 graph: {hint}"}}))
48730
49035
  except Exception: pass' 2>/dev/null`;
48731
49036
  const isCloud = opts.flavor === "cloud-sandbox";
@@ -48734,7 +49039,7 @@ except Exception: pass' 2>/dev/null`;
48734
49039
  const cloudGuard = isCloud ? `if [ -z "\${OLAM_KG_PROXY_URL:-}" ] || [ -z "\${OLAM_KG_PROXY_BEARER:-}" ]; then exit 0; fi; ` : "";
48735
49040
  const wsField = isCloud ? `,\\"workspace\\":\\"\${OLAM_KG_PROXY_WORKSPACE:-}\\"` : "";
48736
49041
  const curlPost = `RESP=$(curl -s --max-time 1 -X POST -H 'Content-Type: application/json' ${authHeader2} -d "{\\"q\\":\\"$(echo \\"$CMD\\" | head -c 200 | tr '\\"' ' ')\\"${wsField}}" ${resolvedUrl} 2>/dev/null)`;
48737
- const hostRemoteFallback = opts.flavor === "host" ? `; if [ -z "$RESP" ] && [ -r "$HOME/.olam/kg-proxy-url" ] && [ -r "$HOME/.olam/kg-proxy-bearer" ]; then RESP=$(curl -s --max-time 2 -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $(cat "$HOME/.olam/kg-proxy-bearer")" -d "{\\"q\\":\\"$(echo \\"$CMD\\" | head -c 200 | tr '\\"' ' ')\\"}" "$(cat "$HOME/.olam/kg-proxy-url")/v1/classify" 2>/dev/null); fi` : "";
49042
+ const hostRemoteFallback = opts.flavor === "host" ? `; if [ -z "$RESP" ] && [ -r "$HOME/.olam/kg-proxy-url" ] && [ -r "$HOME/.olam/kg-proxy-bearer" ]; then KG_ORIGIN=$(sed 's|\\(https*://[^/]*\\).*|\\1|' "$HOME/.olam/kg-proxy-url" 2>/dev/null); RESP=$(curl -s --max-time 3 -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $(cat "$HOME/.olam/kg-proxy-bearer")" -d "{\\"q\\":\\"$(echo \\"$CMD\\" | head -c 200 | tr '\\"' ' ')\\"}" "$KG_ORIGIN/v1/classify" 2>/dev/null); fi` : "";
48738
49043
  return [
48739
49044
  `KG_SENTINEL=${KG_HOOK_SENTINEL}`,
48740
49045
  `CMD=$(${extractCmd})`,
@@ -48781,22 +49086,22 @@ var kgInstallHookSkill = defineSkill({
48781
49086
  // ../mcp-server/src/tools/kg-install-hook.ts
48782
49087
  function settingsPathFor2(scope, projectPath) {
48783
49088
  if (scope === "user") {
48784
- return path44.join(os27.homedir(), ".claude", "settings.json");
49089
+ return path46.join(os27.homedir(), ".claude", "settings.json");
48785
49090
  }
48786
49091
  const root = projectPath ?? process.cwd();
48787
- return path44.join(root, ".claude", "settings.json");
49092
+ return path46.join(root, ".claude", "settings.json");
48788
49093
  }
48789
49094
  function register31(server, _ctx, _initError) {
48790
49095
  validatedTool(server, kgInstallHookSkill, "olam_kg_install_hook", async (params) => {
48791
49096
  const scope = params.scope === "user" ? "user" : "project";
48792
49097
  const filePath = settingsPathFor2(scope, params.projectPath);
48793
49098
  try {
48794
- fs45.mkdirSync(path44.dirname(filePath), { recursive: true });
49099
+ fs47.mkdirSync(path46.dirname(filePath), { recursive: true });
48795
49100
  let backupPath = null;
48796
- if (fs45.existsSync(filePath)) {
49101
+ if (fs47.existsSync(filePath)) {
48797
49102
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
48798
49103
  backupPath = `${filePath}.olam-bak.${ts}`;
48799
- fs45.copyFileSync(filePath, backupPath);
49104
+ fs47.copyFileSync(filePath, backupPath);
48800
49105
  }
48801
49106
  const result = mergeHomeSettingsJson(filePath, {
48802
49107
  ensureHook: {
@@ -48807,7 +49112,7 @@ function register31(server, _ctx, _initError) {
48807
49112
  });
48808
49113
  if (result.status === "already-present" && backupPath) {
48809
49114
  try {
48810
- fs45.unlinkSync(backupPath);
49115
+ fs47.unlinkSync(backupPath);
48811
49116
  } catch {
48812
49117
  }
48813
49118
  }
@@ -48849,8 +49154,8 @@ var kg_uninstall_hook_exports = {};
48849
49154
  __export(kg_uninstall_hook_exports, {
48850
49155
  register: () => register32
48851
49156
  });
48852
- import * as fs46 from "node:fs";
48853
- import * as path45 from "node:path";
49157
+ import * as fs48 from "node:fs";
49158
+ import * as path47 from "node:path";
48854
49159
  import * as os28 from "node:os";
48855
49160
 
48856
49161
  // ../skill-runtime/dist/skills/kg-uninstall-hook.js
@@ -48873,10 +49178,10 @@ var kgUninstallHookSkill = defineSkill({
48873
49178
  // ../mcp-server/src/tools/kg-uninstall-hook.ts
48874
49179
  function settingsPathFor3(scope, projectPath) {
48875
49180
  if (scope === "user") {
48876
- return path45.join(os28.homedir(), ".claude", "settings.json");
49181
+ return path47.join(os28.homedir(), ".claude", "settings.json");
48877
49182
  }
48878
49183
  const root = projectPath ?? process.cwd();
48879
- return path45.join(root, ".claude", "settings.json");
49184
+ return path47.join(root, ".claude", "settings.json");
48880
49185
  }
48881
49186
  function dropSentinel(matchers) {
48882
49187
  let changed = false;
@@ -48903,7 +49208,7 @@ function register32(server, _ctx, _initError) {
48903
49208
  const scope = params.scope === "user" ? "user" : "project";
48904
49209
  const filePath = settingsPathFor3(scope, params.projectPath);
48905
49210
  try {
48906
- if (!fs46.existsSync(filePath)) {
49211
+ if (!fs48.existsSync(filePath)) {
48907
49212
  return {
48908
49213
  content: [
48909
49214
  {
@@ -48917,7 +49222,7 @@ function register32(server, _ctx, _initError) {
48917
49222
  ]
48918
49223
  };
48919
49224
  }
48920
- const raw = fs46.readFileSync(filePath, "utf-8");
49225
+ const raw = fs48.readFileSync(filePath, "utf-8");
48921
49226
  const settings = raw.trim() ? JSON.parse(raw) : {};
48922
49227
  const preToolUse = settings.hooks?.PreToolUse;
48923
49228
  if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
@@ -48952,7 +49257,7 @@ function register32(server, _ctx, _initError) {
48952
49257
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
48953
49258
  const backupPath = `${filePath}.olam-bak.${ts}`;
48954
49259
  try {
48955
- fs46.copyFileSync(filePath, backupPath);
49260
+ fs48.copyFileSync(filePath, backupPath);
48956
49261
  } catch {
48957
49262
  }
48958
49263
  const next = {
@@ -48964,7 +49269,7 @@ function register32(server, _ctx, _initError) {
48964
49269
  if (otherStages.length === 0) delete next.hooks;
48965
49270
  else delete next.hooks.PreToolUse;
48966
49271
  }
48967
- fs46.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
49272
+ fs48.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
48968
49273
  return {
48969
49274
  content: [
48970
49275
  {
@@ -49702,11 +50007,11 @@ function registerAllTools(server, ctx, initError) {
49702
50007
  }
49703
50008
 
49704
50009
  // ../mcp-server/src/resources/chunks.ts
49705
- import fs47 from "node:fs";
50010
+ import fs49 from "node:fs";
49706
50011
  import os29 from "node:os";
49707
- import path46 from "node:path";
50012
+ import path48 from "node:path";
49708
50013
  var DEFAULT_HOST_CP_URL = "http://127.0.0.1:19000";
49709
- var DEFAULT_PLAN_CHAT_SECRET_PATH = path46.join(
50014
+ var DEFAULT_PLAN_CHAT_SECRET_PATH = path48.join(
49710
50015
  os29.homedir(),
49711
50016
  ".olam",
49712
50017
  "plan-chat-secret"
@@ -49721,7 +50026,7 @@ function loadBearer(bearerOpt, secretPath) {
49721
50026
  const envBearer = process.env.OLAM_PLAN_CHAT_BEARER?.trim();
49722
50027
  if (envBearer && envBearer.length > 0) return envBearer;
49723
50028
  try {
49724
- const onDisk = fs47.readFileSync(secretPath, "utf8").trim();
50029
+ const onDisk = fs49.readFileSync(secretPath, "utf8").trim();
49725
50030
  return onDisk.length > 0 ? onDisk : null;
49726
50031
  } catch (err) {
49727
50032
  if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
@@ -51495,9 +51800,9 @@ init_loader();
51495
51800
  // ../core/dist/world/manager.js
51496
51801
  import * as crypto8 from "node:crypto";
51497
51802
  import { execSync as execSync6, spawnSync as spawnSync4 } from "node:child_process";
51498
- import * as fs57 from "node:fs";
51803
+ import * as fs59 from "node:fs";
51499
51804
  import * as os34 from "node:os";
51500
- import * as path57 from "node:path";
51805
+ import * as path59 from "node:path";
51501
51806
 
51502
51807
  // ../core/dist/world/state.js
51503
51808
  var VALID_TRANSITIONS = {
@@ -51592,9 +51897,9 @@ function resolveDevboxImage(config2, tag) {
51592
51897
  }
51593
51898
 
51594
51899
  // ../core/dist/world/worktree.js
51595
- import { execFileSync as execFileSync4 } from "node:child_process";
51596
- import * as fs48 from "node:fs";
51597
- import * as path47 from "node:path";
51900
+ import { execFileSync as execFileSync5 } from "node:child_process";
51901
+ import * as fs50 from "node:fs";
51902
+ import * as path49 from "node:path";
51598
51903
  function resolveGitDir(repo) {
51599
51904
  if (repo.path) {
51600
51905
  return repo.path;
@@ -51604,18 +51909,18 @@ function resolveGitDir(repo) {
51604
51909
  async function createWorktrees(repos, worldId, workspacePath, branch) {
51605
51910
  const created = [];
51606
51911
  for (const repo of repos) {
51607
- const worktreePath = path47.join(workspacePath, repo.name);
51912
+ const worktreePath = path49.join(workspacePath, repo.name);
51608
51913
  const gitDir = resolveGitDir(repo);
51609
51914
  const branchName = branch || `olam/${worldId}`;
51610
51915
  try {
51611
- fs48.mkdirSync(path47.dirname(worktreePath), { recursive: true });
51612
- execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
51916
+ fs50.mkdirSync(path49.dirname(worktreePath), { recursive: true });
51917
+ execFileSync5("git", ["worktree", "add", worktreePath, "-b", branchName], {
51613
51918
  cwd: gitDir,
51614
51919
  stdio: "pipe"
51615
51920
  });
51616
51921
  if (repo.submodules) {
51617
51922
  try {
51618
- execFileSync4("git", ["submodule", "update", "--init", "--recursive"], {
51923
+ execFileSync5("git", ["submodule", "update", "--init", "--recursive"], {
51619
51924
  cwd: worktreePath,
51620
51925
  stdio: "pipe"
51621
51926
  });
@@ -51627,7 +51932,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
51627
51932
  for (const entry of created) {
51628
51933
  try {
51629
51934
  const entryGitDir = resolveGitDir(entry.repo);
51630
- execFileSync4("git", ["worktree", "remove", entry.worktreePath, "--force"], {
51935
+ execFileSync5("git", ["worktree", "remove", entry.worktreePath, "--force"], {
51631
51936
  cwd: entryGitDir,
51632
51937
  stdio: "pipe"
51633
51938
  });
@@ -51641,7 +51946,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
51641
51946
  }
51642
51947
  async function removeWorktrees(repos, workspacePath) {
51643
51948
  for (const repo of repos) {
51644
- const worktreePath = path47.join(workspacePath, repo.name);
51949
+ const worktreePath = path49.join(workspacePath, repo.name);
51645
51950
  let gitDir;
51646
51951
  try {
51647
51952
  gitDir = resolveGitDir(repo);
@@ -51650,7 +51955,7 @@ async function removeWorktrees(repos, workspacePath) {
51650
51955
  }
51651
51956
  let removed = false;
51652
51957
  try {
51653
- execFileSync4("git", ["worktree", "remove", "--force", worktreePath], {
51958
+ execFileSync5("git", ["worktree", "remove", "--force", worktreePath], {
51654
51959
  cwd: gitDir,
51655
51960
  stdio: "pipe"
51656
51961
  });
@@ -51659,7 +51964,7 @@ async function removeWorktrees(repos, workspacePath) {
51659
51964
  }
51660
51965
  if (!removed) {
51661
51966
  try {
51662
- execFileSync4("git", ["worktree", "prune"], {
51967
+ execFileSync5("git", ["worktree", "prune"], {
51663
51968
  cwd: gitDir,
51664
51969
  stdio: "pipe"
51665
51970
  });
@@ -51676,7 +51981,7 @@ function removeBranch(repo, branch) {
51676
51981
  return { branch, action: "not-found" };
51677
51982
  }
51678
51983
  try {
51679
- execFileSync4("git", ["show-ref", "--quiet", `refs/heads/${branch}`], {
51984
+ execFileSync5("git", ["show-ref", "--quiet", `refs/heads/${branch}`], {
51680
51985
  cwd: gitDir,
51681
51986
  stdio: "pipe"
51682
51987
  });
@@ -51685,7 +51990,7 @@ function removeBranch(repo, branch) {
51685
51990
  }
51686
51991
  let hasUpstream = false;
51687
51992
  try {
51688
- execFileSync4("git", ["rev-parse", "--abbrev-ref", `${branch}@{upstream}`], { cwd: gitDir, stdio: "pipe" });
51993
+ execFileSync5("git", ["rev-parse", "--abbrev-ref", `${branch}@{upstream}`], { cwd: gitDir, stdio: "pipe" });
51689
51994
  hasUpstream = true;
51690
51995
  } catch {
51691
51996
  }
@@ -51694,14 +51999,14 @@ function removeBranch(repo, branch) {
51694
51999
  }
51695
52000
  let localCommitCount = 0;
51696
52001
  try {
51697
- const output = execFileSync4("git", ["rev-list", "--count", branch, "--not", "--remotes"], { cwd: gitDir, stdio: "pipe" }).toString().trim();
52002
+ const output = execFileSync5("git", ["rev-list", "--count", branch, "--not", "--remotes"], { cwd: gitDir, stdio: "pipe" }).toString().trim();
51698
52003
  localCommitCount = parseInt(output, 10) || 0;
51699
52004
  } catch {
51700
52005
  localCommitCount = 1;
51701
52006
  }
51702
52007
  if (localCommitCount === 0) {
51703
52008
  try {
51704
- execFileSync4("git", ["branch", "-D", branch], {
52009
+ execFileSync5("git", ["branch", "-D", branch], {
51705
52010
  cwd: gitDir,
51706
52011
  stdio: "pipe"
51707
52012
  });
@@ -51715,13 +52020,13 @@ function removeBranch(repo, branch) {
51715
52020
  }
51716
52021
 
51717
52022
  // ../core/dist/world/kg-overlay.js
51718
- import { execFileSync as execFileSync5 } from "node:child_process";
51719
- import * as fs49 from "node:fs";
51720
- import * as path48 from "node:path";
52023
+ import { execFileSync as execFileSync6 } from "node:child_process";
52024
+ import * as fs51 from "node:fs";
52025
+ import * as path50 from "node:path";
51721
52026
 
51722
52027
  // ../core/dist/kg/storage-paths.js
51723
52028
  import { homedir as homedir30 } from "node:os";
51724
- import { join as join50, resolve as resolve11 } from "node:path";
52029
+ import { join as join52, resolve as resolve11 } from "node:path";
51725
52030
 
51726
52031
  // ../core/dist/world/workspace-name.js
51727
52032
  var InvalidWorkspaceNameError = class extends Error {
@@ -51742,25 +52047,25 @@ function validateWorkspaceName(name) {
51742
52047
 
51743
52048
  // ../core/dist/kg/storage-paths.js
51744
52049
  function olamHome2() {
51745
- return process.env.OLAM_HOME ?? join50(homedir30(), ".olam");
52050
+ return process.env.OLAM_HOME ?? join52(homedir30(), ".olam");
51746
52051
  }
51747
52052
  function kgRoot() {
51748
- return join50(olamHome2(), "kg");
52053
+ return join52(olamHome2(), "kg");
51749
52054
  }
51750
52055
  function worldsRoot() {
51751
- return join50(olamHome2(), "worlds");
52056
+ return join52(olamHome2(), "worlds");
51752
52057
  }
51753
- function assertWithinPrefix(path60, prefix, label) {
51754
- if (!path60.startsWith(prefix + "/")) {
51755
- throw new Error(`${label} escape: ${path60} not under ${prefix}/`);
52058
+ function assertWithinPrefix(path62, prefix, label) {
52059
+ if (!path62.startsWith(prefix + "/")) {
52060
+ throw new Error(`${label} escape: ${path62} not under ${prefix}/`);
51756
52061
  }
51757
52062
  }
51758
52063
  function kgPristinePath(workspace) {
51759
52064
  validateWorkspaceName(workspace);
51760
52065
  const root = kgRoot();
51761
- const path60 = resolve11(join50(root, workspace));
51762
- assertWithinPrefix(path60, root, "kgPristinePath");
51763
- return path60;
52066
+ const path62 = resolve11(join52(root, workspace));
52067
+ assertWithinPrefix(path62, root, "kgPristinePath");
52068
+ return path62;
51764
52069
  }
51765
52070
  var KG_PATHS_INTERNALS = Object.freeze({
51766
52071
  olamHome: olamHome2,
@@ -51776,10 +52081,10 @@ var KgOverlayError = class extends Error {
51776
52081
  }
51777
52082
  };
51778
52083
  function ensureGitignoreEntry(worldClonePath) {
51779
- const gitignorePath = path48.join(worldClonePath, ".gitignore");
51780
- if (!fs49.existsSync(gitignorePath))
52084
+ const gitignorePath = path50.join(worldClonePath, ".gitignore");
52085
+ if (!fs51.existsSync(gitignorePath))
51781
52086
  return "no-gitignore";
51782
- const content = fs49.readFileSync(gitignorePath, "utf-8");
52087
+ const content = fs51.readFileSync(gitignorePath, "utf-8");
51783
52088
  const lines = content.split("\n").map((l) => l.trim());
51784
52089
  const recognised = /* @__PURE__ */ new Set([
51785
52090
  "graphify-out",
@@ -51794,31 +52099,31 @@ function ensureGitignoreEntry(worldClonePath) {
51794
52099
  const eol = content.includes("\r\n") ? "\r\n" : "\n";
51795
52100
  const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
51796
52101
  const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
51797
- fs49.appendFileSync(gitignorePath, block, "utf-8");
52102
+ fs51.appendFileSync(gitignorePath, block, "utf-8");
51798
52103
  return "appended";
51799
52104
  }
51800
52105
  function createWorldOverlay(opts) {
51801
52106
  const pristineRoot = kgPristinePath(opts.workspace);
51802
- const pristinePath = path48.join(pristineRoot, "graphify-out");
51803
- if (!fs49.existsSync(pristinePath)) {
52107
+ const pristinePath = path50.join(pristineRoot, "graphify-out");
52108
+ if (!fs51.existsSync(pristinePath)) {
51804
52109
  throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
51805
52110
  }
51806
- if (!path48.isAbsolute(opts.worldClonePath)) {
52111
+ if (!path50.isAbsolute(opts.worldClonePath)) {
51807
52112
  throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
51808
52113
  }
51809
- if (!fs49.existsSync(opts.worldClonePath)) {
52114
+ if (!fs51.existsSync(opts.worldClonePath)) {
51810
52115
  throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
51811
52116
  }
51812
- const overlayPath = path48.join(opts.worldClonePath, "graphify-out");
51813
- if (fs49.existsSync(overlayPath)) {
51814
- fs49.rmSync(overlayPath, { recursive: true, force: true });
52117
+ const overlayPath = path50.join(opts.worldClonePath, "graphify-out");
52118
+ if (fs51.existsSync(overlayPath)) {
52119
+ fs51.rmSync(overlayPath, { recursive: true, force: true });
51815
52120
  }
51816
52121
  const useReflink = process.platform === "darwin";
51817
52122
  let strategy;
51818
52123
  let reflinkError;
51819
52124
  if (useReflink) {
51820
52125
  try {
51821
- execFileSync5("cp", ["-c", "-r", pristinePath, opts.worldClonePath], {
52126
+ execFileSync6("cp", ["-c", "-r", pristinePath, opts.worldClonePath], {
51822
52127
  stdio: ["ignore", "ignore", "pipe"]
51823
52128
  });
51824
52129
  strategy = "cp-c-r-reflink";
@@ -51829,9 +52134,9 @@ function createWorldOverlay(opts) {
51829
52134
  } else {
51830
52135
  strategy = "cp-r";
51831
52136
  }
51832
- if (strategy === "cp-r" || !fs49.existsSync(overlayPath)) {
52137
+ if (strategy === "cp-r" || !fs51.existsSync(overlayPath)) {
51833
52138
  try {
51834
- execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
52139
+ execFileSync6("cp", ["-r", pristinePath, opts.worldClonePath], {
51835
52140
  stdio: ["ignore", "ignore", "pipe"]
51836
52141
  });
51837
52142
  strategy = "cp-r";
@@ -51841,7 +52146,7 @@ function createWorldOverlay(opts) {
51841
52146
  throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
51842
52147
  }
51843
52148
  }
51844
- if (!fs49.existsSync(overlayPath)) {
52149
+ if (!fs51.existsSync(overlayPath)) {
51845
52150
  throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
51846
52151
  }
51847
52152
  const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
@@ -51854,10 +52159,10 @@ function createWorldOverlay(opts) {
51854
52159
  }
51855
52160
 
51856
52161
  // ../core/dist/world/baseline-diff.js
51857
- import { execFileSync as execFileSync6 } from "node:child_process";
51858
- import * as fs50 from "node:fs";
52162
+ import { execFileSync as execFileSync7 } from "node:child_process";
52163
+ import * as fs52 from "node:fs";
51859
52164
  import * as os30 from "node:os";
51860
- import * as path49 from "node:path";
52165
+ import * as path51 from "node:path";
51861
52166
  var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
51862
52167
  function expandHome2(p, homedir37) {
51863
52168
  return p.replace(/^~(?=$|\/|\\)/, homedir37());
@@ -51882,11 +52187,11 @@ ${stderr}`;
51882
52187
  return /unknown revision|bad revision|does not have any commits|HEAD'?: ambiguous|Needed a single revision/.test(blob);
51883
52188
  }
51884
52189
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
51885
- const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
52190
+ const exec = deps.exec ?? ((cmd, args, opts) => execFileSync7(cmd, args, opts));
51886
52191
  const homedir37 = deps.homedir ?? (() => os30.homedir());
51887
- const baselineDir = path49.join(workspacePath, ".olam", "baseline");
52192
+ const baselineDir = path51.join(workspacePath, ".olam", "baseline");
51888
52193
  try {
51889
- fs50.mkdirSync(baselineDir, { recursive: true });
52194
+ fs52.mkdirSync(baselineDir, { recursive: true });
51890
52195
  } catch (err) {
51891
52196
  const msg = err instanceof Error ? err.message : String(err);
51892
52197
  console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
@@ -51898,9 +52203,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
51898
52203
  if (!repo.path)
51899
52204
  continue;
51900
52205
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
51901
- const outPath = path49.join(baselineDir, filename);
52206
+ const outPath = path51.join(baselineDir, filename);
51902
52207
  const repoPath = expandHome2(repo.path, homedir37);
51903
- if (!fs50.existsSync(repoPath)) {
52208
+ if (!fs52.existsSync(repoPath)) {
51904
52209
  writeBaselineFile(outPath, `# repo: ${repo.name}
51905
52210
  # (skipped: path ${repoPath} does not exist)
51906
52211
  `);
@@ -51967,7 +52272,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
51967
52272
  }
51968
52273
  function writeBaselineFile(outPath, content) {
51969
52274
  try {
51970
- fs50.writeFileSync(outPath, content);
52275
+ fs52.writeFileSync(outPath, content);
51971
52276
  } catch (err) {
51972
52277
  const msg = err instanceof Error ? err.message : String(err);
51973
52278
  console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
@@ -51975,11 +52280,11 @@ function writeBaselineFile(outPath, content) {
51975
52280
  }
51976
52281
  function stripWorktreeEdits(repos, workspacePath) {
51977
52282
  for (const repo of repos) {
51978
- const worktreePath = path49.join(workspacePath, repo.name);
51979
- if (!fs50.existsSync(worktreePath))
52283
+ const worktreePath = path51.join(workspacePath, repo.name);
52284
+ if (!fs52.existsSync(worktreePath))
51980
52285
  continue;
51981
52286
  try {
51982
- execFileSync6("git", ["checkout", "--", "."], {
52287
+ execFileSync7("git", ["checkout", "--", "."], {
51983
52288
  cwd: worktreePath,
51984
52289
  stdio: "pipe"
51985
52290
  });
@@ -52006,7 +52311,7 @@ ${stderr.trim()}` : "";
52006
52311
  }
52007
52312
  };
52008
52313
  function captureOperatorDiff(repoPath, deps = {}) {
52009
- const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
52314
+ const exec = deps.exec ?? ((cmd, args, opts) => execFileSync7(cmd, args, opts));
52010
52315
  const unstaged = exec("git", ["diff"], {
52011
52316
  cwd: repoPath,
52012
52317
  encoding: "utf-8",
@@ -52034,22 +52339,22 @@ function extractStderr(err) {
52034
52339
  return typeof raw === "string" ? raw : raw.toString("utf-8");
52035
52340
  }
52036
52341
  function carryUncommittedEdits(repos, workspacePath, deps = {}) {
52037
- const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
52342
+ const exec = deps.exec ?? ((cmd, args, opts) => execFileSync7(cmd, args, opts));
52038
52343
  const homedir37 = deps.homedir ?? (() => os30.homedir());
52039
- const existsSync59 = deps.existsSync ?? ((p) => fs50.existsSync(p));
52040
- const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs50.copyFileSync(src, dest));
52344
+ const existsSync61 = deps.existsSync ?? ((p) => fs52.existsSync(p));
52345
+ const copyFileSync10 = deps.copyFileSync ?? ((src, dest) => fs52.copyFileSync(src, dest));
52041
52346
  const mkdirSync34 = deps.mkdirSync ?? ((dirPath, opts) => {
52042
- fs50.mkdirSync(dirPath, opts);
52347
+ fs52.mkdirSync(dirPath, opts);
52043
52348
  });
52044
52349
  const plans = [];
52045
52350
  for (const repo of repos) {
52046
52351
  if (!repo.path)
52047
52352
  continue;
52048
52353
  const repoPath = expandHome2(repo.path, homedir37);
52049
- const worktreePath = path49.join(workspacePath, repo.name);
52050
- if (!existsSync59(repoPath))
52354
+ const worktreePath = path51.join(workspacePath, repo.name);
52355
+ if (!existsSync61(repoPath))
52051
52356
  continue;
52052
- if (!existsSync59(worktreePath)) {
52357
+ if (!existsSync61(worktreePath)) {
52053
52358
  console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
52054
52359
  continue;
52055
52360
  }
@@ -52107,13 +52412,13 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
52107
52412
  }
52108
52413
  }
52109
52414
  for (const rel of plan.diff.untracked) {
52110
- const src = path49.join(plan.repoPath, rel);
52111
- const dest = path49.join(plan.worktreePath, rel);
52112
- if (!existsSync59(src))
52415
+ const src = path51.join(plan.repoPath, rel);
52416
+ const dest = path51.join(plan.worktreePath, rel);
52417
+ if (!existsSync61(src))
52113
52418
  continue;
52114
52419
  try {
52115
- mkdirSync34(path49.dirname(dest), { recursive: true });
52116
- copyFileSync9(src, dest);
52420
+ mkdirSync34(path51.dirname(dest), { recursive: true });
52421
+ copyFileSync10(src, dest);
52117
52422
  } catch (err) {
52118
52423
  const msg = err instanceof Error ? err.message : String(err);
52119
52424
  console.warn(`[carry] ${plan.name}: copy untracked ${rel} failed: ${msg}`);
@@ -52138,8 +52443,8 @@ function formatBaselineSummary(result) {
52138
52443
  }
52139
52444
 
52140
52445
  // ../core/dist/world/context-injection.js
52141
- import * as fs51 from "node:fs";
52142
- import * as path50 from "node:path";
52446
+ import * as fs53 from "node:fs";
52447
+ import * as path52 from "node:path";
52143
52448
 
52144
52449
  // ../core/dist/world/templates/_generated.js
52145
52450
  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';
@@ -52149,10 +52454,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
52149
52454
  // ../core/dist/world/context-injection.js
52150
52455
  function injectWorldContext(opts) {
52151
52456
  const { world } = opts;
52152
- const claudeDir2 = path50.join(world.workspacePath, ".claude");
52153
- fs51.mkdirSync(claudeDir2, { recursive: true });
52457
+ const claudeDir2 = path52.join(world.workspacePath, ".claude");
52458
+ fs53.mkdirSync(claudeDir2, { recursive: true });
52154
52459
  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));
52155
- fs51.writeFileSync(path50.join(claudeDir2, "CLAUDE.md"), content);
52460
+ fs53.writeFileSync(path52.join(claudeDir2, "CLAUDE.md"), content);
52156
52461
  writeOlamDocs(world.workspacePath);
52157
52462
  }
52158
52463
  function buildTaskBlock(opts) {
@@ -52226,10 +52531,10 @@ function buildExtraContextBlock(extra) {
52226
52531
  ${extra}`;
52227
52532
  }
52228
52533
  function writeOlamDocs(workspacePath) {
52229
- const docsDir = path50.join(workspacePath, ".olam", "docs");
52230
- fs51.mkdirSync(docsDir, { recursive: true });
52231
- fs51.writeFileSync(path50.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
52232
- fs51.writeFileSync(path50.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
52534
+ const docsDir = path52.join(workspacePath, ".olam", "docs");
52535
+ fs53.mkdirSync(docsDir, { recursive: true });
52536
+ fs53.writeFileSync(path52.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
52537
+ fs53.writeFileSync(path52.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
52233
52538
  }
52234
52539
  function formatTaskSource(ctx) {
52235
52540
  if (ctx.source === "linear" && ctx.ticketId) {
@@ -52243,9 +52548,9 @@ function formatTaskSource(ctx) {
52243
52548
  function hasPlanFile(world) {
52244
52549
  if (world.repos.length === 0)
52245
52550
  return false;
52246
- const plansDir = path50.join(world.workspacePath, world.repos[0], "docs", "plans");
52551
+ const plansDir = path52.join(world.workspacePath, world.repos[0], "docs", "plans");
52247
52552
  try {
52248
- return fs51.existsSync(plansDir) && fs51.readdirSync(plansDir).length > 0;
52553
+ return fs53.existsSync(plansDir) && fs53.readdirSync(plansDir).length > 0;
52249
52554
  } catch {
52250
52555
  return false;
52251
52556
  }
@@ -52814,25 +53119,25 @@ init_repo_manifest();
52814
53119
 
52815
53120
  // ../core/dist/world/snapshot.js
52816
53121
  import * as crypto7 from "node:crypto";
52817
- import * as fs52 from "node:fs";
53122
+ import * as fs54 from "node:fs";
52818
53123
  import * as os31 from "node:os";
52819
- import * as path51 from "node:path";
52820
- import { execFileSync as execFileSync7, spawn as spawn5 } from "node:child_process";
53124
+ import * as path53 from "node:path";
53125
+ import { execFileSync as execFileSync8, spawn as spawn5 } from "node:child_process";
52821
53126
  import { gunzipSync } from "node:zlib";
52822
53127
  function snapshotsDir() {
52823
- return process.env["OLAM_SNAPSHOTS_DIR"] ?? path51.join(os31.homedir(), ".olam", "snapshots");
53128
+ return process.env["OLAM_SNAPSHOTS_DIR"] ?? path53.join(os31.homedir(), ".olam", "snapshots");
52824
53129
  }
52825
53130
  function snapshotKindDirByWorkspace(workspace, arch, kind) {
52826
- return path51.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
53131
+ return path53.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
52827
53132
  }
52828
53133
  function cleanupLegacyByWorldDir(worldId) {
52829
- const legacyDir = path51.join(snapshotsDir(), worldId);
53134
+ const legacyDir = path53.join(snapshotsDir(), worldId);
52830
53135
  if (worldId === "by-workspace")
52831
53136
  return;
52832
- if (!fs52.existsSync(legacyDir))
53137
+ if (!fs54.existsSync(legacyDir))
52833
53138
  return;
52834
53139
  try {
52835
- fs52.rmSync(legacyDir, { recursive: true, force: true });
53140
+ fs54.rmSync(legacyDir, { recursive: true, force: true });
52836
53141
  } catch {
52837
53142
  }
52838
53143
  }
@@ -52851,11 +53156,11 @@ function hashBuffers(entries) {
52851
53156
  return hash2.digest("hex").slice(0, 12);
52852
53157
  }
52853
53158
  function computeGemsFingerprint(repoDir, imageDigest) {
52854
- const lockfile = path51.join(repoDir, "Gemfile.lock");
52855
- if (!fs52.existsSync(lockfile))
53159
+ const lockfile = path53.join(repoDir, "Gemfile.lock");
53160
+ if (!fs54.existsSync(lockfile))
52856
53161
  return null;
52857
53162
  const entries = [
52858
- { path: "Gemfile.lock", content: fs52.readFileSync(lockfile) }
53163
+ { path: "Gemfile.lock", content: fs54.readFileSync(lockfile) }
52859
53164
  ];
52860
53165
  if (imageDigest) {
52861
53166
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -52865,10 +53170,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
52865
53170
  function computeNodeFingerprint(repoDir, imageDigest) {
52866
53171
  const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
52867
53172
  for (const name of candidates) {
52868
- const lockfile = path51.join(repoDir, name);
52869
- if (fs52.existsSync(lockfile)) {
53173
+ const lockfile = path53.join(repoDir, name);
53174
+ if (fs54.existsSync(lockfile)) {
52870
53175
  const entries = [
52871
- { path: name, content: fs52.readFileSync(lockfile) }
53176
+ { path: name, content: fs54.readFileSync(lockfile) }
52872
53177
  ];
52873
53178
  if (imageDigest) {
52874
53179
  entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
@@ -52887,18 +53192,18 @@ function unpackTarballAtomic(srcPath, destDir) {
52887
53192
  detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
52888
53193
  };
52889
53194
  }
52890
- const parent = path51.dirname(destDir);
52891
- fs52.mkdirSync(parent, { recursive: true });
53195
+ const parent = path53.dirname(destDir);
53196
+ fs54.mkdirSync(parent, { recursive: true });
52892
53197
  const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
52893
53198
  const tmpDir = `${destDir}${tmpSuffix}`;
52894
53199
  try {
52895
- fs52.mkdirSync(tmpDir, { recursive: true });
52896
- execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
52897
- fs52.renameSync(tmpDir, destDir);
53200
+ fs54.mkdirSync(tmpDir, { recursive: true });
53201
+ execFileSync8("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
53202
+ fs54.renameSync(tmpDir, destDir);
52898
53203
  return { ok: true, entryCount: validation.entries.length };
52899
53204
  } catch (err) {
52900
53205
  try {
52901
- fs52.rmSync(tmpDir, { recursive: true, force: true });
53206
+ fs54.rmSync(tmpDir, { recursive: true, force: true });
52902
53207
  } catch {
52903
53208
  }
52904
53209
  return {
@@ -52909,12 +53214,12 @@ function unpackTarballAtomic(srcPath, destDir) {
52909
53214
  }
52910
53215
  }
52911
53216
  function resolvesWithin(base, target) {
52912
- const resolved = path51.resolve(base, target);
52913
- const baseResolved = path51.resolve(base);
52914
- const rel = path51.relative(baseResolved, resolved);
53217
+ const resolved = path53.resolve(base, target);
53218
+ const baseResolved = path53.resolve(base);
53219
+ const rel = path53.relative(baseResolved, resolved);
52915
53220
  if (rel === "")
52916
53221
  return true;
52917
- return !rel.startsWith("..") && !path51.isAbsolute(rel);
53222
+ return !rel.startsWith("..") && !path53.isAbsolute(rel);
52918
53223
  }
52919
53224
  var TYPE_CHAR_TO_TYPE = {
52920
53225
  "-": "file",
@@ -52964,7 +53269,7 @@ function parseTarListLine(line) {
52964
53269
  function validateHardlinksBinary(tarPath, targetDir) {
52965
53270
  let raw;
52966
53271
  try {
52967
- raw = gunzipSync(fs52.readFileSync(tarPath));
53272
+ raw = gunzipSync(fs54.readFileSync(tarPath));
52968
53273
  } catch {
52969
53274
  return null;
52970
53275
  }
@@ -52979,7 +53284,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
52979
53284
  const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
52980
53285
  const linkNull = block.indexOf(0, 157);
52981
53286
  const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
52982
- if (linkname && (path51.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
53287
+ if (linkname && (path53.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
52983
53288
  return {
52984
53289
  valid: false,
52985
53290
  reason: "hardlink-escape",
@@ -52997,7 +53302,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
52997
53302
  function enumerateAndValidateTarballEntries(tarPath, targetDir) {
52998
53303
  let raw;
52999
53304
  try {
53000
- raw = execFileSync7("tar", ["-tvf", tarPath], {
53305
+ raw = execFileSync8("tar", ["-tvf", tarPath], {
53001
53306
  stdio: ["ignore", "pipe", "pipe"],
53002
53307
  env: { ...process.env, LC_ALL: "C", TZ: "UTC" },
53003
53308
  encoding: "utf-8",
@@ -53017,7 +53322,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
53017
53322
  const entry = parseTarListLine(line);
53018
53323
  if (!entry)
53019
53324
  continue;
53020
- if (path51.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
53325
+ if (path53.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
53021
53326
  return {
53022
53327
  valid: false,
53023
53328
  reason: "path-traversal",
@@ -53025,8 +53330,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
53025
53330
  };
53026
53331
  }
53027
53332
  if (entry.type === "symlink" && entry.linkname !== void 0) {
53028
- const symlinkParent = path51.join(targetDir, path51.dirname(entry.name));
53029
- if (path51.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path51.join(path51.dirname(entry.name), entry.linkname))) {
53333
+ const symlinkParent = path53.join(targetDir, path53.dirname(entry.name));
53334
+ if (path53.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path53.join(path53.dirname(entry.name), entry.linkname))) {
53030
53335
  return {
53031
53336
  valid: false,
53032
53337
  reason: "symlink-escape",
@@ -53036,7 +53341,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
53036
53341
  }
53037
53342
  }
53038
53343
  if (entry.type === "hardlink" && entry.linkname !== void 0) {
53039
- if (path51.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
53344
+ if (path53.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
53040
53345
  return {
53041
53346
  valid: false,
53042
53347
  reason: "hardlink-escape",
@@ -53069,8 +53374,8 @@ function restoreSnapshotsForRepos(input) {
53069
53374
  }
53070
53375
  const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
53071
53376
  const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
53072
- const tarPath = path51.join(archDir, tarFilename);
53073
- if (!fs52.existsSync(tarPath)) {
53377
+ const tarPath = path53.join(archDir, tarFilename);
53378
+ if (!fs54.existsSync(tarPath)) {
53074
53379
  outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
53075
53380
  continue;
53076
53381
  }
@@ -53085,9 +53390,9 @@ function restoreSnapshotsForRepos(input) {
53085
53390
  });
53086
53391
  continue;
53087
53392
  }
53088
- const targetDir = path51.join(repo.worktreeDir, targetSubpath);
53393
+ const targetDir = path53.join(repo.worktreeDir, targetSubpath);
53089
53394
  try {
53090
- fs52.rmSync(targetDir, { recursive: true, force: true });
53395
+ fs54.rmSync(targetDir, { recursive: true, force: true });
53091
53396
  } catch {
53092
53397
  }
53093
53398
  const result = unpackTarballAtomic(tarPath, targetDir);
@@ -53100,8 +53405,8 @@ function restoreSnapshotsForRepos(input) {
53100
53405
  fingerprint
53101
53406
  });
53102
53407
  try {
53103
- fs52.rmSync(tarPath, { force: true });
53104
- fs52.rmSync(manifestPath(tarPath), { force: true });
53408
+ fs54.rmSync(tarPath, { force: true });
53409
+ fs54.rmSync(manifestPath(tarPath), { force: true });
53105
53410
  } catch {
53106
53411
  }
53107
53412
  continue;
@@ -53117,10 +53422,10 @@ function restoreSnapshotsForRepos(input) {
53117
53422
  }
53118
53423
  function readManifest(tarPath) {
53119
53424
  const mPath = manifestPath(tarPath);
53120
- if (!fs52.existsSync(mPath))
53425
+ if (!fs54.existsSync(mPath))
53121
53426
  return null;
53122
53427
  try {
53123
- return JSON.parse(fs52.readFileSync(mPath, "utf-8"));
53428
+ return JSON.parse(fs54.readFileSync(mPath, "utf-8"));
53124
53429
  } catch {
53125
53430
  return null;
53126
53431
  }
@@ -53135,17 +53440,17 @@ function isPidAlive(pid) {
53135
53440
  }
53136
53441
  }
53137
53442
  function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
53138
- fs52.mkdirSync(dir, { recursive: true });
53139
- const lockPath = path51.join(dir, EVICT_LOCK_FILENAME);
53443
+ fs54.mkdirSync(dir, { recursive: true });
53444
+ const lockPath = path53.join(dir, EVICT_LOCK_FILENAME);
53140
53445
  let fd;
53141
53446
  try {
53142
- fd = fs52.openSync(lockPath, fs52.constants.O_WRONLY | fs52.constants.O_CREAT | fs52.constants.O_EXCL, 384);
53447
+ fd = fs54.openSync(lockPath, fs54.constants.O_WRONLY | fs54.constants.O_CREAT | fs54.constants.O_EXCL, 384);
53143
53448
  } catch (err) {
53144
53449
  if (err.code !== "EEXIST")
53145
53450
  return 0;
53146
53451
  let holderPid = null;
53147
53452
  try {
53148
- holderPid = parseInt(fs52.readFileSync(lockPath, "utf-8").trim(), 10);
53453
+ holderPid = parseInt(fs54.readFileSync(lockPath, "utf-8").trim(), 10);
53149
53454
  } catch {
53150
53455
  holderPid = null;
53151
53456
  }
@@ -53153,23 +53458,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
53153
53458
  return 0;
53154
53459
  }
53155
53460
  try {
53156
- fs52.unlinkSync(lockPath);
53157
- fd = fs52.openSync(lockPath, fs52.constants.O_WRONLY | fs52.constants.O_CREAT | fs52.constants.O_EXCL, 384);
53461
+ fs54.unlinkSync(lockPath);
53462
+ fd = fs54.openSync(lockPath, fs54.constants.O_WRONLY | fs54.constants.O_CREAT | fs54.constants.O_EXCL, 384);
53158
53463
  } catch {
53159
53464
  return 0;
53160
53465
  }
53161
53466
  }
53162
53467
  try {
53163
- fs52.writeSync(fd, `${process.pid}
53468
+ fs54.writeSync(fd, `${process.pid}
53164
53469
  `);
53165
53470
  } finally {
53166
- fs52.closeSync(fd);
53471
+ fs54.closeSync(fd);
53167
53472
  }
53168
53473
  try {
53169
53474
  return evictOldSnapshots(maxBytes, dir);
53170
53475
  } finally {
53171
53476
  try {
53172
- fs52.unlinkSync(lockPath);
53477
+ fs54.unlinkSync(lockPath);
53173
53478
  } catch {
53174
53479
  }
53175
53480
  }
@@ -53202,16 +53507,16 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
53202
53507
  }
53203
53508
  }
53204
53509
  function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
53205
- if (!fs52.existsSync(dir))
53510
+ if (!fs54.existsSync(dir))
53206
53511
  return 0;
53207
53512
  const allTars = [];
53208
53513
  const walk = (d) => {
53209
- for (const entry of fs52.readdirSync(d, { withFileTypes: true })) {
53210
- const full = path51.join(d, entry.name);
53514
+ for (const entry of fs54.readdirSync(d, { withFileTypes: true })) {
53515
+ const full = path53.join(d, entry.name);
53211
53516
  if (entry.isDirectory()) {
53212
53517
  walk(full);
53213
53518
  } else if (entry.name.endsWith(".tar.gz")) {
53214
- const stat2 = fs52.statSync(full);
53519
+ const stat2 = fs54.statSync(full);
53215
53520
  allTars.push({ path: full, size: stat2.size, mtime: stat2.mtimeMs });
53216
53521
  }
53217
53522
  }
@@ -53226,8 +53531,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
53226
53531
  for (const tar of allTars) {
53227
53532
  if (remaining <= maxBytes)
53228
53533
  break;
53229
- fs52.rmSync(tar.path, { force: true });
53230
- fs52.rmSync(manifestPath(tar.path), { force: true });
53534
+ fs54.rmSync(tar.path, { force: true });
53535
+ fs54.rmSync(manifestPath(tar.path), { force: true });
53231
53536
  freed += tar.size;
53232
53537
  remaining -= tar.size;
53233
53538
  }
@@ -53344,14 +53649,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
53344
53649
 
53345
53650
  // ../core/dist/world/olam-yaml.js
53346
53651
  init_repo_manifest();
53347
- import * as path52 from "node:path";
53652
+ import * as path54 from "node:path";
53348
53653
  import YAML2 from "yaml";
53349
53654
  function enrichReposWithManifests(repos, workspacePath) {
53350
53655
  return repos.map((repo) => {
53351
53656
  if (repo.manifest !== void 0 && repo.manifest !== null) {
53352
53657
  return repo;
53353
53658
  }
53354
- const repoDir = path52.join(workspacePath, repo.name);
53659
+ const repoDir = path54.join(workspacePath, repo.name);
53355
53660
  let manifest = null;
53356
53661
  try {
53357
53662
  manifest = loadRepoManifest(repoDir);
@@ -53366,8 +53671,8 @@ function enrichReposWithManifests(repos, workspacePath) {
53366
53671
  }
53367
53672
 
53368
53673
  // ../core/dist/policies/loader.js
53369
- import * as fs53 from "node:fs";
53370
- import * as path53 from "node:path";
53674
+ import * as fs55 from "node:fs";
53675
+ import * as path55 from "node:path";
53371
53676
  import { parse as parseYaml5 } from "yaml";
53372
53677
  function parseFrontmatter2(content) {
53373
53678
  const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
@@ -53387,20 +53692,20 @@ function toStringArray(v) {
53387
53692
  return v.filter((x) => typeof x === "string");
53388
53693
  }
53389
53694
  function loadPolicies(workspaceRoot) {
53390
- const policiesDir = path53.join(workspaceRoot, ".olam", "policies");
53391
- if (!fs53.existsSync(policiesDir))
53695
+ const policiesDir = path55.join(workspaceRoot, ".olam", "policies");
53696
+ if (!fs55.existsSync(policiesDir))
53392
53697
  return [];
53393
53698
  let files;
53394
53699
  try {
53395
- files = fs53.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
53700
+ files = fs55.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
53396
53701
  } catch {
53397
53702
  return [];
53398
53703
  }
53399
53704
  const policies = [];
53400
53705
  for (const file2 of files) {
53401
- const filePath = path53.join(policiesDir, file2);
53706
+ const filePath = path55.join(policiesDir, file2);
53402
53707
  try {
53403
- const content = fs53.readFileSync(filePath, "utf8");
53708
+ const content = fs55.readFileSync(filePath, "utf8");
53404
53709
  const parsed = parseFrontmatter2(content);
53405
53710
  if (!parsed) {
53406
53711
  console.warn(`[policies] skipping ${file2}: no valid frontmatter block`);
@@ -53544,9 +53849,9 @@ async function autoDispatchTask(opts) {
53544
53849
  }
53545
53850
 
53546
53851
  // ../core/dist/world/wiki-injection-loader.js
53547
- import * as fs54 from "node:fs";
53852
+ import * as fs56 from "node:fs";
53548
53853
  import * as os32 from "node:os";
53549
- import * as path54 from "node:path";
53854
+ import * as path56 from "node:path";
53550
53855
  var WIKI_INJECTION_FLAG = "OLAM_WIKI_INJECTION";
53551
53856
  var WIKI_PATH_ENV = "OLAM_WIKI_PATH";
53552
53857
  function flagEnabled(value) {
@@ -53559,14 +53864,14 @@ function wikiBlobPath() {
53559
53864
  const override = process.env[WIKI_PATH_ENV];
53560
53865
  if (override && override.length > 0)
53561
53866
  return override;
53562
- return path54.join(os32.homedir(), ".olam", "wiki.json");
53867
+ return path56.join(os32.homedir(), ".olam", "wiki.json");
53563
53868
  }
53564
53869
  function defaultReadBlob() {
53565
53870
  const p = wikiBlobPath();
53566
53871
  try {
53567
- if (!fs54.existsSync(p))
53872
+ if (!fs56.existsSync(p))
53568
53873
  return null;
53569
- return fs54.readFileSync(p, "utf8");
53874
+ return fs56.readFileSync(p, "utf8");
53570
53875
  } catch {
53571
53876
  return null;
53572
53877
  }
@@ -53605,12 +53910,12 @@ init_store2();
53605
53910
  init_bridge();
53606
53911
 
53607
53912
  // ../core/dist/global-config/runbook-resolver.js
53608
- import * as fs55 from "node:fs";
53913
+ import * as fs57 from "node:fs";
53609
53914
  import * as os33 from "node:os";
53610
- import * as path55 from "node:path";
53915
+ import * as path57 from "node:path";
53611
53916
  function expandTilde(p) {
53612
53917
  if (p === "~" || p.startsWith("~/")) {
53613
- return path55.join(os33.homedir(), p.slice(1));
53918
+ return path57.join(os33.homedir(), p.slice(1));
53614
53919
  }
53615
53920
  return p;
53616
53921
  }
@@ -53622,7 +53927,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
53622
53927
  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.`);
53623
53928
  }
53624
53929
  const resolvedPath = expandTilde(entry.path);
53625
- if (!fs55.existsSync(resolvedPath)) {
53930
+ if (!fs57.existsSync(resolvedPath)) {
53626
53931
  throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
53627
53932
  }
53628
53933
  }
@@ -53638,19 +53943,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
53638
53943
  init_port_validator();
53639
53944
 
53640
53945
  // ../core/dist/world/bootstrap-hooks.js
53641
- import * as fs56 from "node:fs";
53642
- import * as path56 from "node:path";
53946
+ import * as fs58 from "node:fs";
53947
+ import * as path58 from "node:path";
53643
53948
  function runFixtureCopySeeds(seeds, workspacePath) {
53644
53949
  if (!seeds)
53645
53950
  return;
53646
53951
  for (const seed of seeds) {
53647
53952
  if (seed.type !== "fixture-copy")
53648
53953
  continue;
53649
- const srcAbs = path56.resolve(workspacePath, seed.repo, seed.src);
53650
- const destAbs = path56.resolve(workspacePath, seed.repo, seed.dest);
53651
- const destDir = path56.dirname(destAbs);
53652
- fs56.mkdirSync(destDir, { recursive: true });
53653
- fs56.cpSync(srcAbs, destAbs, { recursive: true, force: true });
53954
+ const srcAbs = path58.resolve(workspacePath, seed.repo, seed.src);
53955
+ const destAbs = path58.resolve(workspacePath, seed.repo, seed.dest);
53956
+ const destDir = path58.dirname(destAbs);
53957
+ fs58.mkdirSync(destDir, { recursive: true });
53958
+ fs58.cpSync(srcAbs, destAbs, { recursive: true, force: true });
53654
53959
  }
53655
53960
  }
53656
53961
  async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
@@ -54353,7 +54658,7 @@ ${detail}`);
54353
54658
  runbookSeeds = resolved.seeds;
54354
54659
  }
54355
54660
  const worldId = generateWorldId();
54356
- const workspacePath = path57.join(os34.homedir(), ".olam", "worlds", worldId);
54661
+ const workspacePath = path59.join(os34.homedir(), ".olam", "worlds", worldId);
54357
54662
  const portOffset = this.registry.getNextPortOffset();
54358
54663
  const branch = opts.branchName ?? `olam/${worldId}`;
54359
54664
  const repos = await this.resolveReposWithWorkspace(opts);
@@ -54436,37 +54741,37 @@ ${detail}`);
54436
54741
  if (!repo.path)
54437
54742
  continue;
54438
54743
  const sourceRoot = repo.path.replace(/^~/, os34.homedir());
54439
- const worktreeRoot = path57.join(workspacePath, repo.name);
54440
- if (!fs57.existsSync(sourceRoot) || !fs57.existsSync(worktreeRoot))
54744
+ const worktreeRoot = path59.join(workspacePath, repo.name);
54745
+ if (!fs59.existsSync(sourceRoot) || !fs59.existsSync(worktreeRoot))
54441
54746
  continue;
54442
54747
  let copied = 0;
54443
54748
  for (const pattern of RUNTIME_FILE_PATTERNS) {
54444
54749
  const matches2 = [];
54445
54750
  if (pattern.includes("*")) {
54446
- const [dir, glob] = [path57.dirname(pattern), path57.basename(pattern)];
54447
- const sourceDir = path57.join(sourceRoot, dir);
54448
- if (fs57.existsSync(sourceDir)) {
54751
+ const [dir, glob] = [path59.dirname(pattern), path59.basename(pattern)];
54752
+ const sourceDir = path59.join(sourceRoot, dir);
54753
+ if (fs59.existsSync(sourceDir)) {
54449
54754
  const ext = glob.replace(/^\*+/, "");
54450
54755
  try {
54451
- for (const entry of fs57.readdirSync(sourceDir)) {
54756
+ for (const entry of fs59.readdirSync(sourceDir)) {
54452
54757
  if (ext === "" || entry.endsWith(ext))
54453
- matches2.push(path57.join(dir, entry));
54758
+ matches2.push(path59.join(dir, entry));
54454
54759
  }
54455
54760
  } catch {
54456
54761
  }
54457
54762
  }
54458
- } else if (fs57.existsSync(path57.join(sourceRoot, pattern))) {
54763
+ } else if (fs59.existsSync(path59.join(sourceRoot, pattern))) {
54459
54764
  matches2.push(pattern);
54460
54765
  }
54461
54766
  for (const rel of matches2) {
54462
- const src = path57.join(sourceRoot, rel);
54463
- const dst = path57.join(worktreeRoot, rel);
54767
+ const src = path59.join(sourceRoot, rel);
54768
+ const dst = path59.join(worktreeRoot, rel);
54464
54769
  try {
54465
- const st = fs57.statSync(src);
54770
+ const st = fs59.statSync(src);
54466
54771
  if (!st.isFile())
54467
54772
  continue;
54468
- fs57.mkdirSync(path57.dirname(dst), { recursive: true });
54469
- fs57.copyFileSync(src, dst);
54773
+ fs59.mkdirSync(path59.dirname(dst), { recursive: true });
54774
+ fs59.copyFileSync(src, dst);
54470
54775
  copied++;
54471
54776
  } catch {
54472
54777
  }
@@ -54552,7 +54857,7 @@ ${detail}`);
54552
54857
  }
54553
54858
  const overlayAttachments = [];
54554
54859
  for (const repo of repos) {
54555
- const worldClonePath = path57.join(workspacePath, repo.name);
54860
+ const worldClonePath = path59.join(workspacePath, repo.name);
54556
54861
  try {
54557
54862
  const result = createWorldOverlay({
54558
54863
  workspace: repo.name,
@@ -54607,7 +54912,7 @@ ${detail}`);
54607
54912
  try {
54608
54913
  const hostExec = makeHostExecFn();
54609
54914
  for (const repo of repos) {
54610
- const repoDir = path57.join(workspacePath, repo.name);
54915
+ const repoDir = path59.join(workspacePath, repo.name);
54611
54916
  if (repo.stack && Object.keys(repo.stack).length > 0) {
54612
54917
  preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
54613
54918
  } else {
@@ -54651,10 +54956,10 @@ ${detail}`);
54651
54956
  const worldEnv = {};
54652
54957
  if (opts.task)
54653
54958
  worldEnv.OLAM_TASK = opts.task;
54654
- const r2CredsPath = path57.join(os34.homedir(), ".olam", "r2-credentials.json");
54655
- if (fs57.existsSync(r2CredsPath)) {
54959
+ const r2CredsPath = path59.join(os34.homedir(), ".olam", "r2-credentials.json");
54960
+ if (fs59.existsSync(r2CredsPath)) {
54656
54961
  try {
54657
- const r2Raw = fs57.readFileSync(r2CredsPath, "utf-8").trim();
54962
+ const r2Raw = fs59.readFileSync(r2CredsPath, "utf-8").trim();
54658
54963
  if (r2Raw.length > 0) {
54659
54964
  const r2 = JSON.parse(r2Raw);
54660
54965
  if (typeof r2.account_id === "string")
@@ -54671,10 +54976,10 @@ ${detail}`);
54671
54976
  } catch {
54672
54977
  }
54673
54978
  }
54674
- const keysYamlPath = path57.join(os34.homedir(), ".olam", "keys.yaml");
54675
- if (fs57.existsSync(keysYamlPath)) {
54979
+ const keysYamlPath = path59.join(os34.homedir(), ".olam", "keys.yaml");
54980
+ if (fs59.existsSync(keysYamlPath)) {
54676
54981
  try {
54677
- const keysRaw = fs57.readFileSync(keysYamlPath, "utf-8").trim();
54982
+ const keysRaw = fs59.readFileSync(keysYamlPath, "utf-8").trim();
54678
54983
  if (keysRaw.length > 0) {
54679
54984
  const { default: YAML3 } = await import("yaml");
54680
54985
  const parsed = YAML3.parse(keysRaw);
@@ -54734,10 +55039,10 @@ ${detail}`);
54734
55039
  worldEnv[k] = v;
54735
55040
  }
54736
55041
  for (const { repoName, relativePath, content } of fileWrites) {
54737
- const absPath = path57.join(workspacePath, repoName, relativePath);
55042
+ const absPath = path59.join(workspacePath, repoName, relativePath);
54738
55043
  try {
54739
- fs57.mkdirSync(path57.dirname(absPath), { recursive: true });
54740
- fs57.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
55044
+ fs59.mkdirSync(path59.dirname(absPath), { recursive: true });
55045
+ fs59.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
54741
55046
  mode: 384
54742
55047
  });
54743
55048
  console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
@@ -54914,7 +55219,7 @@ ${detail}`);
54914
55219
  imageDigest: void 0,
54915
55220
  repos: enrichedRepos.map((r) => ({
54916
55221
  name: r.name,
54917
- worktreeDir: path57.join(workspacePath, r.name)
55222
+ worktreeDir: path59.join(workspacePath, r.name)
54918
55223
  }))
54919
55224
  });
54920
55225
  for (const out of restoreResult.outcomes) {
@@ -55020,7 +55325,7 @@ ${detail}`);
55020
55325
  }
55021
55326
  if (opts.task) {
55022
55327
  const allPolicies = repos.flatMap((repo) => {
55023
- const repoWorktree = path57.join(workspacePath, repo.name);
55328
+ const repoWorktree = path59.join(workspacePath, repo.name);
55024
55329
  try {
55025
55330
  return loadPolicies(repoWorktree);
55026
55331
  } catch (err) {
@@ -55033,8 +55338,8 @@ ${detail}`);
55033
55338
  try {
55034
55339
  execSync6(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
55035
55340
  for (const repo of repos) {
55036
- const policiesDir = path57.join(workspacePath, repo.name, ".olam", "policies");
55037
- if (fs57.existsSync(policiesDir)) {
55341
+ const policiesDir = path59.join(workspacePath, repo.name, ".olam", "policies");
55342
+ if (fs59.existsSync(policiesDir)) {
55038
55343
  execSync6(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
55039
55344
  }
55040
55345
  }
@@ -55144,8 +55449,8 @@ ${detail}`);
55144
55449
  } catch {
55145
55450
  }
55146
55451
  try {
55147
- fs57.rmSync(world.workspacePath, { recursive: true, force: true });
55148
- if (fs57.existsSync(world.workspacePath)) {
55452
+ fs59.rmSync(world.workspacePath, { recursive: true, force: true });
55453
+ if (fs59.existsSync(world.workspacePath)) {
55149
55454
  console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
55150
55455
  }
55151
55456
  } catch (err) {
@@ -55255,14 +55560,14 @@ ${detail}`);
55255
55560
  }).filter((r) => r !== void 0);
55256
55561
  }
55257
55562
  transportPlanFile(planFilePath, workspacePath, repoNames) {
55258
- const planContent = fs57.readFileSync(planFilePath, "utf-8");
55259
- const planFileName = path57.basename(planFilePath);
55563
+ const planContent = fs59.readFileSync(planFilePath, "utf-8");
55564
+ const planFileName = path59.basename(planFilePath);
55260
55565
  const targetRepo = repoNames[0];
55261
55566
  if (!targetRepo)
55262
55567
  return;
55263
- const plansDir = path57.join(workspacePath, targetRepo, "docs", "plans");
55264
- fs57.mkdirSync(plansDir, { recursive: true });
55265
- fs57.writeFileSync(path57.join(plansDir, planFileName), planContent);
55568
+ const plansDir = path59.join(workspacePath, targetRepo, "docs", "plans");
55569
+ fs59.mkdirSync(plansDir, { recursive: true });
55570
+ fs59.writeFileSync(path59.join(plansDir, planFileName), planContent);
55266
55571
  }
55267
55572
  resolveServices(repos) {
55268
55573
  const services = [];
@@ -55726,8 +56031,8 @@ import * as http2 from "node:http";
55726
56031
 
55727
56032
  // ../core/dist/dashboard/server.js
55728
56033
  import * as http from "node:http";
55729
- import * as fs58 from "node:fs";
55730
- import * as path58 from "node:path";
56034
+ import * as fs60 from "node:fs";
56035
+ import * as path60 from "node:path";
55731
56036
  import { fileURLToPath as fileURLToPath4 } from "node:url";
55732
56037
 
55733
56038
  // ../core/dist/dashboard/serialize.js
@@ -56062,7 +56367,7 @@ function notFound(res) {
56062
56367
  }
56063
56368
  function openThoughtStore(workspacePath) {
56064
56369
  const dbPath = getWorldDbPath(workspacePath);
56065
- if (!fs58.existsSync(dbPath))
56370
+ if (!fs60.existsSync(dbPath))
56066
56371
  return null;
56067
56372
  return new ThoughtLocalStore(dbPath);
56068
56373
  }
@@ -56233,13 +56538,13 @@ function findSessionInWorld(registry2, sessionId) {
56233
56538
  }
56234
56539
  function createDashboardServer(opts) {
56235
56540
  const { port: port2, registry: registry2 } = opts;
56236
- const thisDir = path58.dirname(fileURLToPath4(import.meta.url));
56237
- const defaultPublicDir = path58.resolve(thisDir, "../../../control-plane/public");
56541
+ const thisDir = path60.dirname(fileURLToPath4(import.meta.url));
56542
+ const defaultPublicDir = path60.resolve(thisDir, "../../../control-plane/public");
56238
56543
  const publicDir = opts.publicDir ?? defaultPublicDir;
56239
- let hasPublicDir = fs58.existsSync(publicDir);
56544
+ let hasPublicDir = fs60.existsSync(publicDir);
56240
56545
  const server = http.createServer((req, res) => {
56241
56546
  if (!hasPublicDir) {
56242
- hasPublicDir = fs58.existsSync(publicDir);
56547
+ hasPublicDir = fs60.existsSync(publicDir);
56243
56548
  }
56244
56549
  const host = req.headers.host ?? `localhost:${port2}`;
56245
56550
  const url3 = new URL(req.url ?? "/", `http://${host}`);
@@ -56513,22 +56818,22 @@ function createDashboardServer(opts) {
56513
56818
  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>`);
56514
56819
  return;
56515
56820
  }
56516
- let filePath = path58.join(publicDir, pathname === "/" ? "index.html" : pathname);
56821
+ let filePath = path60.join(publicDir, pathname === "/" ? "index.html" : pathname);
56517
56822
  if (!filePath.startsWith(publicDir)) {
56518
56823
  notFound(res);
56519
56824
  return;
56520
56825
  }
56521
- if (fs58.existsSync(filePath) && fs58.statSync(filePath).isFile()) {
56522
- const ext = path58.extname(filePath);
56826
+ if (fs60.existsSync(filePath) && fs60.statSync(filePath).isFile()) {
56827
+ const ext = path60.extname(filePath);
56523
56828
  const contentType = MIME[ext] ?? "application/octet-stream";
56524
56829
  res.writeHead(200, { "Content-Type": contentType });
56525
- fs58.createReadStream(filePath).pipe(res);
56830
+ fs60.createReadStream(filePath).pipe(res);
56526
56831
  return;
56527
56832
  }
56528
- filePath = path58.join(publicDir, "index.html");
56529
- if (fs58.existsSync(filePath)) {
56833
+ filePath = path60.join(publicDir, "index.html");
56834
+ if (fs60.existsSync(filePath)) {
56530
56835
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
56531
- fs58.createReadStream(filePath).pipe(res);
56836
+ fs60.createReadStream(filePath).pipe(res);
56532
56837
  return;
56533
56838
  }
56534
56839
  notFound(res);
@@ -56538,17 +56843,17 @@ function createDashboardServer(opts) {
56538
56843
  }
56539
56844
 
56540
56845
  // ../core/dist/dashboard/state.js
56541
- import * as fs59 from "node:fs";
56846
+ import * as fs61 from "node:fs";
56542
56847
  import * as os35 from "node:os";
56543
- import * as path59 from "node:path";
56544
- var STATE_PATH = path59.join(os35.homedir(), ".olam", "dashboard.json");
56848
+ import * as path61 from "node:path";
56849
+ var STATE_PATH = path61.join(os35.homedir(), ".olam", "dashboard.json");
56545
56850
  function saveDashboardState(state) {
56546
- fs59.mkdirSync(path59.dirname(STATE_PATH), { recursive: true });
56547
- fs59.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
56851
+ fs61.mkdirSync(path61.dirname(STATE_PATH), { recursive: true });
56852
+ fs61.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
56548
56853
  }
56549
56854
  function loadDashboardState() {
56550
56855
  try {
56551
- const raw = fs59.readFileSync(STATE_PATH, "utf-8");
56856
+ const raw = fs61.readFileSync(STATE_PATH, "utf-8");
56552
56857
  return JSON.parse(raw);
56553
56858
  } catch {
56554
56859
  return null;
@@ -56556,7 +56861,7 @@ function loadDashboardState() {
56556
56861
  }
56557
56862
  function clearDashboardState() {
56558
56863
  try {
56559
- fs59.unlinkSync(STATE_PATH);
56864
+ fs61.unlinkSync(STATE_PATH);
56560
56865
  } catch {
56561
56866
  }
56562
56867
  }
@@ -56836,8 +57141,8 @@ var PleriClient = class {
56836
57141
  };
56837
57142
 
56838
57143
  // ../mcp-server/src/env-loader.ts
56839
- import { readFileSync as readFileSync46, existsSync as existsSync58, statSync as statSync14 } from "node:fs";
56840
- import { join as join62, dirname as dirname31, resolve as resolve15 } from "node:path";
57144
+ import { readFileSync as readFileSync47, existsSync as existsSync60, statSync as statSync15 } from "node:fs";
57145
+ import { join as join64, dirname as dirname31, resolve as resolve15 } from "node:path";
56841
57146
  var PROJECT_MARKERS = [
56842
57147
  ".olam/config.yaml",
56843
57148
  ".olam/config.yml",
@@ -56849,12 +57154,12 @@ function findProjectRoot2(startDir) {
56849
57154
  const root = resolve15("/");
56850
57155
  while (true) {
56851
57156
  for (const marker of PROJECT_MARKERS) {
56852
- if (existsSync58(join62(dir, marker))) return dir;
57157
+ if (existsSync60(join64(dir, marker))) return dir;
56853
57158
  }
56854
- const pkg = join62(dir, "package.json");
56855
- if (existsSync58(pkg)) {
57159
+ const pkg = join64(dir, "package.json");
57160
+ if (existsSync60(pkg)) {
56856
57161
  try {
56857
- const json2 = JSON.parse(readFileSync46(pkg, "utf8"));
57162
+ const json2 = JSON.parse(readFileSync47(pkg, "utf8"));
56858
57163
  const isOlamWorkspace = typeof json2.name === "string" && json2.name.startsWith("@olam/");
56859
57164
  const hasOlamDep = json2.dependencies && Object.keys(json2.dependencies).some((k) => k.startsWith("@olam/")) || json2.devDependencies && Object.keys(json2.devDependencies).some((k) => k.startsWith("@olam/"));
56860
57165
  if (isOlamWorkspace || hasOlamDep) return dir;
@@ -56866,9 +57171,9 @@ function findProjectRoot2(startDir) {
56866
57171
  dir = parent;
56867
57172
  }
56868
57173
  }
56869
- function parseEnvFile(path60) {
57174
+ function parseEnvFile(path62) {
56870
57175
  const out = {};
56871
- const raw = readFileSync46(path60, "utf8");
57176
+ const raw = readFileSync47(path62, "utf8");
56872
57177
  for (const line of raw.split(/\r?\n/)) {
56873
57178
  const trimmed = line.trim();
56874
57179
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -56891,8 +57196,8 @@ function loadProjectEnv(startDir = process.cwd()) {
56891
57196
  const filesRead = [];
56892
57197
  const merged = {};
56893
57198
  for (const name of [".env", ".env.local"]) {
56894
- const p = join62(root, name);
56895
- if (existsSync58(p) && statSync14(p).isFile()) {
57199
+ const p = join64(root, name);
57200
+ if (existsSync60(p) && statSync15(p).isFile()) {
56896
57201
  Object.assign(merged, parseEnvFile(p));
56897
57202
  filesRead.push(p);
56898
57203
  }