@pleri/olam-cli 0.1.199 → 0.1.201

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/ask/knowledge-pack.generated.d.ts.map +1 -1
  2. package/dist/ask/knowledge-pack.generated.js +3 -1
  3. package/dist/ask/knowledge-pack.generated.js.map +1 -1
  4. package/dist/commands/auth.d.ts.map +1 -1
  5. package/dist/commands/auth.js +23 -8
  6. package/dist/commands/auth.js.map +1 -1
  7. package/dist/commands/create.d.ts.map +1 -1
  8. package/dist/commands/create.js +3 -0
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/flywheel/diversity-check.d.ts +1 -1
  11. package/dist/commands/flywheel/diversity-check.js +1 -1
  12. package/dist/commands/flywheel/k5-score.d.ts +1 -1
  13. package/dist/commands/flywheel/k5-score.js +1 -1
  14. package/dist/commands/flywheel/k5-validate.d.ts +1 -1
  15. package/dist/commands/init.js +1 -1
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/kg-mirror.d.ts +16 -0
  18. package/dist/commands/kg-mirror.d.ts.map +1 -1
  19. package/dist/commands/kg-mirror.js +94 -0
  20. package/dist/commands/kg-mirror.js.map +1 -1
  21. package/dist/commands/ps.d.ts.map +1 -1
  22. package/dist/commands/ps.js +7 -3
  23. package/dist/commands/ps.js.map +1 -1
  24. package/dist/commands/refresh.js +1 -1
  25. package/dist/commands/refresh.js.map +1 -1
  26. package/dist/commands/skills-100x.d.ts +34 -0
  27. package/dist/commands/skills-100x.d.ts.map +1 -0
  28. package/dist/commands/{skills-10x.js → skills-100x.js} +138 -41
  29. package/dist/commands/skills-100x.js.map +1 -0
  30. package/dist/commands/skills-install-model-router.d.ts +20 -0
  31. package/dist/commands/skills-install-model-router.d.ts.map +1 -0
  32. package/dist/commands/skills-install-model-router.js +55 -0
  33. package/dist/commands/skills-install-model-router.js.map +1 -0
  34. package/dist/commands/skills.d.ts.map +1 -1
  35. package/dist/commands/skills.js +2 -0
  36. package/dist/commands/skills.js.map +1 -1
  37. package/dist/commands/status.d.ts.map +1 -1
  38. package/dist/commands/status.js +0 -1
  39. package/dist/commands/status.js.map +1 -1
  40. package/dist/commands/workspace.d.ts.map +1 -1
  41. package/dist/commands/workspace.js +1 -2
  42. package/dist/commands/workspace.js.map +1 -1
  43. package/dist/image-digests.json +8 -8
  44. package/dist/index.js +1127 -716
  45. package/dist/index.js.map +1 -1
  46. package/dist/lib/help-groups.js +1 -1
  47. package/dist/lib/help-groups.js.map +1 -1
  48. package/dist/mcp-server.js +547 -346
  49. package/hermes-bundle/version.json +1 -1
  50. package/hooks/model-router.py +445 -0
  51. package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
  52. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
  53. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
  54. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
  55. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
  56. package/package.json +2 -1
  57. package/dist/commands/skills-10x.d.ts +0 -23
  58. package/dist/commands/skills-10x.d.ts.map +0 -1
  59. package/dist/commands/skills-10x.js.map +0 -1
package/dist/index.js CHANGED
@@ -5568,7 +5568,7 @@ async function safeText(res) {
5568
5568
  }
5569
5569
  }
5570
5570
  function sleep(ms) {
5571
- return new Promise((resolve30) => setTimeout(resolve30, ms));
5571
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
5572
5572
  }
5573
5573
  var DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, RETRY_COUNT, RETRY_BACKOFF_MS, AuthClient;
5574
5574
  var init_client = __esm({
@@ -5721,7 +5721,7 @@ function resolveAuthServicePath() {
5721
5721
  return path10.join(pkgsDir, "auth-service");
5722
5722
  }
5723
5723
  function sleep2(ms) {
5724
- return new Promise((resolve30) => setTimeout(resolve30, ms));
5724
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
5725
5725
  }
5726
5726
  var DEFAULT_PORT, DEFAULT_VOLUME, DEFAULT_CONTAINER, DEFAULT_IMAGE, AuthContainerController;
5727
5727
  var init_container = __esm({
@@ -6032,7 +6032,7 @@ var init_network = __esm({
6032
6032
  // ../adapters/dist/docker/pull.js
6033
6033
  import { spawn } from "node:child_process";
6034
6034
  function spawnAsync(cmd, args, opts = {}) {
6035
- return new Promise((resolve30) => {
6035
+ return new Promise((resolve31) => {
6036
6036
  const child = spawn(cmd, [...args], {
6037
6037
  stdio: ["ignore", "pipe", "pipe"],
6038
6038
  signal: opts.signal
@@ -6046,10 +6046,10 @@ function spawnAsync(cmd, args, opts = {}) {
6046
6046
  stderr += chunk.toString();
6047
6047
  });
6048
6048
  child.on("error", (err) => {
6049
- resolve30({ exitCode: -1, stdout, stderr: stderr + err.message });
6049
+ resolve31({ exitCode: -1, stdout, stderr: stderr + err.message });
6050
6050
  });
6051
6051
  child.on("close", (code) => {
6052
- resolve30({ exitCode: code ?? -1, stdout, stderr });
6052
+ resolve31({ exitCode: code ?? -1, stdout, stderr });
6053
6053
  });
6054
6054
  });
6055
6055
  }
@@ -6614,7 +6614,7 @@ var demuxStream, execInContainer;
6614
6614
  var init_exec = __esm({
6615
6615
  "../adapters/dist/docker/exec.js"() {
6616
6616
  "use strict";
6617
- demuxStream = (stream) => new Promise((resolve30, reject) => {
6617
+ demuxStream = (stream) => new Promise((resolve31, reject) => {
6618
6618
  const stdoutChunks = [];
6619
6619
  const stderrChunks = [];
6620
6620
  const stdout = new PassThrough();
@@ -6628,7 +6628,7 @@ var init_exec = __esm({
6628
6628
  stream.pipe(stdout);
6629
6629
  }
6630
6630
  stream.on("end", () => {
6631
- resolve30({
6631
+ resolve31({
6632
6632
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
6633
6633
  stderr: Buffer.concat(stderrChunks).toString("utf-8")
6634
6634
  });
@@ -7088,7 +7088,7 @@ var init_connection = __esm({
7088
7088
  // -----------------------------------------------------------------------
7089
7089
  async exec(host, command) {
7090
7090
  const client = await this.getConnection(host);
7091
- return new Promise((resolve30, reject) => {
7091
+ return new Promise((resolve31, reject) => {
7092
7092
  client.exec(command, (err, stream) => {
7093
7093
  if (err) {
7094
7094
  reject(new Error(`SSH exec failed on ${host}: ${err.message}`));
@@ -7103,7 +7103,7 @@ var init_connection = __esm({
7103
7103
  stderr += data.toString();
7104
7104
  });
7105
7105
  stream.on("close", (code) => {
7106
- resolve30({
7106
+ resolve31({
7107
7107
  exitCode: code ?? 0,
7108
7108
  stdout: stdout.trimEnd(),
7109
7109
  stderr: stderr.trimEnd()
@@ -7134,10 +7134,10 @@ var init_connection = __esm({
7134
7134
  throw new Error(`No SSH configuration found for host: ${host}`);
7135
7135
  }
7136
7136
  const client = new SSHClient();
7137
- return new Promise((resolve30, reject) => {
7137
+ return new Promise((resolve31, reject) => {
7138
7138
  client.on("ready", () => {
7139
7139
  this.connections.set(host, client);
7140
- resolve30(client);
7140
+ resolve31(client);
7141
7141
  }).on("error", (err) => {
7142
7142
  this.connections.delete(host);
7143
7143
  reject(new Error(`SSH connection to ${host} failed: ${err.message}`));
@@ -9539,8 +9539,8 @@ import { execFileSync as execFileSync4 } from "node:child_process";
9539
9539
  import * as fs17 from "node:fs";
9540
9540
  import * as os11 from "node:os";
9541
9541
  import * as path19 from "node:path";
9542
- function expandHome2(p, homedir76) {
9543
- return p.replace(/^~(?=$|\/|\\)/, homedir76());
9542
+ function expandHome2(p, homedir77) {
9543
+ return p.replace(/^~(?=$|\/|\\)/, homedir77());
9544
9544
  }
9545
9545
  function sanitizeRepoFilename(name) {
9546
9546
  const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -9563,7 +9563,7 @@ ${stderr}`;
9563
9563
  }
9564
9564
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
9565
9565
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
9566
- const homedir76 = deps.homedir ?? (() => os11.homedir());
9566
+ const homedir77 = deps.homedir ?? (() => os11.homedir());
9567
9567
  const baselineDir = path19.join(workspacePath, ".olam", "baseline");
9568
9568
  try {
9569
9569
  fs17.mkdirSync(baselineDir, { recursive: true });
@@ -9579,7 +9579,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
9579
9579
  continue;
9580
9580
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
9581
9581
  const outPath = path19.join(baselineDir, filename);
9582
- const repoPath = expandHome2(repo.path, homedir76);
9582
+ const repoPath = expandHome2(repo.path, homedir77);
9583
9583
  if (!fs17.existsSync(repoPath)) {
9584
9584
  writeBaselineFile(outPath, `# repo: ${repo.name}
9585
9585
  # (skipped: path ${repoPath} does not exist)
@@ -9699,21 +9699,21 @@ function extractStderr(err) {
9699
9699
  }
9700
9700
  function carryUncommittedEdits(repos, workspacePath, deps = {}) {
9701
9701
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
9702
- const homedir76 = deps.homedir ?? (() => os11.homedir());
9703
- const existsSync120 = deps.existsSync ?? ((p) => fs17.existsSync(p));
9702
+ const homedir77 = deps.homedir ?? (() => os11.homedir());
9703
+ const existsSync122 = deps.existsSync ?? ((p) => fs17.existsSync(p));
9704
9704
  const copyFileSync17 = deps.copyFileSync ?? ((src, dest) => fs17.copyFileSync(src, dest));
9705
- const mkdirSync72 = deps.mkdirSync ?? ((dirPath, opts) => {
9705
+ const mkdirSync73 = deps.mkdirSync ?? ((dirPath, opts) => {
9706
9706
  fs17.mkdirSync(dirPath, opts);
9707
9707
  });
9708
9708
  const plans = [];
9709
9709
  for (const repo of repos) {
9710
9710
  if (!repo.path)
9711
9711
  continue;
9712
- const repoPath = expandHome2(repo.path, homedir76);
9712
+ const repoPath = expandHome2(repo.path, homedir77);
9713
9713
  const worktreePath = path19.join(workspacePath, repo.name);
9714
- if (!existsSync120(repoPath))
9714
+ if (!existsSync122(repoPath))
9715
9715
  continue;
9716
- if (!existsSync120(worktreePath)) {
9716
+ if (!existsSync122(worktreePath)) {
9717
9717
  console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
9718
9718
  continue;
9719
9719
  }
@@ -9773,10 +9773,10 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
9773
9773
  for (const rel of plan.diff.untracked) {
9774
9774
  const src = path19.join(plan.repoPath, rel);
9775
9775
  const dest = path19.join(plan.worktreePath, rel);
9776
- if (!existsSync120(src))
9776
+ if (!existsSync122(src))
9777
9777
  continue;
9778
9778
  try {
9779
- mkdirSync72(path19.dirname(dest), { recursive: true });
9779
+ mkdirSync73(path19.dirname(dest), { recursive: true });
9780
9780
  copyFileSync17(src, dest);
9781
9781
  } catch (err) {
9782
9782
  const msg = err instanceof Error ? err.message : String(err);
@@ -11425,7 +11425,7 @@ var init_auto_dispatch_task = __esm({
11425
11425
  this.name = "TaskDispatchError";
11426
11426
  }
11427
11427
  };
11428
- DEFAULT_SLEEP = (ms) => new Promise((resolve30) => setTimeout(resolve30, ms));
11428
+ DEFAULT_SLEEP = (ms) => new Promise((resolve31) => setTimeout(resolve31, ms));
11429
11429
  }
11430
11430
  });
11431
11431
 
@@ -11660,7 +11660,7 @@ var init_schema4 = __esm({
11660
11660
  env: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.string())).optional(),
11661
11661
  updatedAt: external_exports.number().int().nonnegative()
11662
11662
  });
11663
- MetaHookBlockKindSchema = external_exports.enum(["memory-recall", "memory-classify"]);
11663
+ MetaHookBlockKindSchema = external_exports.enum(["memory-recall", "memory-classify", "model-router"]);
11664
11664
  GlobalConfigSchema = external_exports.object({
11665
11665
  schemaVersion: external_exports.literal(1),
11666
11666
  repos: external_exports.array(RepoEntrySchema).optional().default([]),
@@ -15417,7 +15417,7 @@ function isCloudflaredAvailable() {
15417
15417
  }
15418
15418
  }
15419
15419
  function startTunnel(port2) {
15420
- return new Promise((resolve30, reject) => {
15420
+ return new Promise((resolve31, reject) => {
15421
15421
  const child = spawn3("cloudflared", ["tunnel", "--url", `http://localhost:${port2}`], {
15422
15422
  stdio: ["ignore", "pipe", "pipe"],
15423
15423
  detached: false
@@ -15439,7 +15439,7 @@ function startTunnel(port2) {
15439
15439
  if (match2) {
15440
15440
  resolved = true;
15441
15441
  clearTimeout(timeout);
15442
- resolve30(match2[0]);
15442
+ resolve31(match2[0]);
15443
15443
  }
15444
15444
  }
15445
15445
  child.stdout?.on("data", scan);
@@ -15526,8 +15526,8 @@ var init_dashboard = __esm({
15526
15526
  }
15527
15527
  throw err;
15528
15528
  }
15529
- await new Promise((resolve30, reject) => {
15530
- this.server.on("listening", resolve30);
15529
+ await new Promise((resolve31, reject) => {
15530
+ this.server.on("listening", resolve31);
15531
15531
  this.server.on("error", reject);
15532
15532
  });
15533
15533
  this.info = { localUrl: `http://localhost:${port2}` };
@@ -15573,8 +15573,8 @@ var init_dashboard = __esm({
15573
15573
  async stop() {
15574
15574
  stopTunnel();
15575
15575
  if (this.server) {
15576
- await new Promise((resolve30) => {
15577
- this.server.close(() => resolve30());
15576
+ await new Promise((resolve31) => {
15577
+ this.server.close(() => resolve31());
15578
15578
  });
15579
15579
  this.server = null;
15580
15580
  }
@@ -15903,8 +15903,8 @@ async function findHostCpContainer() {
15903
15903
  const docker3 = new Dockerode2(resolveDockerHostOptions());
15904
15904
  let timer = null;
15905
15905
  const listing = docker3.listContainers({ all: true }).then((cs) => cs);
15906
- const timeout = new Promise((resolve30) => {
15907
- timer = setTimeout(() => resolve30(null), DOCKER_PROBE_TIMEOUT_MS);
15906
+ const timeout = new Promise((resolve31) => {
15907
+ timer = setTimeout(() => resolve31(null), DOCKER_PROBE_TIMEOUT_MS);
15908
15908
  });
15909
15909
  let containers;
15910
15910
  try {
@@ -16688,7 +16688,7 @@ async function ensureOlamPostgresSingleton(options = {}) {
16688
16688
  };
16689
16689
  }
16690
16690
  function sleep3(ms) {
16691
- return new Promise((resolve30) => setTimeout(resolve30, ms));
16691
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
16692
16692
  }
16693
16693
  var DEFAULT_POSTGRES_NETWORK, DEFAULT_POSTGRES_CONTAINER, DEFAULT_POSTGRES_HOST_PORT, DEFAULT_POSTGRES_IMAGE, DEFAULT_POSTGRES_USER, DEFAULT_POSTGRES_PASSWORD, DEFAULT_POSTGRES_DB, DEFAULT_POSTGRES_READY_TIMEOUT_MS;
16694
16694
  var init_postgres_init_helpers = __esm({
@@ -18399,17 +18399,143 @@ var init_memory_classify = __esm({
18399
18399
  }
18400
18400
  });
18401
18401
 
18402
+ // ../core/dist/meta-hooks/model-router.js
18403
+ import * as fs69 from "node:fs";
18404
+ function buildModelRouterHookEntry() {
18405
+ return {
18406
+ hooks: [
18407
+ {
18408
+ type: "command",
18409
+ command: `OLAM_META_SENTINEL=${OLAM_META_MODEL_ROUTER_SENTINEL}; ${OLAM_META_NOOP_GUARD3} python3 "${OLAM_META_MODEL_ROUTER_SCRIPT_PATH}"`,
18410
+ timeout: OLAM_META_MODEL_ROUTER_TIMEOUT_MS
18411
+ }
18412
+ ]
18413
+ };
18414
+ }
18415
+ function computeModelRouterUninstall(settings) {
18416
+ const matchers = settings.hooks?.UserPromptSubmit;
18417
+ if (!Array.isArray(matchers) || matchers.length === 0) {
18418
+ return { status: "not-found" };
18419
+ }
18420
+ let changed = false;
18421
+ const filteredMatchers = [];
18422
+ for (const matcher of matchers) {
18423
+ const innerHooks = matcher.hooks ?? [];
18424
+ const keptInner = innerHooks.filter((h) => {
18425
+ if (typeof h.command === "string" && h.command.includes(OLAM_META_MODEL_ROUTER_SENTINEL)) {
18426
+ changed = true;
18427
+ return false;
18428
+ }
18429
+ return true;
18430
+ });
18431
+ if (keptInner.length === 0 && innerHooks.length > 0) {
18432
+ changed = true;
18433
+ continue;
18434
+ }
18435
+ if (keptInner.length === innerHooks.length) {
18436
+ filteredMatchers.push(matcher);
18437
+ } else {
18438
+ filteredMatchers.push({ ...matcher, hooks: keptInner });
18439
+ }
18440
+ }
18441
+ if (!changed)
18442
+ return { status: "not-found" };
18443
+ const next = {
18444
+ ...settings,
18445
+ hooks: {
18446
+ ...settings.hooks,
18447
+ UserPromptSubmit: filteredMatchers
18448
+ }
18449
+ };
18450
+ if (filteredMatchers.length === 0) {
18451
+ const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "UserPromptSubmit");
18452
+ if (otherStages.length === 0) {
18453
+ delete next.hooks;
18454
+ } else {
18455
+ delete next.hooks.UserPromptSubmit;
18456
+ }
18457
+ }
18458
+ return { status: "removed", settingsAfter: next };
18459
+ }
18460
+ function matchModelRouterSentinel(commandLine) {
18461
+ return commandLine.includes(OLAM_META_MODEL_ROUTER_SENTINEL);
18462
+ }
18463
+ var OLAM_META_MODEL_ROUTER_SENTINEL, OLAM_META_MODEL_ROUTER_STAGE, OLAM_META_MODEL_ROUTER_TIMEOUT_MS, OLAM_META_MODEL_ROUTER_SCRIPT_PATH, OLAM_META_MODEL_ROUTER_SCRIPT_BASENAME, OLAM_META_NOOP_GUARD3;
18464
+ var init_model_router = __esm({
18465
+ "../core/dist/meta-hooks/model-router.js"() {
18466
+ "use strict";
18467
+ OLAM_META_MODEL_ROUTER_SENTINEL = "olam-meta-model-router-v1";
18468
+ OLAM_META_MODEL_ROUTER_STAGE = "UserPromptSubmit";
18469
+ OLAM_META_MODEL_ROUTER_TIMEOUT_MS = 5e3;
18470
+ OLAM_META_MODEL_ROUTER_SCRIPT_PATH = "$HOME/.claude/hooks/model-router.py";
18471
+ OLAM_META_MODEL_ROUTER_SCRIPT_BASENAME = "model-router.py";
18472
+ OLAM_META_NOOP_GUARD3 = "command -v olam >/dev/null 2>&1 || exit 0;";
18473
+ }
18474
+ });
18475
+
18476
+ // ../core/dist/meta-hooks/model-router-deploy.js
18477
+ import { existsSync as existsSync77, mkdirSync as mkdirSync45, readFileSync as readFileSync66, writeFileSync as writeFileSync41 } from "node:fs";
18478
+ import { homedir as homedir43 } from "node:os";
18479
+ import { dirname as dirname39, join as join75, resolve as resolve20 } from "node:path";
18480
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
18481
+ function resolveModelRouterSourcePath() {
18482
+ const here3 = dirname39(fileURLToPath8(import.meta.url));
18483
+ const candidates2 = [
18484
+ // (1) in-repo tsc dist: core/dist/meta-hooks → ../../../cli/hooks
18485
+ resolve20(here3, "..", "..", "..", "cli", "hooks", MODEL_ROUTER_SCRIPT_BASENAME),
18486
+ // (1b) in-repo src (tsx / vitest): core/src/meta-hooks → ../../../cli/hooks
18487
+ resolve20(here3, "..", "..", "..", "cli", "hooks", MODEL_ROUTER_SCRIPT_BASENAME),
18488
+ // (2) bundled CLI: dist/<bundle> → ../hooks (hooks is sibling of dist)
18489
+ resolve20(here3, "..", "hooks", MODEL_ROUTER_SCRIPT_BASENAME),
18490
+ resolve20(here3, "..", "..", "hooks", MODEL_ROUTER_SCRIPT_BASENAME)
18491
+ ];
18492
+ for (const candidate of candidates2) {
18493
+ if (existsSync77(candidate))
18494
+ return candidate;
18495
+ }
18496
+ return candidates2[0];
18497
+ }
18498
+ function deployModelRouterScript(opts = {}) {
18499
+ const targetDir = opts.targetDir ?? join75(homedir43(), ".claude", "hooks");
18500
+ const targetPath = join75(targetDir, MODEL_ROUTER_SCRIPT_BASENAME);
18501
+ const sourcePath = opts.sourcePath ?? resolveModelRouterSourcePath();
18502
+ if (!existsSync77(sourcePath)) {
18503
+ return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "source-missing", targetPath };
18504
+ }
18505
+ const newContent = readFileSync66(sourcePath, "utf8");
18506
+ if (existsSync77(targetPath)) {
18507
+ const existing = readFileSync66(targetPath, "utf8");
18508
+ if (existing === newContent) {
18509
+ return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "unchanged", targetPath };
18510
+ }
18511
+ }
18512
+ if (opts.dryRun !== true) {
18513
+ mkdirSync45(dirname39(targetPath), { recursive: true });
18514
+ writeFileSync41(targetPath, newContent, { mode: 493 });
18515
+ }
18516
+ return { basename: MODEL_ROUTER_SCRIPT_BASENAME, action: "written", targetPath };
18517
+ }
18518
+ var MODEL_ROUTER_SCRIPT_BASENAME;
18519
+ var init_model_router_deploy = __esm({
18520
+ "../core/dist/meta-hooks/model-router-deploy.js"() {
18521
+ "use strict";
18522
+ MODEL_ROUTER_SCRIPT_BASENAME = "model-router.py";
18523
+ }
18524
+ });
18525
+
18402
18526
  // ../core/dist/meta-hooks/index.js
18403
18527
  var init_meta_hooks = __esm({
18404
18528
  "../core/dist/meta-hooks/index.js"() {
18405
18529
  "use strict";
18406
18530
  init_memory_recall();
18407
18531
  init_memory_classify();
18532
+ init_model_router();
18533
+ init_model_router_deploy();
18408
18534
  }
18409
18535
  });
18410
18536
 
18411
18537
  // ../core/dist/skill-sync/settings-merger.js
18412
- import * as fs69 from "node:fs";
18538
+ import * as fs70 from "node:fs";
18413
18539
  import * as os39 from "node:os";
18414
18540
  import * as path68 from "node:path";
18415
18541
  function claudeSettingsPath() {
@@ -18478,28 +18604,28 @@ function tagOlam(entry) {
18478
18604
  return { ...entry, [OLAM_SKILLS_MARKER]: true };
18479
18605
  }
18480
18606
  function readJson(file) {
18481
- return JSON.parse(fs69.readFileSync(file, "utf-8"));
18607
+ return JSON.parse(fs70.readFileSync(file, "utf-8"));
18482
18608
  }
18483
18609
  function rotateBackups(backupDir) {
18484
- if (!fs69.existsSync(backupDir))
18610
+ if (!fs70.existsSync(backupDir))
18485
18611
  return;
18486
- const files = fs69.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path68.join(backupDir, f), mtime: fs69.statSync(path68.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
18612
+ const files = fs70.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path68.join(backupDir, f), mtime: fs70.statSync(path68.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
18487
18613
  for (const f of files.slice(BACKUP_RETENTION)) {
18488
18614
  try {
18489
- fs69.unlinkSync(f.full);
18615
+ fs70.unlinkSync(f.full);
18490
18616
  } catch {
18491
18617
  }
18492
18618
  }
18493
18619
  }
18494
18620
  function backupSettings() {
18495
18621
  const src = claudeSettingsPath();
18496
- if (!fs69.existsSync(src))
18622
+ if (!fs70.existsSync(src))
18497
18623
  return void 0;
18498
18624
  const dir = settingsBackupDir();
18499
- fs69.mkdirSync(dir, { recursive: true });
18625
+ fs70.mkdirSync(dir, { recursive: true });
18500
18626
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
18501
18627
  const dest = path68.join(dir, `settings-${stamp}.json`);
18502
- fs69.copyFileSync(src, dest);
18628
+ fs70.copyFileSync(src, dest);
18503
18629
  rotateBackups(dir);
18504
18630
  return dest;
18505
18631
  }
@@ -18507,7 +18633,7 @@ function mergeSettings(input2) {
18507
18633
  const settingsPath = claudeSettingsPath();
18508
18634
  const backupPath = backupSettings();
18509
18635
  let base = {};
18510
- if (fs69.existsSync(settingsPath)) {
18636
+ if (fs70.existsSync(settingsPath)) {
18511
18637
  try {
18512
18638
  base = readJson(settingsPath);
18513
18639
  } catch {
@@ -18575,10 +18701,10 @@ function mergeSettings(input2) {
18575
18701
  ...input2.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
18576
18702
  }
18577
18703
  };
18578
- fs69.mkdirSync(path68.dirname(settingsPath), { recursive: true });
18704
+ fs70.mkdirSync(path68.dirname(settingsPath), { recursive: true });
18579
18705
  const tmp = `${settingsPath}.tmp-${process.pid}`;
18580
- fs69.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
18581
- fs69.renameSync(tmp, settingsPath);
18706
+ fs70.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
18707
+ fs70.renameSync(tmp, settingsPath);
18582
18708
  return { backupPath, hooksAdded, permissionsCount: permSet.size, dualWriteDeduped, dualWriteDroppedCommands };
18583
18709
  }
18584
18710
  var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
@@ -18635,7 +18761,7 @@ var init_schema5 = __esm({
18635
18761
 
18636
18762
  // ../core/dist/skill-sync/per-project-override.js
18637
18763
  import { execFileSync as execFileSync16 } from "node:child_process";
18638
- import * as fs70 from "node:fs";
18764
+ import * as fs71 from "node:fs";
18639
18765
  import * as path69 from "node:path";
18640
18766
  import { parse as parseYaml6 } from "yaml";
18641
18767
  function findProjectOverride(startDir) {
@@ -18643,8 +18769,8 @@ function findProjectOverride(startDir) {
18643
18769
  const root = path69.parse(dir).root;
18644
18770
  while (true) {
18645
18771
  const candidate = path69.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
18646
- if (fs70.existsSync(candidate) && fs70.statSync(candidate).isFile()) {
18647
- const raw = fs70.readFileSync(candidate, "utf-8");
18772
+ if (fs71.existsSync(candidate) && fs71.statSync(candidate).isFile()) {
18773
+ const raw = fs71.readFileSync(candidate, "utf-8");
18648
18774
  let parsed;
18649
18775
  try {
18650
18776
  parsed = parseYaml6(raw);
@@ -18703,7 +18829,7 @@ var init_per_project_override = __esm({
18703
18829
  });
18704
18830
 
18705
18831
  // ../core/dist/lib/file-lock.js
18706
- import * as fs71 from "node:fs";
18832
+ import * as fs72 from "node:fs";
18707
18833
  import * as os40 from "node:os";
18708
18834
  import * as path70 from "node:path";
18709
18835
  function defaultIsPidAlive(pid) {
@@ -18716,11 +18842,11 @@ function defaultIsPidAlive(pid) {
18716
18842
  }
18717
18843
  }
18718
18844
  function sleep7(ms) {
18719
- return new Promise((resolve30) => setTimeout(resolve30, ms));
18845
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
18720
18846
  }
18721
18847
  function readLockMeta(lockPath) {
18722
18848
  try {
18723
- const raw = fs71.readFileSync(lockPath, "utf-8");
18849
+ const raw = fs72.readFileSync(lockPath, "utf-8");
18724
18850
  const parsed = JSON.parse(raw);
18725
18851
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
18726
18852
  return parsed;
@@ -18739,12 +18865,12 @@ function isLockStale(meta, opts) {
18739
18865
  }
18740
18866
  function tryAcquireOnce(lockPath, meta, opts) {
18741
18867
  try {
18742
- fs71.mkdirSync(path70.dirname(lockPath), { recursive: true });
18743
- const fd = fs71.openSync(lockPath, "wx", 384);
18868
+ fs72.mkdirSync(path70.dirname(lockPath), { recursive: true });
18869
+ const fd = fs72.openSync(lockPath, "wx", 384);
18744
18870
  try {
18745
- fs71.writeSync(fd, JSON.stringify(meta));
18871
+ fs72.writeSync(fd, JSON.stringify(meta));
18746
18872
  } finally {
18747
- fs71.closeSync(fd);
18873
+ fs72.closeSync(fd);
18748
18874
  }
18749
18875
  return true;
18750
18876
  } catch (err) {
@@ -18754,14 +18880,14 @@ function tryAcquireOnce(lockPath, meta, opts) {
18754
18880
  const existing = readLockMeta(lockPath);
18755
18881
  if (existing === void 0) {
18756
18882
  try {
18757
- fs71.unlinkSync(lockPath);
18883
+ fs72.unlinkSync(lockPath);
18758
18884
  } catch {
18759
18885
  }
18760
18886
  return tryAcquireOnce(lockPath, meta, opts);
18761
18887
  }
18762
18888
  if (isLockStale(existing, opts)) {
18763
18889
  try {
18764
- fs71.unlinkSync(lockPath);
18890
+ fs72.unlinkSync(lockPath);
18765
18891
  } catch {
18766
18892
  }
18767
18893
  return tryAcquireOnce(lockPath, meta, opts);
@@ -18791,7 +18917,7 @@ async function acquireFileLock(lockDir, options = {}) {
18791
18917
  lockPath,
18792
18918
  release: () => {
18793
18919
  try {
18794
- fs71.unlinkSync(lockPath);
18920
+ fs72.unlinkSync(lockPath);
18795
18921
  } catch {
18796
18922
  }
18797
18923
  }
@@ -18831,13 +18957,13 @@ var init_file_lock = __esm({
18831
18957
  });
18832
18958
 
18833
18959
  // ../core/dist/lib/min-version-filter.js
18834
- import { existsSync as existsSync78, readFileSync as readFileSync68 } from "node:fs";
18960
+ import { existsSync as existsSync80, readFileSync as readFileSync70 } from "node:fs";
18835
18961
  function readOlamMinVersion(filepath) {
18836
- if (!existsSync78(filepath))
18962
+ if (!existsSync80(filepath))
18837
18963
  return void 0;
18838
18964
  let text;
18839
18965
  try {
18840
- text = readFileSync68(filepath, "utf8");
18966
+ text = readFileSync70(filepath, "utf8");
18841
18967
  } catch {
18842
18968
  return void 0;
18843
18969
  }
@@ -18895,11 +19021,11 @@ var init_min_version_filter = __esm({
18895
19021
  });
18896
19022
 
18897
19023
  // ../core/dist/skill-sync/overlay-scan.js
18898
- import * as fs72 from "node:fs";
19024
+ import * as fs73 from "node:fs";
18899
19025
  import * as path71 from "node:path";
18900
19026
  function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
18901
19027
  const result = /* @__PURE__ */ new Map();
18902
- if (!fs72.existsSync(overlayRoot)) {
19028
+ if (!fs73.existsSync(overlayRoot)) {
18903
19029
  return result;
18904
19030
  }
18905
19031
  if (basenames.length === 0) {
@@ -18908,13 +19034,13 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
18908
19034
  const mdFiles = [];
18909
19035
  let overlayRootReal;
18910
19036
  try {
18911
- overlayRootReal = fs72.realpathSync(overlayRoot);
19037
+ overlayRootReal = fs73.realpathSync(overlayRoot);
18912
19038
  } catch {
18913
19039
  return result;
18914
19040
  }
18915
19041
  for (const subdir of OVERRIDE_SUBDIRS) {
18916
19042
  const dir = path71.join(overlayRoot, subdir);
18917
- if (!fs72.existsSync(dir))
19043
+ if (!fs73.existsSync(dir))
18918
19044
  continue;
18919
19045
  walkMarkdown(dir, mdFiles, caps.maxFiles);
18920
19046
  }
@@ -18922,7 +19048,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
18922
19048
  for (const filepath of mdFiles) {
18923
19049
  let realFile;
18924
19050
  try {
18925
- realFile = fs72.realpathSync(filepath);
19051
+ realFile = fs73.realpathSync(filepath);
18926
19052
  } catch (err) {
18927
19053
  const code = err.code;
18928
19054
  if (code === "ENOENT" || code === "EACCES")
@@ -18935,12 +19061,12 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
18935
19061
  }
18936
19062
  let content;
18937
19063
  try {
18938
- const stat = fs72.statSync(filepath);
19064
+ const stat = fs73.statSync(filepath);
18939
19065
  totalBytes += stat.size;
18940
19066
  if (totalBytes > caps.maxTotalBytes) {
18941
19067
  throw new Error(`[overlay-scan] aborted: overlay tree exceeds ${caps.maxTotalBytes} total bytes. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
18942
19068
  }
18943
- content = fs72.readFileSync(filepath, "utf8");
19069
+ content = fs73.readFileSync(filepath, "utf8");
18944
19070
  } catch (err) {
18945
19071
  const code = err.code;
18946
19072
  if (code === "ENOENT" || code === "EACCES") {
@@ -18962,7 +19088,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
18962
19088
  function walkMarkdown(dir, out, cap) {
18963
19089
  let entries;
18964
19090
  try {
18965
- entries = fs72.readdirSync(dir, { withFileTypes: true });
19091
+ entries = fs73.readdirSync(dir, { withFileTypes: true });
18966
19092
  } catch (err) {
18967
19093
  if (err.code === "ENOENT")
18968
19094
  return;
@@ -18997,7 +19123,7 @@ var init_overlay_scan = __esm({
18997
19123
  });
18998
19124
 
18999
19125
  // ../core/dist/skill-sync/settings-json-lock.js
19000
- import * as fs73 from "node:fs";
19126
+ import * as fs74 from "node:fs";
19001
19127
  import * as os41 from "node:os";
19002
19128
  import * as path72 from "node:path";
19003
19129
  function defaultSettingsJsonLockPath() {
@@ -19014,11 +19140,11 @@ function defaultIsPidAlive2(pid) {
19014
19140
  }
19015
19141
  }
19016
19142
  function sleep8(ms) {
19017
- return new Promise((resolve30) => setTimeout(resolve30, ms));
19143
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
19018
19144
  }
19019
19145
  function readLockMeta2(lockPath) {
19020
19146
  try {
19021
- const raw = fs73.readFileSync(lockPath, "utf-8");
19147
+ const raw = fs74.readFileSync(lockPath, "utf-8");
19022
19148
  const parsed = JSON.parse(raw);
19023
19149
  if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
19024
19150
  return parsed;
@@ -19041,12 +19167,12 @@ function isLockStale2(meta, opts) {
19041
19167
  function tryAcquireOnce2(lockPath, meta, opts) {
19042
19168
  for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
19043
19169
  try {
19044
- fs73.mkdirSync(path72.dirname(lockPath), { recursive: true });
19045
- const fd = fs73.openSync(lockPath, "wx", 384);
19170
+ fs74.mkdirSync(path72.dirname(lockPath), { recursive: true });
19171
+ const fd = fs74.openSync(lockPath, "wx", 384);
19046
19172
  try {
19047
- fs73.writeSync(fd, JSON.stringify(meta));
19173
+ fs74.writeSync(fd, JSON.stringify(meta));
19048
19174
  } finally {
19049
- fs73.closeSync(fd);
19175
+ fs74.closeSync(fd);
19050
19176
  }
19051
19177
  return true;
19052
19178
  } catch (err) {
@@ -19064,9 +19190,9 @@ function tryAcquireOnce2(lockPath, meta, opts) {
19064
19190
  }
19065
19191
  const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
19066
19192
  try {
19067
- fs73.renameSync(lockPath, victimPath);
19193
+ fs74.renameSync(lockPath, victimPath);
19068
19194
  try {
19069
- fs73.unlinkSync(victimPath);
19195
+ fs74.unlinkSync(victimPath);
19070
19196
  } catch {
19071
19197
  }
19072
19198
  } catch (err) {
@@ -19098,7 +19224,7 @@ async function acquireSettingsJsonLock(options = {}) {
19098
19224
  lockPath,
19099
19225
  release: () => {
19100
19226
  try {
19101
- fs73.unlinkSync(lockPath);
19227
+ fs74.unlinkSync(lockPath);
19102
19228
  } catch {
19103
19229
  }
19104
19230
  }
@@ -19201,7 +19327,7 @@ var init_services_status = __esm({
19201
19327
 
19202
19328
  // ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
19203
19329
  import * as crypto10 from "node:crypto";
19204
- import * as fs74 from "node:fs";
19330
+ import * as fs75 from "node:fs";
19205
19331
  import * as os42 from "node:os";
19206
19332
  import * as path73 from "node:path";
19207
19333
  function migrationSnapshotsDir2() {
@@ -19219,41 +19345,41 @@ function writeMetaHooksSnapshot(originalSettings) {
19219
19345
  };
19220
19346
  const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
19221
19347
  const dir = migrationSnapshotsDir2();
19222
- fs74.mkdirSync(dir, { recursive: true });
19348
+ fs75.mkdirSync(dir, { recursive: true });
19223
19349
  const stamp = validated.takenAt.replace(/[:.]/g, "-");
19224
19350
  const rand = crypto10.randomBytes(3).toString("hex");
19225
19351
  const file = path73.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
19226
- fs74.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
19352
+ fs75.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
19227
19353
  return file;
19228
19354
  }
19229
19355
  function readMetaHooksSnapshot(filePath) {
19230
- if (!fs74.existsSync(filePath)) {
19356
+ if (!fs75.existsSync(filePath)) {
19231
19357
  throw new Error(`snapshot file not found: ${filePath}`);
19232
19358
  }
19233
- const raw = fs74.readFileSync(filePath, "utf-8");
19359
+ const raw = fs75.readFileSync(filePath, "utf-8");
19234
19360
  const parsed = JSON.parse(raw);
19235
19361
  return MetaHooksMigrationSnapshotSchema.parse(parsed);
19236
19362
  }
19237
19363
  function findLatestMetaHooksSnapshot() {
19238
19364
  const dir = migrationSnapshotsDir2();
19239
- if (!fs74.existsSync(dir))
19365
+ if (!fs75.existsSync(dir))
19240
19366
  return void 0;
19241
- const candidates2 = fs74.readdirSync(dir).filter((n) => n.startsWith(META_HOOKS_SNAPSHOT_PREFIX) && n.endsWith(".json")).sort().reverse();
19367
+ const candidates2 = fs75.readdirSync(dir).filter((n) => n.startsWith(META_HOOKS_SNAPSHOT_PREFIX) && n.endsWith(".json")).sort().reverse();
19242
19368
  if (candidates2.length === 0)
19243
19369
  return void 0;
19244
19370
  return path73.join(dir, candidates2[0]);
19245
19371
  }
19246
19372
  function restoreSettingsFromSnapshot(snapshot, settingsPath) {
19247
19373
  if (snapshot.originalSettings === null) {
19248
- if (fs74.existsSync(settingsPath)) {
19249
- fs74.unlinkSync(settingsPath);
19374
+ if (fs75.existsSync(settingsPath)) {
19375
+ fs75.unlinkSync(settingsPath);
19250
19376
  }
19251
19377
  return;
19252
19378
  }
19253
- fs74.mkdirSync(path73.dirname(settingsPath), { recursive: true });
19379
+ fs75.mkdirSync(path73.dirname(settingsPath), { recursive: true });
19254
19380
  const tmp = `${settingsPath}.tmp-restore-${process.pid}-${Date.now()}`;
19255
- fs74.writeFileSync(tmp, JSON.stringify(snapshot.originalSettings, null, 2) + "\n");
19256
- fs74.renameSync(tmp, settingsPath);
19381
+ fs75.writeFileSync(tmp, JSON.stringify(snapshot.originalSettings, null, 2) + "\n");
19382
+ fs75.renameSync(tmp, settingsPath);
19257
19383
  }
19258
19384
  var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
19259
19385
  var init_meta_hooks_migration_snapshot = __esm({
@@ -19393,6 +19519,8 @@ function decideTargetBlocks(opts) {
19393
19519
  target.add("memory-recall");
19394
19520
  if (wantMemory && !disabled.has("memory-classify"))
19395
19521
  target.add("memory-classify");
19522
+ if (!disabled.has("model-router"))
19523
+ target.add("model-router");
19396
19524
  return target;
19397
19525
  }
19398
19526
  function injectMetaHooks(opts) {
@@ -19400,6 +19528,7 @@ function injectMetaHooks(opts) {
19400
19528
  let working = JSON.parse(JSON.stringify(opts.currentSettings ?? {}));
19401
19529
  const blocksAdded = [];
19402
19530
  const blocksRemoved = [];
19531
+ const blocksSkippedForeign = [];
19403
19532
  const memoryRecallPresent = hasMemoryRecallBlock(working);
19404
19533
  if (target.has("memory-recall")) {
19405
19534
  if (!memoryRecallPresent) {
@@ -19430,10 +19559,30 @@ function injectMetaHooks(opts) {
19430
19559
  }
19431
19560
  }
19432
19561
  }
19562
+ const modelRouterPresent = hasModelRouterBlock(working);
19563
+ if (target.has("model-router")) {
19564
+ if (!modelRouterPresent) {
19565
+ if (hasForeignModelRouterEntry(working)) {
19566
+ blocksSkippedForeign.push("model-router");
19567
+ } else {
19568
+ working = appendBlock(working, OLAM_META_MODEL_ROUTER_STAGE, buildModelRouterHookEntry());
19569
+ blocksAdded.push("model-router");
19570
+ }
19571
+ }
19572
+ } else {
19573
+ if (modelRouterPresent) {
19574
+ const r = computeModelRouterUninstall(working);
19575
+ if (r.status === "removed" && r.settingsAfter) {
19576
+ working = r.settingsAfter;
19577
+ blocksRemoved.push("model-router");
19578
+ }
19579
+ }
19580
+ }
19433
19581
  return {
19434
19582
  nextSettings: working,
19435
19583
  blocksAdded,
19436
19584
  blocksRemoved,
19585
+ blocksSkippedForeign,
19437
19586
  mode: opts.mode ?? "auto"
19438
19587
  };
19439
19588
  }
@@ -19467,6 +19616,40 @@ function hasMemoryClassifyBlock(settings) {
19467
19616
  }
19468
19617
  return false;
19469
19618
  }
19619
+ function hasModelRouterBlock(settings) {
19620
+ const entries = settings.hooks?.UserPromptSubmit;
19621
+ if (!Array.isArray(entries))
19622
+ return false;
19623
+ for (const matcher of entries) {
19624
+ const inner = matcher?.hooks ?? [];
19625
+ if (!Array.isArray(inner))
19626
+ continue;
19627
+ for (const h of inner) {
19628
+ if (typeof h?.command === "string" && matchModelRouterSentinel(h.command))
19629
+ return true;
19630
+ }
19631
+ }
19632
+ return false;
19633
+ }
19634
+ function hasForeignModelRouterEntry(settings) {
19635
+ const entries = settings.hooks?.UserPromptSubmit;
19636
+ if (!Array.isArray(entries))
19637
+ return false;
19638
+ for (const matcher of entries) {
19639
+ const inner = matcher?.hooks ?? [];
19640
+ if (!Array.isArray(inner))
19641
+ continue;
19642
+ for (const h of inner) {
19643
+ if (typeof h?.command !== "string")
19644
+ continue;
19645
+ if (matchModelRouterSentinel(h.command))
19646
+ continue;
19647
+ if (h.command.includes(OLAM_META_MODEL_ROUTER_SCRIPT_BASENAME))
19648
+ return true;
19649
+ }
19650
+ }
19651
+ return false;
19652
+ }
19470
19653
  function appendBlock(settings, stage, entry) {
19471
19654
  const next = { ...settings };
19472
19655
  const hooks = { ...settings.hooks ?? {} };
@@ -19485,7 +19668,7 @@ var init_meta_hook_injector = __esm({
19485
19668
 
19486
19669
  // ../core/dist/lib/markdown-merger.js
19487
19670
  import { createHash as createHash9 } from "node:crypto";
19488
- import { readFileSync as readFileSync72, existsSync as existsSync81, statSync as statSync23 } from "node:fs";
19671
+ import { readFileSync as readFileSync74, existsSync as existsSync83, statSync as statSync23 } from "node:fs";
19489
19672
  function parseFrontmatter3(text) {
19490
19673
  const match2 = FM_RE2.exec(text);
19491
19674
  if (match2 === null)
@@ -19614,9 +19797,9 @@ function mergeMarkdown(upstreamText, overlayText, labelForError, upstreamPath, o
19614
19797
  return { merged: fmBlock !== "" ? fmBlock + mergedBody : mergedBody };
19615
19798
  }
19616
19799
  function sha256OfPath(p) {
19617
- if (!existsSync81(p) || !statSync23(p).isFile())
19800
+ if (!existsSync83(p) || !statSync23(p).isFile())
19618
19801
  return "MISSING";
19619
- return createHash9("sha256").update(readFileSync72(p)).digest("hex");
19802
+ return createHash9("sha256").update(readFileSync74(p)).digest("hex");
19620
19803
  }
19621
19804
  var FM_RE2, H2_RE;
19622
19805
  var init_markdown_merger = __esm({
@@ -19628,7 +19811,7 @@ var init_markdown_merger = __esm({
19628
19811
  });
19629
19812
 
19630
19813
  // ../core/dist/skill-sync/managed-merge.js
19631
- import * as fs75 from "node:fs";
19814
+ import * as fs76 from "node:fs";
19632
19815
  import * as path74 from "node:path";
19633
19816
  function materializeMergedSkill(opts) {
19634
19817
  const { sourceId, sourcePath, deployBasename, mergedContent, claudeDir: claudeDir2 } = opts;
@@ -19638,12 +19821,12 @@ function materializeMergedSkill(opts) {
19638
19821
  if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path74.sep))) {
19639
19822
  throw new Error(`[managed-merge] refusing to materialize: deployBasename "${deployBasename}" escapes managed root "${sourceRoot}" (resolved to "${managedResolved}")`);
19640
19823
  }
19641
- fs75.mkdirSync(managedDir, { recursive: true });
19824
+ fs76.mkdirSync(managedDir, { recursive: true });
19642
19825
  const skillMdPath = path74.join(managedDir, "SKILL.md");
19643
19826
  const tmpPath = `${skillMdPath}.tmp-${process.pid}-${Date.now()}`;
19644
- fs75.writeFileSync(tmpPath, mergedContent);
19645
- fs75.renameSync(tmpPath, skillMdPath);
19646
- const baseEntries = fs75.readdirSync(sourcePath);
19827
+ fs76.writeFileSync(tmpPath, mergedContent);
19828
+ fs76.renameSync(tmpPath, skillMdPath);
19829
+ const baseEntries = fs76.readdirSync(sourcePath);
19647
19830
  for (const entry of baseEntries) {
19648
19831
  if (entry === "SKILL.md")
19649
19832
  continue;
@@ -19651,13 +19834,13 @@ function materializeMergedSkill(opts) {
19651
19834
  const targetAbsolute = path74.join(sourcePath, entry);
19652
19835
  const targetRelative = path74.relative(managedDir, targetAbsolute);
19653
19836
  try {
19654
- fs75.lstatSync(linkPath);
19655
- fs75.rmSync(linkPath, { recursive: true, force: true });
19837
+ fs76.lstatSync(linkPath);
19838
+ fs76.rmSync(linkPath, { recursive: true, force: true });
19656
19839
  } catch {
19657
19840
  }
19658
- fs75.symlinkSync(targetRelative, linkPath);
19841
+ fs76.symlinkSync(targetRelative, linkPath);
19659
19842
  }
19660
- const managedEntries = fs75.readdirSync(managedDir);
19843
+ const managedEntries = fs76.readdirSync(managedDir);
19661
19844
  const baseEntrySet = new Set(baseEntries);
19662
19845
  for (const entry of managedEntries) {
19663
19846
  if (entry === "SKILL.md")
@@ -19665,7 +19848,7 @@ function materializeMergedSkill(opts) {
19665
19848
  if (!baseEntrySet.has(entry)) {
19666
19849
  const stalePath = path74.join(managedDir, entry);
19667
19850
  try {
19668
- fs75.rmSync(stalePath, { recursive: true, force: true });
19851
+ fs76.rmSync(stalePath, { recursive: true, force: true });
19669
19852
  } catch {
19670
19853
  }
19671
19854
  }
@@ -19673,7 +19856,7 @@ function materializeMergedSkill(opts) {
19673
19856
  return managedDir;
19674
19857
  }
19675
19858
  function cleanMergedDir(claudeDir2) {
19676
- fs75.rmSync(path74.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
19859
+ fs76.rmSync(path74.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
19677
19860
  }
19678
19861
  var init_managed_merge = __esm({
19679
19862
  "../core/dist/skill-sync/managed-merge.js"() {
@@ -19812,7 +19995,7 @@ var init_prefix_rules = __esm({
19812
19995
  });
19813
19996
 
19814
19997
  // ../core/dist/skill-sync/prefix-deploy.js
19815
- import * as fs76 from "node:fs";
19998
+ import * as fs77 from "node:fs";
19816
19999
  import * as path75 from "node:path";
19817
20000
  function buildSourcePrefixMap(sources) {
19818
20001
  const byId = /* @__PURE__ */ new Map();
@@ -19868,7 +20051,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
19868
20051
  }
19869
20052
  if (artifact.kind === "skill") {
19870
20053
  const skillMdPath = path75.join(artifact.sourcePath, "SKILL.md");
19871
- const content = fs76.readFileSync(skillMdPath);
20054
+ const content = fs77.readFileSync(skillMdPath);
19872
20055
  const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
19873
20056
  const managedDir = materializeMergedSkill({
19874
20057
  sourceId: artifact.sourceId,
@@ -19880,7 +20063,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
19880
20063
  artifact.sourcePath = managedDir;
19881
20064
  artifact.deployBasename = renamed;
19882
20065
  } else {
19883
- const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs76.readFileSync(artifact.sourcePath);
20066
+ const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs77.readFileSync(artifact.sourcePath);
19884
20067
  const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
19885
20068
  artifact.resolvedContent = rewritten;
19886
20069
  artifact.deployBasename = renamed;
@@ -19925,19 +20108,19 @@ var init_prefix_deploy = __esm({
19925
20108
  });
19926
20109
 
19927
20110
  // ../core/dist/skill-sync/resolve-source-config.js
19928
- import { readFileSync as readFileSync74, existsSync as existsSync82 } from "node:fs";
19929
- import { join as join83 } from "node:path";
20111
+ import { readFileSync as readFileSync76, existsSync as existsSync84 } from "node:fs";
20112
+ import { join as join84 } from "node:path";
19930
20113
  import { parse as parseYaml7 } from "yaml";
19931
20114
  function sourceConfigPath(clonePath) {
19932
- return join83(clonePath, "shared", "source-config.yaml");
20115
+ return join84(clonePath, "shared", "source-config.yaml");
19933
20116
  }
19934
20117
  function readSourceConfig(clonePath, sourceId) {
19935
20118
  const path106 = sourceConfigPath(clonePath);
19936
- if (!existsSync82(path106))
20119
+ if (!existsSync84(path106))
19937
20120
  return void 0;
19938
20121
  let raw;
19939
20122
  try {
19940
- raw = readFileSync74(path106, "utf-8");
20123
+ raw = readFileSync76(path106, "utf-8");
19941
20124
  } catch (err) {
19942
20125
  emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
19943
20126
  return void 0;
@@ -20032,7 +20215,7 @@ var init_resolve_source_config = __esm({
20032
20215
  });
20033
20216
 
20034
20217
  // ../core/dist/skill-sync/engine.js
20035
- import * as fs77 from "node:fs";
20218
+ import * as fs78 from "node:fs";
20036
20219
  import * as os43 from "node:os";
20037
20220
  import * as path76 from "node:path";
20038
20221
  function resolveAtlasUser(override) {
@@ -20040,8 +20223,8 @@ function resolveAtlasUser(override) {
20040
20223
  return override;
20041
20224
  const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path76.join(os43.homedir(), ".claude");
20042
20225
  const f = path76.join(claudeDir2, ".atlas-user");
20043
- if (fs77.existsSync(f)) {
20044
- return fs77.readFileSync(f, "utf-8").trim() || void 0;
20226
+ if (fs78.existsSync(f)) {
20227
+ return fs78.readFileSync(f, "utf-8").trim() || void 0;
20045
20228
  }
20046
20229
  return void 0;
20047
20230
  }
@@ -20053,7 +20236,7 @@ async function syncSkills(opts = {}) {
20053
20236
  const perSource = [];
20054
20237
  for (const source of sources) {
20055
20238
  const clonePath = skillSourceClonePath(source.id);
20056
- if (!fs77.existsSync(clonePath))
20239
+ if (!fs78.existsSync(clonePath))
20057
20240
  continue;
20058
20241
  const { artifacts, subscription } = await withFileLock(clonePath, () => {
20059
20242
  const pinRef = projectOverride?.override.pin?.[source.id];
@@ -20093,7 +20276,7 @@ async function syncSkills(opts = {}) {
20093
20276
  const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
20094
20277
  const effectiveSources = sources.map((s) => {
20095
20278
  const clonePath = skillSourceClonePath(s.id);
20096
- const sourceConfig = fs77.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
20279
+ const sourceConfig = fs78.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
20097
20280
  const eff = resolveEffectivePrefix(s, sourceConfig);
20098
20281
  const entry = {
20099
20282
  id: s.id,
@@ -20200,12 +20383,12 @@ async function syncSkills(opts = {}) {
20200
20383
  let basePath;
20201
20384
  if (overlay.targetKind === "skill") {
20202
20385
  basePath = path76.join(base.sourcePath, "SKILL.md");
20203
- baseContent = fs77.readFileSync(basePath, "utf-8");
20386
+ baseContent = fs78.readFileSync(basePath, "utf-8");
20204
20387
  } else {
20205
20388
  basePath = base.sourcePath;
20206
- baseContent = fs77.readFileSync(basePath, "utf-8");
20389
+ baseContent = fs78.readFileSync(basePath, "utf-8");
20207
20390
  }
20208
- const overlayContent = fs77.readFileSync(overlay.sourcePath, "utf-8");
20391
+ const overlayContent = fs78.readFileSync(overlay.sourcePath, "utf-8");
20209
20392
  const label = `${overlay.sourceId}/${overlay.deployBasename}`;
20210
20393
  const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
20211
20394
  if ("error" in mergeResult) {
@@ -20287,24 +20470,34 @@ async function injectMetaHooksIntoSettings(opts) {
20287
20470
  ...memoryProbe.detail !== void 0 ? { memoryDetail: memoryProbe.detail } : {}
20288
20471
  };
20289
20472
  const settingsFile = claudeSettingsPath();
20473
+ let configDisabled = [];
20474
+ try {
20475
+ const cfg = readGlobalConfig();
20476
+ configDisabled = cfg.metaHooksDisabled ?? [];
20477
+ } catch {
20478
+ }
20479
+ const disabledBlocks = Array.from(/* @__PURE__ */ new Set([
20480
+ ...configDisabled,
20481
+ ...opts.metaHooksDisabled ?? []
20482
+ ]));
20290
20483
  let snapshotError;
20291
20484
  let stripCandidates = [];
20292
20485
  const result = await withSettingsJsonLock(() => {
20293
20486
  let currentSettings = {};
20294
20487
  let settingsExisted = false;
20295
- if (fs77.existsSync(settingsFile)) {
20488
+ if (fs78.existsSync(settingsFile)) {
20296
20489
  settingsExisted = true;
20297
20490
  try {
20298
- const raw = fs77.readFileSync(settingsFile, "utf-8");
20491
+ const raw = fs78.readFileSync(settingsFile, "utf-8");
20299
20492
  currentSettings = raw.trim() ? JSON.parse(raw) : {};
20300
20493
  } catch {
20301
20494
  try {
20302
- const raw = fs77.readFileSync(settingsFile);
20495
+ const raw = fs78.readFileSync(settingsFile);
20303
20496
  const bakDir = path76.join(path76.dirname(settingsFile), ".malformed-backups");
20304
- fs77.mkdirSync(bakDir, { recursive: true });
20497
+ fs78.mkdirSync(bakDir, { recursive: true });
20305
20498
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
20306
20499
  const bakFile = path76.join(bakDir, `settings.json.malformed.${stamp}.bak`);
20307
- fs77.writeFileSync(bakFile, raw, { mode: 384 });
20500
+ fs78.writeFileSync(bakFile, raw, { mode: 384 });
20308
20501
  snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
20309
20502
  } catch (bakErr) {
20310
20503
  snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
@@ -20315,16 +20508,6 @@ async function injectMetaHooksIntoSettings(opts) {
20315
20508
  }
20316
20509
  stripCandidates = findStripCandidates(currentSettings);
20317
20510
  const settingsForInject = stripCandidates.length > 0 ? applyStrip(currentSettings, stripCandidates).nextSettings : currentSettings;
20318
- let configDisabled = [];
20319
- try {
20320
- const cfg = readGlobalConfig();
20321
- configDisabled = cfg.metaHooksDisabled ?? [];
20322
- } catch {
20323
- }
20324
- const disabledBlocks = Array.from(/* @__PURE__ */ new Set([
20325
- ...configDisabled,
20326
- ...opts.metaHooksDisabled ?? []
20327
- ]));
20328
20511
  const inject = injectMetaHooks({
20329
20512
  servicesStatus: servicesStatus2,
20330
20513
  currentSettings: settingsForInject,
@@ -20354,17 +20537,34 @@ async function injectMetaHooksIntoSettings(opts) {
20354
20537
  } catch {
20355
20538
  }
20356
20539
  }
20357
- fs77.mkdirSync(path76.dirname(settingsFile), { recursive: true });
20540
+ fs78.mkdirSync(path76.dirname(settingsFile), { recursive: true });
20358
20541
  const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
20359
- fs77.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
20360
- fs77.renameSync(tmpPath, settingsFile);
20542
+ fs78.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
20543
+ fs78.renameSync(tmpPath, settingsFile);
20361
20544
  return inject;
20362
20545
  }, { reason: `syncSkills meta-hook injection (mode=${mode})` });
20546
+ let scriptDeploy;
20547
+ const modelRouterTargeted = mode !== "never" && !disabledBlocks.includes("model-router");
20548
+ if (modelRouterTargeted) {
20549
+ try {
20550
+ scriptDeploy = deployModelRouterScript({
20551
+ targetDir: path76.join(claudeDir(), "hooks")
20552
+ });
20553
+ } catch (err) {
20554
+ scriptDeploy = {
20555
+ basename: "model-router.py",
20556
+ action: "source-missing",
20557
+ targetPath: `${err instanceof Error ? err.message : String(err)}`
20558
+ };
20559
+ }
20560
+ }
20363
20561
  return {
20364
20562
  mode: result.mode,
20365
20563
  servicesStatus: servicesStatus2,
20366
20564
  blocksAdded: result.blocksAdded,
20367
20565
  blocksRemoved: result.blocksRemoved,
20566
+ ...result.blocksSkippedForeign.length > 0 ? { blocksSkippedForeign: result.blocksSkippedForeign } : {},
20567
+ ...scriptDeploy !== void 0 ? { scriptDeploy } : {},
20368
20568
  ...snapshotError !== void 0 ? { snapshotError } : {},
20369
20569
  ...stripCandidates.length > 0 ? { autoMigrated: { strippedCount: stripCandidates.length, stripCandidates } } : {}
20370
20570
  };
@@ -20389,6 +20589,7 @@ var init_engine = __esm({
20389
20589
  init_trust_audit_log();
20390
20590
  init_atlas_hook_strip();
20391
20591
  init_meta_hook_injector();
20592
+ init_model_router_deploy();
20392
20593
  init_markdown_merger();
20393
20594
  init_managed_merge();
20394
20595
  init_prefix_deploy();
@@ -20398,7 +20599,7 @@ var init_engine = __esm({
20398
20599
  });
20399
20600
 
20400
20601
  // ../core/dist/skill-sync/shadow-backup-manager.js
20401
- import * as fs78 from "node:fs";
20602
+ import * as fs79 from "node:fs";
20402
20603
  import * as path77 from "node:path";
20403
20604
  function listShadowBackups(opts = {}) {
20404
20605
  const claude = opts.claudeDirOverride ?? claudeDir();
@@ -20406,11 +20607,11 @@ function listShadowBackups(opts = {}) {
20406
20607
  const out = [];
20407
20608
  for (const bucket of SHADOW_BACKUP_BUCKETS) {
20408
20609
  const bucketDir = path77.join(claude, bucket);
20409
- if (!fs78.existsSync(bucketDir))
20610
+ if (!fs79.existsSync(bucketDir))
20410
20611
  continue;
20411
20612
  let entries;
20412
20613
  try {
20413
- entries = fs78.readdirSync(bucketDir);
20614
+ entries = fs79.readdirSync(bucketDir);
20414
20615
  } catch {
20415
20616
  continue;
20416
20617
  }
@@ -20424,7 +20625,7 @@ function listShadowBackups(opts = {}) {
20424
20625
  const full = path77.join(bucketDir, name);
20425
20626
  let sizeBytes = 0;
20426
20627
  try {
20427
- const st = fs78.statSync(full);
20628
+ const st = fs79.statSync(full);
20428
20629
  if (st.isDirectory())
20429
20630
  continue;
20430
20631
  sizeBytes = st.size;
@@ -20480,7 +20681,7 @@ function pruneShadowBackups(opts) {
20480
20681
  }
20481
20682
  if (!opts.dryRun) {
20482
20683
  try {
20483
- fs78.unlinkSync(b.path);
20684
+ fs79.unlinkSync(b.path);
20484
20685
  } catch {
20485
20686
  skipped.push(b);
20486
20687
  continue;
@@ -20492,7 +20693,7 @@ function pruneShadowBackups(opts) {
20492
20693
  }
20493
20694
  function restoreShadowBackup(opts) {
20494
20695
  const abs = path77.resolve(opts.backupPath);
20495
- if (!fs78.existsSync(abs)) {
20696
+ if (!fs79.existsSync(abs)) {
20496
20697
  throw new Error(`backup file not found: ${abs}`);
20497
20698
  }
20498
20699
  const basename17 = path77.basename(abs);
@@ -20502,13 +20703,13 @@ function restoreShadowBackup(opts) {
20502
20703
  }
20503
20704
  const originalBasename = basename17.slice(0, basename17.length - match2[0].length);
20504
20705
  const originalPath = path77.join(path77.dirname(abs), originalBasename);
20505
- if (fs78.existsSync(originalPath) && !opts.force) {
20706
+ if (fs79.existsSync(originalPath) && !opts.force) {
20506
20707
  throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
20507
20708
  }
20508
- if (opts.force && fs78.existsSync(originalPath)) {
20509
- fs78.unlinkSync(originalPath);
20709
+ if (opts.force && fs79.existsSync(originalPath)) {
20710
+ fs79.unlinkSync(originalPath);
20510
20711
  }
20511
- fs78.renameSync(abs, originalPath);
20712
+ fs79.renameSync(abs, originalPath);
20512
20713
  return { restoredTo: originalPath };
20513
20714
  }
20514
20715
  var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
@@ -20522,7 +20723,7 @@ var init_shadow_backup_manager = __esm({
20522
20723
  });
20523
20724
 
20524
20725
  // ../core/dist/global-config/repos.js
20525
- import * as fs79 from "node:fs";
20726
+ import * as fs80 from "node:fs";
20526
20727
  import * as os44 from "node:os";
20527
20728
  import * as path78 from "node:path";
20528
20729
  function expandPath(p) {
@@ -20540,7 +20741,7 @@ function addRepo(entry) {
20540
20741
  throw new Error(`repo "${entry.name}" already registered. Use "olam repos update" to change its path.`);
20541
20742
  }
20542
20743
  const resolvedPath = expandPath(entry.path);
20543
- if (!fs79.existsSync(resolvedPath)) {
20744
+ if (!fs80.existsSync(resolvedPath)) {
20544
20745
  throw new Error(`path "${entry.path}" does not exist. Verify the path is correct.`);
20545
20746
  }
20546
20747
  const now = Date.now();
@@ -20569,7 +20770,7 @@ function updateRepo(name, updates) {
20569
20770
  throw new Error(`repo "${name}" is not registered. Run "olam repos list" to see registered repos.`);
20570
20771
  }
20571
20772
  const resolvedUpdatePath = updates.path !== void 0 ? expandPath(updates.path) : void 0;
20572
- if (resolvedUpdatePath !== void 0 && !fs79.existsSync(resolvedUpdatePath)) {
20773
+ if (resolvedUpdatePath !== void 0 && !fs80.existsSync(resolvedUpdatePath)) {
20573
20774
  throw new Error(`path "${updates.path}" does not exist. Verify the path is correct.`);
20574
20775
  }
20575
20776
  const existing = config.repos[idx];
@@ -20638,7 +20839,7 @@ var init_global_config = __esm({
20638
20839
  });
20639
20840
 
20640
20841
  // ../core/dist/skill-sources/doctor-checks.js
20641
- import * as fs80 from "node:fs";
20842
+ import * as fs81 from "node:fs";
20642
20843
  import * as path79 from "node:path";
20643
20844
  import * as os45 from "node:os";
20644
20845
  function claudeDirInternal3() {
@@ -20654,11 +20855,11 @@ function checkStateFileParse() {
20654
20855
  healthy: true,
20655
20856
  description: `~/.olam state file (${filePath})`
20656
20857
  };
20657
- if (!fs80.existsSync(filePath)) {
20858
+ if (!fs81.existsSync(filePath)) {
20658
20859
  result.details = ["(file does not yet exist \u2014 will be created on first write)"];
20659
20860
  return result;
20660
20861
  }
20661
- const raw = fs80.readFileSync(filePath, "utf-8");
20862
+ const raw = fs81.readFileSync(filePath, "utf-8");
20662
20863
  let parsed;
20663
20864
  try {
20664
20865
  parsed = JSON.parse(raw);
@@ -20668,8 +20869,8 @@ function checkStateFileParse() {
20668
20869
  result.details = [err instanceof Error ? err.message : String(err)];
20669
20870
  result.repair = () => {
20670
20871
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
20671
- fs80.renameSync(filePath, aside);
20672
- fs80.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
20872
+ fs81.renameSync(filePath, aside);
20873
+ fs81.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
20673
20874
  };
20674
20875
  return result;
20675
20876
  }
@@ -20680,7 +20881,7 @@ function checkStateFileParse() {
20680
20881
  result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
20681
20882
  result.repair = () => {
20682
20883
  const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
20683
- fs80.copyFileSync(filePath, aside);
20884
+ fs81.copyFileSync(filePath, aside);
20684
20885
  const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
20685
20886
  const next = {
20686
20887
  ...base,
@@ -20689,7 +20890,7 @@ function checkStateFileParse() {
20689
20890
  runbooks: [],
20690
20891
  skillSources: []
20691
20892
  };
20692
- fs80.writeFileSync(filePath, JSON.stringify(next, null, 2));
20893
+ fs81.writeFileSync(filePath, JSON.stringify(next, null, 2));
20693
20894
  };
20694
20895
  return result;
20695
20896
  }
@@ -20701,15 +20902,15 @@ function checkDanglingSymlinks() {
20701
20902
  const dangling = [];
20702
20903
  for (const bucket of buckets) {
20703
20904
  const dir = path79.join(claude, bucket);
20704
- if (!fs80.existsSync(dir))
20905
+ if (!fs81.existsSync(dir))
20705
20906
  continue;
20706
- for (const name of fs80.readdirSync(dir)) {
20907
+ for (const name of fs81.readdirSync(dir)) {
20707
20908
  const linkPath = path79.join(dir, name);
20708
20909
  try {
20709
- const lst = fs80.lstatSync(linkPath);
20910
+ const lst = fs81.lstatSync(linkPath);
20710
20911
  if (!lst.isSymbolicLink())
20711
20912
  continue;
20712
- if (!fs80.existsSync(linkPath)) {
20913
+ if (!fs81.existsSync(linkPath)) {
20713
20914
  dangling.push(linkPath);
20714
20915
  }
20715
20916
  } catch {
@@ -20727,7 +20928,7 @@ function checkDanglingSymlinks() {
20727
20928
  result.repair = () => {
20728
20929
  for (const p of dangling) {
20729
20930
  try {
20730
- fs80.unlinkSync(p);
20931
+ fs81.unlinkSync(p);
20731
20932
  } catch {
20732
20933
  }
20733
20934
  }
@@ -20742,19 +20943,19 @@ function checkOrphanedSnapshots() {
20742
20943
  healthy: true,
20743
20944
  description: `orphaned migration snapshots under ${dir}`
20744
20945
  };
20745
- if (!fs80.existsSync(dir)) {
20946
+ if (!fs81.existsSync(dir)) {
20746
20947
  return result;
20747
20948
  }
20748
20949
  const orphans = [];
20749
- for (const name of fs80.readdirSync(dir)) {
20950
+ for (const name of fs81.readdirSync(dir)) {
20750
20951
  if (!name.endsWith(".json"))
20751
20952
  continue;
20752
20953
  const full = path79.join(dir, name);
20753
20954
  try {
20754
- const stat = fs80.statSync(full);
20955
+ const stat = fs81.statSync(full);
20755
20956
  if (!stat.isFile())
20756
20957
  continue;
20757
- const raw = fs80.readFileSync(full, "utf-8");
20958
+ const raw = fs81.readFileSync(full, "utf-8");
20758
20959
  let parsed;
20759
20960
  try {
20760
20961
  parsed = JSON.parse(raw);
@@ -20779,7 +20980,7 @@ function checkOrphanedSnapshots() {
20779
20980
  result.repair = () => {
20780
20981
  for (const o of orphans) {
20781
20982
  try {
20782
- fs80.unlinkSync(o.path);
20983
+ fs81.unlinkSync(o.path);
20783
20984
  } catch {
20784
20985
  }
20785
20986
  }
@@ -20794,12 +20995,12 @@ function checkSentinelDrift() {
20794
20995
  healthy: true,
20795
20996
  description: `olam-skills sentinel block in ${filePath}`
20796
20997
  };
20797
- if (!fs80.existsSync(filePath)) {
20998
+ if (!fs81.existsSync(filePath)) {
20798
20999
  return result;
20799
21000
  }
20800
21001
  let parsed;
20801
21002
  try {
20802
- parsed = JSON.parse(fs80.readFileSync(filePath, "utf-8"));
21003
+ parsed = JSON.parse(fs81.readFileSync(filePath, "utf-8"));
20803
21004
  } catch {
20804
21005
  return result;
20805
21006
  }
@@ -20840,7 +21041,7 @@ function checkSentinelDrift() {
20840
21041
  backupSettings();
20841
21042
  } catch {
20842
21043
  }
20843
- const next = JSON.parse(fs80.readFileSync(filePath, "utf-8"));
21044
+ const next = JSON.parse(fs81.readFileSync(filePath, "utf-8"));
20844
21045
  if (!next.hooks)
20845
21046
  return;
20846
21047
  for (const stage of Object.keys(next.hooks)) {
@@ -20863,7 +21064,7 @@ function checkSentinelDrift() {
20863
21064
  return bad === void 0;
20864
21065
  });
20865
21066
  }
20866
- fs80.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
21067
+ fs81.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
20867
21068
  };
20868
21069
  }
20869
21070
  return result;
@@ -20888,7 +21089,7 @@ function checkMemberNameMissing() {
20888
21089
  }
20889
21090
  const claudeDir2 = claudeDirInternal3();
20890
21091
  const atlasUserPath = path79.join(claudeDir2, ".atlas-user");
20891
- const value = fs80.existsSync(atlasUserPath) ? fs80.readFileSync(atlasUserPath, "utf-8").trim() : "";
21092
+ const value = fs81.existsSync(atlasUserPath) ? fs81.readFileSync(atlasUserPath, "utf-8").trim() : "";
20892
21093
  if (value.length > 0) {
20893
21094
  result.details = [`atlas-user: ${value}`];
20894
21095
  return result;
@@ -20897,9 +21098,9 @@ function checkMemberNameMissing() {
20897
21098
  result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
20898
21099
  const clonePath = skillSourceClonePath(atlasSource.id);
20899
21100
  const membersDir = path79.join(clonePath, "members");
20900
- const existing = fs80.existsSync(membersDir) ? fs80.readdirSync(membersDir).filter((e) => {
21101
+ const existing = fs81.existsSync(membersDir) ? fs81.readdirSync(membersDir).filter((e) => {
20901
21102
  try {
20902
- return fs80.statSync(path79.join(membersDir, e)).isDirectory();
21103
+ return fs81.statSync(path79.join(membersDir, e)).isDirectory();
20903
21104
  } catch {
20904
21105
  return false;
20905
21106
  }
@@ -20914,7 +21115,7 @@ function checkMemberNameMissing() {
20914
21115
  function checkMemberOverlayDrift() {
20915
21116
  const claudeDir2 = claudeDirInternal3();
20916
21117
  const atlasUserPath = path79.join(claudeDir2, ".atlas-user");
20917
- const atlasUser = fs80.existsSync(atlasUserPath) ? fs80.readFileSync(atlasUserPath, "utf-8").trim() : "";
21118
+ const atlasUser = fs81.existsSync(atlasUserPath) ? fs81.readFileSync(atlasUserPath, "utf-8").trim() : "";
20918
21119
  if (atlasUser.length === 0) {
20919
21120
  return [];
20920
21121
  }
@@ -20931,11 +21132,11 @@ function checkMemberOverlayDrift() {
20931
21132
  const results = [];
20932
21133
  for (const kind of ["skills", "agents"]) {
20933
21134
  const localRoot = path79.join(claudeDir2, `${kind}.overrides`);
20934
- if (!fs80.existsSync(localRoot))
21135
+ if (!fs81.existsSync(localRoot))
20935
21136
  continue;
20936
21137
  let entries;
20937
21138
  try {
20938
- entries = fs80.readdirSync(localRoot);
21139
+ entries = fs81.readdirSync(localRoot);
20939
21140
  } catch {
20940
21141
  continue;
20941
21142
  }
@@ -20943,7 +21144,7 @@ function checkMemberOverlayDrift() {
20943
21144
  const localFile = path79.join(localRoot, entry);
20944
21145
  let stat;
20945
21146
  try {
20946
- stat = fs80.statSync(localFile);
21147
+ stat = fs81.statSync(localFile);
20947
21148
  } catch {
20948
21149
  continue;
20949
21150
  }
@@ -21119,7 +21320,7 @@ __export(project_sweep_exports, {
21119
21320
  walkProjectRoot: () => walkProjectRoot
21120
21321
  });
21121
21322
  import * as path80 from "node:path";
21122
- import { readdirSync as readdirSync26, lstatSync as lstatSync6, statSync as statSync26, existsSync as existsSync87 } from "node:fs";
21323
+ import { readdirSync as readdirSync26, lstatSync as lstatSync6, statSync as statSync26, existsSync as existsSync89 } from "node:fs";
21123
21324
  function isSkipped(basename17, extra) {
21124
21325
  if (DEFAULT_SKIP.has(basename17))
21125
21326
  return true;
@@ -21198,7 +21399,7 @@ function makeRealFsAdapter() {
21198
21399
  const s = statSync26(p, { throwIfNoEntry: true });
21199
21400
  return { isDirectory: () => s.isDirectory(), mtimeMs: s.mtimeMs };
21200
21401
  },
21201
- existsSync: (p) => existsSync87(p)
21402
+ existsSync: (p) => existsSync89(p)
21202
21403
  };
21203
21404
  }
21204
21405
  function walkProjectRoot(rootPath, opts = {}) {
@@ -21224,7 +21425,7 @@ __export(kg_eager_exports, {
21224
21425
  runEagerKgBuild: () => runEagerKgBuild,
21225
21426
  writeQueue: () => writeQueue
21226
21427
  });
21227
- import * as fs81 from "node:fs";
21428
+ import * as fs82 from "node:fs";
21228
21429
  import * as path81 from "node:path";
21229
21430
  import * as os46 from "node:os";
21230
21431
  function defaultQueuePath() {
@@ -21232,9 +21433,9 @@ function defaultQueuePath() {
21232
21433
  return path81.join(stateDir, "kg-pending.jsonl");
21233
21434
  }
21234
21435
  function readQueue(queuePath) {
21235
- if (!fs81.existsSync(queuePath))
21436
+ if (!fs82.existsSync(queuePath))
21236
21437
  return [];
21237
- const raw = fs81.readFileSync(queuePath, "utf-8");
21438
+ const raw = fs82.readFileSync(queuePath, "utf-8");
21238
21439
  const entries = [];
21239
21440
  for (const line of raw.split("\n")) {
21240
21441
  const trimmed = line.trim();
@@ -21248,16 +21449,16 @@ function readQueue(queuePath) {
21248
21449
  return entries;
21249
21450
  }
21250
21451
  function writeQueue(queuePath, entries) {
21251
- fs81.mkdirSync(path81.dirname(queuePath), { recursive: true });
21452
+ fs82.mkdirSync(path81.dirname(queuePath), { recursive: true });
21252
21453
  const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
21253
- fs81.writeFileSync(queuePath, content, "utf-8");
21454
+ fs82.writeFileSync(queuePath, content, "utf-8");
21254
21455
  }
21255
21456
  function appendQueue(queuePath, repos, nowMs) {
21256
21457
  if (repos.length === 0)
21257
21458
  return;
21258
- fs81.mkdirSync(path81.dirname(queuePath), { recursive: true });
21459
+ fs82.mkdirSync(path81.dirname(queuePath), { recursive: true });
21259
21460
  const lines = repos.map((r) => JSON.stringify({ path: r.path, addedAt: nowMs })).join("\n") + "\n";
21260
- fs81.appendFileSync(queuePath, lines, "utf-8");
21461
+ fs82.appendFileSync(queuePath, lines, "utf-8");
21261
21462
  }
21262
21463
  async function defaultBuildOne(_repo) {
21263
21464
  return { ok: true, ms: 0 };
@@ -21397,27 +21598,27 @@ var init_install_shared = __esm({
21397
21598
  });
21398
21599
 
21399
21600
  // src/commands/memory/_paths.ts
21400
- import { homedir as homedir52 } from "node:os";
21401
- import { join as join92, dirname as dirname49 } from "node:path";
21402
- import { fileURLToPath as fileURLToPath8 } from "node:url";
21601
+ import { homedir as homedir53 } from "node:os";
21602
+ import { join as join93, dirname as dirname50 } from "node:path";
21603
+ import { fileURLToPath as fileURLToPath9 } from "node:url";
21403
21604
  var OLAM_HOME5, MEMORY_PID_PATH, MEMORY_LOG_PATH, MEMORY_DATA_DIR, MEMORY_REST_PORT, MEMORY_LIVEZ_URL, here, candidates, MEMORY_SERVICE_CANDIDATES;
21404
21605
  var init_paths2 = __esm({
21405
21606
  "src/commands/memory/_paths.ts"() {
21406
21607
  "use strict";
21407
- OLAM_HOME5 = join92(homedir52(), ".olam");
21408
- MEMORY_PID_PATH = join92(OLAM_HOME5, "memory.pid");
21409
- MEMORY_LOG_PATH = join92(OLAM_HOME5, "memory-service.log");
21410
- MEMORY_DATA_DIR = join92(OLAM_HOME5, "memory-data");
21608
+ OLAM_HOME5 = join93(homedir53(), ".olam");
21609
+ MEMORY_PID_PATH = join93(OLAM_HOME5, "memory.pid");
21610
+ MEMORY_LOG_PATH = join93(OLAM_HOME5, "memory-service.log");
21611
+ MEMORY_DATA_DIR = join93(OLAM_HOME5, "memory-data");
21411
21612
  MEMORY_REST_PORT = 3111;
21412
21613
  MEMORY_LIVEZ_URL = `http://localhost:${MEMORY_REST_PORT}/agentmemory/livez`;
21413
- here = dirname49(fileURLToPath8(import.meta.url));
21614
+ here = dirname50(fileURLToPath9(import.meta.url));
21414
21615
  candidates = [
21415
21616
  // 1. Workspace dev (built): packages/cli/dist/commands/memory/_paths.js → packages/cli → packages/memory-service
21416
- join92(here, "..", "..", "..", "..", "memory-service"),
21617
+ join93(here, "..", "..", "..", "..", "memory-service"),
21417
21618
  // 2. Workspace bundled: packages/cli/dist/index.js → packages/cli → packages/memory-service
21418
- join92(here, "..", "..", "memory-service"),
21619
+ join93(here, "..", "..", "memory-service"),
21419
21620
  // 3. CWD fallback
21420
- join92(process.cwd(), "packages", "memory-service")
21621
+ join93(process.cwd(), "packages", "memory-service")
21421
21622
  ];
21422
21623
  MEMORY_SERVICE_CANDIDATES = candidates;
21423
21624
  }
@@ -21526,16 +21727,16 @@ __export(machine_schema_exports, {
21526
21727
  readMachineConfig: () => readMachineConfig,
21527
21728
  writeMachineConfig: () => writeMachineConfig
21528
21729
  });
21529
- import * as fs85 from "node:fs";
21730
+ import * as fs86 from "node:fs";
21530
21731
  import * as path86 from "node:path";
21531
21732
  import * as os48 from "node:os";
21532
21733
  import { parse as parseYaml8, stringify as stringifyYaml6 } from "yaml";
21533
21734
  function readMachineConfig(configPath) {
21534
21735
  const p = configPath ?? DEFAULT_CONFIG_PATH;
21535
- if (!fs85.existsSync(p))
21736
+ if (!fs86.existsSync(p))
21536
21737
  return null;
21537
21738
  try {
21538
- const raw = fs85.readFileSync(p, "utf-8");
21739
+ const raw = fs86.readFileSync(p, "utf-8");
21539
21740
  const parsed = parseYaml8(raw);
21540
21741
  return MachineConfigSchema.parse(parsed);
21541
21742
  } catch {
@@ -21544,8 +21745,8 @@ function readMachineConfig(configPath) {
21544
21745
  }
21545
21746
  function writeMachineConfig(config, configPath) {
21546
21747
  const p = configPath ?? DEFAULT_CONFIG_PATH;
21547
- fs85.mkdirSync(path86.dirname(p), { recursive: true });
21548
- fs85.writeFileSync(p, stringifyYaml6({ ...config }), { mode: 420 });
21748
+ fs86.mkdirSync(path86.dirname(p), { recursive: true });
21749
+ fs86.writeFileSync(p, stringifyYaml6({ ...config }), { mode: 420 });
21549
21750
  }
21550
21751
  function initMachineConfig(opts = {}) {
21551
21752
  const configPath = opts.configPath ?? DEFAULT_CONFIG_PATH;
@@ -21671,7 +21872,7 @@ function registerWorkspace(program2) {
21671
21872
  process.exitCode = 1;
21672
21873
  }
21673
21874
  });
21674
- workspace.command("remove").description("Delete a workspace (does NOT touch worlds that already referenced it)").argument("<name>", "Workspace name").option("--force", "Skip confirmation", false).action((name, _opts) => {
21875
+ workspace.command("remove").description("Delete a workspace (does NOT touch worlds that already referenced it)").argument("<name>", "Workspace name").action((name) => {
21675
21876
  try {
21676
21877
  if (removeWorkspace(name)) {
21677
21878
  printSuccess(`Removed workspace "${name}"`);
@@ -22040,7 +22241,7 @@ function runGlobalInit(opts) {
22040
22241
  }
22041
22242
  }
22042
22243
  function registerInit(program2) {
22043
- program2.command("init").description("Initialize olam in the current project or globally").option("--path <path>", "Project root path", process.cwd()).option("--skip-pleri", "Skip Pleri setup (deprecated \u2014 PLERI is always optional)").option("--global", "Write only ~/.olam/config.json (global scope); skip per-repo .olam/config.yaml").option("--project", "Write .olam/config.yaml in the nearest git repo (per-repo scope; default when --global is absent)").option("--yes / -y", "Auto-affirm prompts (non-interactive)").action(async (opts) => {
22244
+ program2.command("init").description("Initialize olam in the current project or globally").option("--path <path>", "Project root path", process.cwd()).option("--skip-pleri", "No-op (deprecated \u2014 PLERI is always optional; accepted for backward compat but has no effect)").option("--global", "Write only ~/.olam/config.json (global scope); skip per-repo .olam/config.yaml").option("--project", "Write .olam/config.yaml in the nearest git repo (per-repo scope; default when --global is absent)").option("--yes / -y", "Auto-affirm prompts (non-interactive)").action(async (opts) => {
22044
22245
  if (opts.global) {
22045
22246
  try {
22046
22247
  const result = runGlobalInit({});
@@ -22594,7 +22795,7 @@ async function kubectlWrap(args, opts = {}) {
22594
22795
  const spawnImpl = opts.spawnImpl ?? spawn4;
22595
22796
  const stdout = [];
22596
22797
  const stderr = [];
22597
- return new Promise((resolve30) => {
22798
+ return new Promise((resolve31) => {
22598
22799
  let resolved = false;
22599
22800
  let killTimer = null;
22600
22801
  let sigkillTimer = null;
@@ -22609,7 +22810,7 @@ async function kubectlWrap(args, opts = {}) {
22609
22810
  clearTimeout(sigkillTimer);
22610
22811
  sigkillTimer = null;
22611
22812
  }
22612
- resolve30(r);
22813
+ resolve31(r);
22613
22814
  }
22614
22815
  let child;
22615
22816
  try {
@@ -22618,7 +22819,7 @@ async function kubectlWrap(args, opts = {}) {
22618
22819
  env: { ...process.env, ...opts.env ?? {} }
22619
22820
  });
22620
22821
  } catch (err) {
22621
- resolve30({
22822
+ resolve31({
22622
22823
  ok: false,
22623
22824
  stdout: "",
22624
22825
  stderr: err instanceof Error ? err.message : String(err),
@@ -23134,7 +23335,7 @@ function runLiveTask(label, cmd, args, opts) {
23134
23335
  const startMs = Date.now();
23135
23336
  const settle = opts.settle ?? "auto";
23136
23337
  const useSpinner = !opts.verbose && Boolean(process.stdout.isTTY);
23137
- return new Promise((resolve30) => {
23338
+ return new Promise((resolve31) => {
23138
23339
  const child = spawn5(cmd, [...args], {
23139
23340
  env: opts.env ?? process.env,
23140
23341
  stdio: ["ignore", "pipe", "pipe"]
@@ -23198,7 +23399,7 @@ function runLiveTask(label, cmd, args, opts) {
23198
23399
  );
23199
23400
  }
23200
23401
  }
23201
- resolve30({ ok, exitCode: code, durationMs, logPath });
23402
+ resolve31({ ok, exitCode: code, durationMs, logPath });
23202
23403
  };
23203
23404
  child.on("error", (err) => {
23204
23405
  chunks.push(`
@@ -24388,10 +24589,10 @@ async function confirm(message) {
24388
24589
  if (!process.stdin.isTTY) return true;
24389
24590
  const { createInterface: createInterface12 } = await import("node:readline");
24390
24591
  const rl = createInterface12({ input: process.stdin, output: process.stdout });
24391
- return new Promise((resolve30) => {
24592
+ return new Promise((resolve31) => {
24392
24593
  rl.question(`${message} [y/N] `, (answer) => {
24393
24594
  rl.close();
24394
- resolve30(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
24595
+ resolve31(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
24395
24596
  });
24396
24597
  });
24397
24598
  }
@@ -24863,7 +25064,7 @@ var KgServiceContainerController = class {
24863
25064
  }
24864
25065
  };
24865
25066
  function sleep4(ms) {
24866
- return new Promise((resolve30) => setTimeout(resolve30, ms));
25067
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
24867
25068
  }
24868
25069
 
24869
25070
  // src/commands/memory-service-container.ts
@@ -25086,7 +25287,7 @@ var MemoryServiceContainerController = class {
25086
25287
  }
25087
25288
  };
25088
25289
  function sleep5(ms) {
25089
- return new Promise((resolve30) => setTimeout(resolve30, ms));
25290
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
25090
25291
  }
25091
25292
 
25092
25293
  // src/lib/peripheral-registry.ts
@@ -25681,7 +25882,7 @@ var McpAuthContainerController = class {
25681
25882
  }
25682
25883
  };
25683
25884
  function sleep6(ms) {
25684
- return new Promise((resolve30) => setTimeout(resolve30, ms));
25885
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
25685
25886
  }
25686
25887
  var K8S_NAMESPACE2 = "olam";
25687
25888
  function assertK8sContext(configPath) {
@@ -26287,14 +26488,14 @@ async function probePortForwardLiveness(deps = {}) {
26287
26488
  return probe2("127.0.0.1", PORT_FORWARD_PORT, TCP_PROBE_TIMEOUT_MS);
26288
26489
  }
26289
26490
  function realTcpProbe(host, port2, timeoutMs) {
26290
- return new Promise((resolve30) => {
26491
+ return new Promise((resolve31) => {
26291
26492
  const socket = new net3.Socket();
26292
26493
  let done = false;
26293
26494
  function finish(result) {
26294
26495
  if (done) return;
26295
26496
  done = true;
26296
26497
  socket.destroy();
26297
- resolve30(result);
26498
+ resolve31(result);
26298
26499
  }
26299
26500
  const timer = setTimeout(() => finish(false), timeoutMs);
26300
26501
  socket.once("connect", () => {
@@ -26632,12 +26833,12 @@ function appendAuditEntry(entry, auditLogPath, writeFileSyncImpl) {
26632
26833
  async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, peripheral) {
26633
26834
  const auditLogPath = deps.auditLogPath ?? MANIFEST_REFRESH_AUDIT_LOG;
26634
26835
  const readdirSync34 = deps.readdirSync ?? fs35.readdirSync;
26635
- const readFileSync108 = deps.readFileSync ?? fs35.readFileSync;
26836
+ const readFileSync110 = deps.readFileSync ?? fs35.readFileSync;
26636
26837
  const writeFileSyncImpl = deps.writeFileSync ?? fs35.writeFileSync;
26637
- const existsSync120 = deps.existsSync ?? fs35.existsSync;
26838
+ const existsSync122 = deps.existsSync ?? fs35.existsSync;
26638
26839
  const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
26639
26840
  const targetDir = peripheral ? path36.join(manifestsDir, peripheral) : manifestsDir;
26640
- if (!existsSync120(targetDir)) {
26841
+ if (!existsSync122(targetDir)) {
26641
26842
  return {
26642
26843
  ok: false,
26643
26844
  message: peripheral ? `peripheral manifests directory not found: ${targetDir}` : `manifests directory not found: ${targetDir}`
@@ -26658,7 +26859,7 @@ async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, per
26658
26859
  const filePath = path36.join(targetDir, file);
26659
26860
  let content;
26660
26861
  try {
26661
- content = readFileSync108(filePath, "utf8");
26862
+ content = readFileSync110(filePath, "utf8");
26662
26863
  } catch {
26663
26864
  continue;
26664
26865
  }
@@ -26914,11 +27115,11 @@ async function checkSecretPreCondition(context, deps) {
26914
27115
  }
26915
27116
  async function applyConfigMapSubstitution(context, manifestsDir, deps) {
26916
27117
  const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
26917
- const readFileSync108 = deps.readFileSyncImpl ?? fs36.readFileSync;
27118
+ const readFileSync110 = deps.readFileSyncImpl ?? fs36.readFileSync;
26918
27119
  const configMapPath = path37.join(manifestsDir, "30-configmap.yaml");
26919
27120
  let rawYaml;
26920
27121
  try {
26921
- rawYaml = readFileSync108(configMapPath, "utf8");
27122
+ rawYaml = readFileSync110(configMapPath, "utf8");
26922
27123
  } catch (err) {
26923
27124
  return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
26924
27125
  }
@@ -28193,10 +28394,10 @@ function emptyMigrationState() {
28193
28394
  return { version: 1, migrated: {} };
28194
28395
  }
28195
28396
  function readMigrationState(statePath, deps) {
28196
- const existsSync120 = deps.existsSync ?? fs40.existsSync;
28197
- const readFileSync108 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
28198
- if (!existsSync120(statePath)) return emptyMigrationState();
28199
- const raw = readFileSync108(statePath);
28397
+ const existsSync122 = deps.existsSync ?? fs40.existsSync;
28398
+ const readFileSync110 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
28399
+ if (!existsSync122(statePath)) return emptyMigrationState();
28400
+ const raw = readFileSync110(statePath);
28200
28401
  let parsed;
28201
28402
  try {
28202
28403
  parsed = JSON.parse(raw);
@@ -28213,17 +28414,17 @@ function readMigrationState(statePath, deps) {
28213
28414
  return parsed;
28214
28415
  }
28215
28416
  function writeMigrationStateAtomic(statePath, state, deps) {
28216
- const writeFileSync65 = deps.writeFileSync ?? ((p, d) => fs40.writeFileSync(p, d, "utf-8"));
28417
+ const writeFileSync67 = deps.writeFileSync ?? ((p, d) => fs40.writeFileSync(p, d, "utf-8"));
28217
28418
  const renameSync21 = deps.renameSync ?? fs40.renameSync;
28218
28419
  const tmpPath = `${statePath}.tmp`;
28219
- writeFileSync65(tmpPath, JSON.stringify(state, null, 2) + "\n");
28420
+ writeFileSync67(tmpPath, JSON.stringify(state, null, 2) + "\n");
28220
28421
  renameSync21(tmpPath, statePath);
28221
28422
  }
28222
28423
  function readLocalAccounts(accountsPath, deps) {
28223
- const existsSync120 = deps.existsSync ?? fs40.existsSync;
28224
- const readFileSync108 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
28225
- if (!existsSync120(accountsPath)) return null;
28226
- const raw = readFileSync108(accountsPath);
28424
+ const existsSync122 = deps.existsSync ?? fs40.existsSync;
28425
+ const readFileSync110 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
28426
+ if (!existsSync122(accountsPath)) return null;
28427
+ const raw = readFileSync110(accountsPath);
28227
28428
  let parsed;
28228
28429
  try {
28229
28430
  parsed = JSON.parse(raw);
@@ -29108,18 +29309,31 @@ ${pc13.dim("Tip: set ANTHROPIC_BASE_URL=" + baseUrl.replace(/\/+$/, "") + "/v1/p
29108
29309
  auth.command("revoke-anthropic-token").description("Revoke an Anthropic proxy token on the remote auth-worker (g4)").requiredOption("--remote <url>", "Auth-worker base URL").requiredOption("--token-hash <hash>", "Token hash to revoke (from issue or list output)").action(async (opts) => {
29109
29310
  const baseUrl = opts.remote;
29110
29311
  printHeader("Auth worker \u2014 revoke Anthropic proxy token");
29111
- console.log(`
29312
+ const serviceToken = resolveCfAccessServiceToken();
29313
+ let remoteOpts;
29314
+ if (serviceToken) {
29315
+ console.log(`
29316
+ ${pc13.dim("Using CF Access service token (machine-to-machine; no cookie needed).")}`);
29317
+ remoteOpts = {
29318
+ baseUrl,
29319
+ cfAccessClientId: serviceToken.clientId,
29320
+ cfAccessClientSecret: serviceToken.clientSecret
29321
+ };
29322
+ } else {
29323
+ console.log(`
29112
29324
  Open ${pc13.cyan(baseUrl.replace(/\/+$/, "") + "/v1/oauth/start")} in a browser to authenticate via CF Access SSO.`);
29113
- console.log(` Once you've completed SSO, paste your CF_Authorization cookie below.
29325
+ console.log(` Once you've completed SSO, paste your CF_Authorization cookie below.
29114
29326
  `);
29115
- const rawCookie = await promptLine(` ${pc13.dim("CF_Authorization cookie:")} `);
29116
- if (!rawCookie) {
29117
- printError("No cookie provided. Aborting.");
29118
- process.exitCode = 1;
29119
- return;
29327
+ const rawCookie = await promptLine(` ${pc13.dim("CF_Authorization cookie:")} `);
29328
+ if (!rawCookie) {
29329
+ printError("No cookie provided. Aborting.");
29330
+ process.exitCode = 1;
29331
+ return;
29332
+ }
29333
+ remoteOpts = { baseUrl, cfAuthCookie: rawCookie };
29120
29334
  }
29121
29335
  try {
29122
- const revoked = await remoteRevokeAnthropicToken({ baseUrl, cfAuthCookie: rawCookie }, opts.tokenHash);
29336
+ const revoked = await remoteRevokeAnthropicToken(remoteOpts, opts.tokenHash);
29123
29337
  if (revoked) {
29124
29338
  printSuccess(`Token ${opts.tokenHash} revoked.`);
29125
29339
  } else {
@@ -31411,6 +31625,7 @@ Top-level commands (run \`olam <command> --help\` for flags and subcommands):
31411
31625
  - \`olam enter\` \u2014 Open terminal to a world
31412
31626
  - \`olam evict\` \u2014 Evict oldest snapshots until total size \u2264 cap (default 5GB; override via OLAM_SNAPSHOT_MAX_BYTES)
31413
31627
  - \`olam get\` \u2014 Print the active substrate
31628
+ - \`olam graph\` \u2014 Query the cross-repo graph: locate a symbol, its relationships, or browse a repo (POST /v1/graph)
31414
31629
  - \`olam hermes\` \u2014 Hermes integration commands
31415
31630
  - \`olam host-cp\` \u2014 Manage the Olam host control plane container
31416
31631
  - \`olam implode\` \u2014 Destroy ALL local olam install and configs (dry-run by default)
@@ -31418,6 +31633,7 @@ Top-level commands (run \`olam <command> --help\` for flags and subcommands):
31418
31633
  - \`olam inspect\` \u2014 Diagnose warm-create cache hits/misses for a workspace (read-only; mutates nothing)
31419
31634
  - \`olam install\` \u2014 Pick an archetype preset for this Olam install
31420
31635
  - \`olam install-hook\` \u2014 Install kg-service hook (idempotent). --for hermes targets ~/.hermes/; default targets .claude/settings.json
31636
+ - \`olam install-model-router\` \u2014 Deploy the model-router.py UserPromptSubmit hook script to ~/.claude/hooks/ (idempotent; auto-run by
31421
31637
  - \`olam issue-anthropic-token\` \u2014 Mint a new Anthropic proxy token via the remote auth-worker (g4)
31422
31638
  - \`olam keys\` \u2014 Manage LLM API keys stored at ~/.olam/keys.yaml
31423
31639
  - \`olam kg\` \u2014 Knowledge-graph operations (kg-service container)
@@ -31472,7 +31688,7 @@ Top-level commands (run \`olam <command> --help\` for flags and subcommands):
31472
31688
  - \`olam substrate\` \u2014 Manage deployment substrate (beta)
31473
31689
  - \`olam sync\` \u2014 Sync registered skill sources to ~/.claude/
31474
31690
  - \`olam tls-install\` \u2014 Provision a locally-trusted TLS cert (mkcert) for the Traefik IngressRoute
31475
- - \`olam uninstall\` \u2014 Remove /10x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)
31691
+ - \`olam uninstall\` \u2014 Remove /100x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)
31476
31692
  - \`olam uninstall-hook\` \u2014 Remove kg-service PreToolUse hook from .claude/settings.json (sentinel-matched; surgical)
31477
31693
  - \`olam unset-prefix\` \u2014 Remove the deploy prefix from a registered skill source (reverts to canonical deploy names)
31478
31694
  - \`olam unset-prefix-scope\` \u2014 Remove the prefix-scope override from a registered skill source (reverts to default: both skill and agent are renamed)
@@ -31678,12 +31894,12 @@ async function runRepl(deps = {}) {
31678
31894
  closed = true;
31679
31895
  onClose?.();
31680
31896
  });
31681
- const ask = () => new Promise((resolve30) => {
31682
- if (closed) return resolve30(null);
31683
- onClose = () => resolve30(null);
31897
+ const ask = () => new Promise((resolve31) => {
31898
+ if (closed) return resolve31(null);
31899
+ onClose = () => resolve31(null);
31684
31900
  rl.question(pc14.cyan("olam ask> "), (line) => {
31685
31901
  onClose = null;
31686
- resolve30(line);
31902
+ resolve31(line);
31687
31903
  });
31688
31904
  });
31689
31905
  try {
@@ -32221,15 +32437,15 @@ var AGENTMEMORY_LOCAL_URL = "http://host.docker.internal:3111";
32221
32437
  var HOST_CP_URL = "http://127.0.0.1:19000";
32222
32438
  async function readHostCpTokenForCreate() {
32223
32439
  try {
32224
- const { default: fs107 } = await import("node:fs");
32440
+ const { default: fs108 } = await import("node:fs");
32225
32441
  const { default: os60 } = await import("node:os");
32226
32442
  const { default: path106 } = await import("node:path");
32227
32443
  const tp = path106.join(
32228
32444
  process.env.OLAM_HOME ?? path106.join(os60.homedir(), ".olam"),
32229
32445
  "host-cp.token"
32230
32446
  );
32231
- if (!fs107.existsSync(tp)) return null;
32232
- return fs107.readFileSync(tp, "utf-8").trim();
32447
+ if (!fs108.existsSync(tp)) return null;
32448
+ return fs108.readFileSync(tp, "utf-8").trim();
32233
32449
  } catch {
32234
32450
  return null;
32235
32451
  }
@@ -32241,7 +32457,7 @@ function registerCreate(program2) {
32241
32457
  ).option("--devbox-image <ref>", "Override the default devbox image (full registry/name:tag or @sha256: ref)").option("--allow-custom-registry", "Allow --devbox-image refs outside ghcr.io/pleri/* (logs a warning)").option("--runbook <name>", "Named runbook profile from ~/.olam/config.json").option(
32242
32458
  "--claude-home <id-or-path>",
32243
32459
  "Use a per-world Claude Code HOME (multi-account isolation; see docs/decisions/045-claude-home-override.md)"
32244
- ).action(async (opts) => {
32460
+ ).option("--json", "Emit machine-readable JSON on success (suppresses interactive hints)").action(async (opts) => {
32245
32461
  const { resolveDevboxImageOverride: resolveDevboxImageOverride2, decideAllowlist: decideAllowlist2 } = await Promise.resolve().then(() => (init_registry_allowlist(), registry_allowlist_exports));
32246
32462
  const overrideRef = resolveDevboxImageOverride2(opts.devboxImage);
32247
32463
  if (overrideRef) {
@@ -32729,12 +32945,12 @@ function defaultNameFromPrompt(prompt) {
32729
32945
  }
32730
32946
  async function readHostCpToken3() {
32731
32947
  try {
32732
- const { default: fs107 } = await import("node:fs");
32948
+ const { default: fs108 } = await import("node:fs");
32733
32949
  const { default: os60 } = await import("node:os");
32734
32950
  const { default: path106 } = await import("node:path");
32735
32951
  const tp = path106.join(os60.homedir(), ".olam", "host-cp.token");
32736
- if (!fs107.existsSync(tp)) return null;
32737
- const raw = fs107.readFileSync(tp, "utf-8").trim();
32952
+ if (!fs108.existsSync(tp)) return null;
32953
+ const raw = fs108.readFileSync(tp, "utf-8").trim();
32738
32954
  return raw.length > 0 ? raw : null;
32739
32955
  } catch {
32740
32956
  return null;
@@ -33108,7 +33324,7 @@ function parseRuntimeStatus(raw) {
33108
33324
  last_event_age_seconds
33109
33325
  };
33110
33326
  }
33111
- var fetchWorldRuntimeStatus = (worldId, token) => new Promise((resolve30) => {
33327
+ var fetchWorldRuntimeStatus = (worldId, token) => new Promise((resolve31) => {
33112
33328
  const opts = {
33113
33329
  host: "127.0.0.1",
33114
33330
  port: HOST_CP_PORT2,
@@ -33120,7 +33336,7 @@ var fetchWorldRuntimeStatus = (worldId, token) => new Promise((resolve30) => {
33120
33336
  const req = http3.request(opts, (res) => {
33121
33337
  if (res.statusCode !== 200) {
33122
33338
  res.resume();
33123
- return resolve30(null);
33339
+ return resolve31(null);
33124
33340
  }
33125
33341
  let body = "";
33126
33342
  res.setEncoding("utf-8");
@@ -33130,17 +33346,17 @@ var fetchWorldRuntimeStatus = (worldId, token) => new Promise((resolve30) => {
33130
33346
  res.on("end", () => {
33131
33347
  try {
33132
33348
  const parsed = parseRuntimeStatus(JSON.parse(body));
33133
- resolve30(parsed);
33349
+ resolve31(parsed);
33134
33350
  } catch {
33135
- resolve30(null);
33351
+ resolve31(null);
33136
33352
  }
33137
33353
  });
33138
- res.on("error", () => resolve30(null));
33354
+ res.on("error", () => resolve31(null));
33139
33355
  });
33140
- req.on("error", () => resolve30(null));
33356
+ req.on("error", () => resolve31(null));
33141
33357
  req.on("timeout", () => {
33142
33358
  req.destroy();
33143
- resolve30(null);
33359
+ resolve31(null);
33144
33360
  });
33145
33361
  req.end();
33146
33362
  });
@@ -33196,7 +33412,7 @@ async function getMachineStatus(_probe, _loadCtx, _readToken) {
33196
33412
  };
33197
33413
  }
33198
33414
  function registerStatus(program2) {
33199
- program2.command("status").description("Show machine status, or world details when a world ID is given").argument("[world]", "World ID \u2014 omit to show machine status").option("--json", "Output as JSON").option("--pretty", "Render world status as a human-readable table (engine-aware view)").action(async (worldId, opts) => {
33415
+ program2.command("status").description("Show machine status, or world details when a world ID is given").argument("[world]", "World ID \u2014 omit to show machine status").option("--json", "Output as JSON").action(async (worldId, opts) => {
33200
33416
  if (!worldId) {
33201
33417
  const ms = await getMachineStatus();
33202
33418
  if (opts.json) {
@@ -33330,12 +33546,12 @@ async function readlineConfirm(world) {
33330
33546
 
33331
33547
  `
33332
33548
  );
33333
- return new Promise((resolve30) => {
33549
+ return new Promise((resolve31) => {
33334
33550
  rl.question(
33335
33551
  `Destroy ${pc20.bold(world.name)}? This cannot be undone. [y/N] `,
33336
33552
  (answer) => {
33337
33553
  rl.close();
33338
- resolve30(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
33554
+ resolve31(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
33339
33555
  }
33340
33556
  );
33341
33557
  });
@@ -33690,14 +33906,14 @@ function printTable(entries) {
33690
33906
  async function confirmInteractive() {
33691
33907
  process.stdout.write(" Type `yes` to proceed: ");
33692
33908
  const buf = [];
33693
- return new Promise((resolve30) => {
33909
+ return new Promise((resolve31) => {
33694
33910
  const onData = (chunk) => {
33695
33911
  buf.push(chunk);
33696
33912
  if (Buffer.concat(buf).toString("utf-8").includes("\n")) {
33697
33913
  process.stdin.removeListener("data", onData);
33698
33914
  process.stdin.pause();
33699
33915
  const answer = Buffer.concat(buf).toString("utf-8").trim();
33700
- resolve30(answer.toLowerCase() === "yes");
33916
+ resolve31(answer.toLowerCase() === "yes");
33701
33917
  }
33702
33918
  };
33703
33919
  process.stdin.resume();
@@ -39893,10 +40109,10 @@ async function confirm2(message) {
39893
40109
  if (!process.stdin.isTTY) return true;
39894
40110
  const { createInterface: createInterface12 } = await import("node:readline");
39895
40111
  const rl = createInterface12({ input: process.stdin, output: process.stdout });
39896
- return new Promise((resolve30) => {
40112
+ return new Promise((resolve31) => {
39897
40113
  rl.question(`${message} [y/N] `, (answer) => {
39898
40114
  rl.close();
39899
- resolve30(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
40115
+ resolve31(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
39900
40116
  });
39901
40117
  });
39902
40118
  }
@@ -41140,7 +41356,15 @@ function registerPs(program2) {
41140
41356
  process.exitCode = 1;
41141
41357
  return;
41142
41358
  }
41143
- const sortKey = ["cpu", "mem", "pid"].includes(opts.sort) ? opts.sort : "cpu";
41359
+ const VALID_SORT_KEYS = ["cpu", "mem", "pid"];
41360
+ if (!VALID_SORT_KEYS.includes(opts.sort)) {
41361
+ printError(
41362
+ `Invalid --sort key "${opts.sort}". Valid values: ${VALID_SORT_KEYS.join(", ")}.`
41363
+ );
41364
+ process.exitCode = 1;
41365
+ return;
41366
+ }
41367
+ const sortKey = opts.sort;
41144
41368
  const containerName = `olam-${worldId}-devbox`;
41145
41369
  let watchInterval;
41146
41370
  function fetchAndPrint() {
@@ -41880,7 +42104,7 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
41880
42104
  return { worldId, ok: true };
41881
42105
  }
41882
42106
  function registerRefresh(program2) {
41883
- program2.command("refresh").description("Hot-refresh a running world's per-world CP from the local checkout").argument("[world]", "World ID").option("--all", "Refresh every running world sequentially (overrides positional arg)").option("--no-restart", "Copy files but skip CP restart (for debugging)").option("--skip-build", "Skip the prerequisite server.mjs presence check").action(async (worldId, opts) => {
42107
+ program2.command("refresh").description("Hot-refresh a running world's per-world container-CP bundle (packages/control-plane/standalone/ \u2014 legacy per-world CP surface)").argument("[world]", "World ID").option("--all", "Refresh every running world sequentially (overrides positional arg)").option("--no-restart", "Copy files but skip CP restart (for debugging)").option("--skip-build", "Skip the prerequisite server.mjs presence check").action(async (worldId, opts) => {
41884
42108
  if (!opts.all && !worldId) {
41885
42109
  printError("Specify a world ID or use --all to refresh all running worlds.");
41886
42110
  process.exitCode = 1;
@@ -42566,7 +42790,7 @@ async function runPeripheralProbes(peripheral, startPosition, kubectlContext, wr
42566
42790
  })();
42567
42791
  rows.push({ name: `${peripheral.name} ready`, result: reachableResult, position: startPosition });
42568
42792
  const pfLivenessResult = await (async () => {
42569
- return new Promise((resolve30) => {
42793
+ return new Promise((resolve31) => {
42570
42794
  const socket = new net4.Socket();
42571
42795
  let done = false;
42572
42796
  const finish = (alive) => {
@@ -42574,9 +42798,9 @@ async function runPeripheralProbes(peripheral, startPosition, kubectlContext, wr
42574
42798
  done = true;
42575
42799
  socket.destroy();
42576
42800
  if (alive) {
42577
- resolve30({ ok: true, message: `${peripheral.name} port-forward live on :${peripheral.port}` });
42801
+ resolve31({ ok: true, message: `${peripheral.name} port-forward live on :${peripheral.port}` });
42578
42802
  } else {
42579
- resolve30({
42803
+ resolve31({
42580
42804
  ok: true,
42581
42805
  warn: true,
42582
42806
  message: `${peripheral.name} port-forward not live on :${peripheral.port}`,
@@ -43804,8 +44028,8 @@ function registerCompletion(program2) {
43804
44028
  init_cli_version();
43805
44029
  init_health_probes();
43806
44030
  import { spawn as spawn8, spawnSync as spawnSync29 } from "node:child_process";
43807
- import { existsSync as existsSync90, readFileSync as readFileSync78 } from "node:fs";
43808
- import { homedir as homedir53 } from "node:os";
44031
+ import { existsSync as existsSync92, readFileSync as readFileSync80 } from "node:fs";
44032
+ import { homedir as homedir54 } from "node:os";
43809
44033
  import path84 from "node:path";
43810
44034
  import { createInterface as createInterface5 } from "node:readline";
43811
44035
 
@@ -44052,9 +44276,9 @@ async function pickSkillSourcePhase(opts, deps) {
44052
44276
  }
44053
44277
 
44054
44278
  // src/commands/setup-phase-5b-project-sweep.ts
44055
- import { homedir as homedir50 } from "node:os";
44279
+ import { homedir as homedir51 } from "node:os";
44056
44280
  import * as path82 from "node:path";
44057
- import * as fs82 from "node:fs";
44281
+ import * as fs83 from "node:fs";
44058
44282
  async function loadWalkFn() {
44059
44283
  const m = await Promise.resolve().then(() => (init_project_sweep(), project_sweep_exports));
44060
44284
  return m.walkProjectRoot;
@@ -44085,9 +44309,9 @@ async function runProjectSweepPhase(opts, deps, sweepDeps = {}) {
44085
44309
  if (opts.skipProjectSweep) {
44086
44310
  return { ok: true, skipped: true, message: "skipped via --skip-project-sweep" };
44087
44311
  }
44088
- const home = deps.home ?? homedir50();
44312
+ const home = deps.home ?? homedir51();
44089
44313
  const projectsRoot = opts.projects ?? path82.join(home, "Projects");
44090
- const existsSyncFn = sweepDeps.existsSync ?? fs82.existsSync;
44314
+ const existsSyncFn = sweepDeps.existsSync ?? fs83.existsSync;
44091
44315
  if (!existsSyncFn(projectsRoot)) {
44092
44316
  return {
44093
44317
  ok: true,
@@ -44188,7 +44412,7 @@ async function runProjectSweepPhase(opts, deps, sweepDeps = {}) {
44188
44412
  }
44189
44413
 
44190
44414
  // src/commands/setup-phase-8-kg-hook.ts
44191
- import * as fs83 from "node:fs";
44415
+ import * as fs84 from "node:fs";
44192
44416
  import * as path83 from "node:path";
44193
44417
  import * as os47 from "node:os";
44194
44418
  async function loadMergeHookFn() {
@@ -44218,7 +44442,7 @@ async function runKgHookPhase(opts, _deps, kgDeps = {}) {
44218
44442
  message: `dry-run: would install KG hook into ${settingsPath}`
44219
44443
  };
44220
44444
  }
44221
- const mkdirFn = kgDeps.mkdirSync ?? ((p, o) => fs83.mkdirSync(p, o));
44445
+ const mkdirFn = kgDeps.mkdirSync ?? ((p, o) => fs84.mkdirSync(p, o));
44222
44446
  try {
44223
44447
  mkdirFn(path83.dirname(settingsPath), { recursive: true });
44224
44448
  } catch (err) {
@@ -44306,10 +44530,10 @@ var NEXT_STEPS_DOCS_KUBERNETES = [
44306
44530
  "https://github.com/pleri/olam/blob/main/docs/architecture/config-spec.md \u2014 workspace .olam/config.yaml schema",
44307
44531
  "https://github.com/pleri/olam/blob/main/docs/k8s/SETUP.md \u2014 k3d operator guide"
44308
44532
  ];
44309
- var defaultSpawn2 = (cmd, args) => new Promise((resolve30) => {
44533
+ var defaultSpawn2 = (cmd, args) => new Promise((resolve31) => {
44310
44534
  const child = spawn8(cmd, [...args], { stdio: "inherit" });
44311
- child.on("exit", (code) => resolve30({ status: code }));
44312
- child.on("error", () => resolve30({ status: 1 }));
44535
+ child.on("exit", (code) => resolve31({ status: code }));
44536
+ child.on("error", () => resolve31({ status: 1 }));
44313
44537
  });
44314
44538
  var defaultPrompt = (question, defaultYes) => {
44315
44539
  if (!process.stdin.isTTY) {
@@ -44319,18 +44543,18 @@ var defaultPrompt = (question, defaultYes) => {
44319
44543
  );
44320
44544
  return Promise.resolve(defaultYes);
44321
44545
  }
44322
- return new Promise((resolve30) => {
44546
+ return new Promise((resolve31) => {
44323
44547
  const rl = createInterface5({ input: process.stdin, output: process.stdout });
44324
44548
  const suffix = defaultYes ? " [Y/n]: " : " [y/N]: ";
44325
44549
  rl.question(`${question}${suffix}`, (answer) => {
44326
44550
  rl.close();
44327
44551
  const t = answer.trim().toLowerCase();
44328
- if (t === "") resolve30(defaultYes);
44329
- else if (t === "y" || t === "yes") resolve30(true);
44330
- else if (t === "n" || t === "no") resolve30(false);
44331
- else resolve30(defaultYes);
44552
+ if (t === "") resolve31(defaultYes);
44553
+ else if (t === "y" || t === "yes") resolve31(true);
44554
+ else if (t === "n" || t === "no") resolve31(false);
44555
+ else resolve31(defaultYes);
44332
44556
  });
44333
- rl.on("close", () => resolve30(defaultYes));
44557
+ rl.on("close", () => resolve31(defaultYes));
44334
44558
  });
44335
44559
  };
44336
44560
  var CLUSTER_NAME_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
@@ -44350,9 +44574,9 @@ function resolveSubstrate(opts, deps) {
44350
44574
  if (opts.substrate === "kubernetes") return "kubernetes";
44351
44575
  if (opts.substrate === "docker") return "docker";
44352
44576
  const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
44353
- if (existsSync90(configPath)) {
44577
+ if (existsSync92(configPath)) {
44354
44578
  try {
44355
- const raw = readFileSync78(configPath, "utf8");
44579
+ const raw = readFileSync80(configPath, "utf8");
44356
44580
  const parsed = JSON.parse(raw);
44357
44581
  const host = parsed.host;
44358
44582
  if (host?.substrate === "kubernetes") return "kubernetes";
@@ -44419,9 +44643,9 @@ async function phase0SubstratePicker(opts, deps) {
44419
44643
  return { ok: true, skipped: true, message: "skipped via --skip-substrate-picker" };
44420
44644
  }
44421
44645
  const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
44422
- if (existsSync90(configPath)) {
44646
+ if (existsSync92(configPath)) {
44423
44647
  try {
44424
- const raw = readFileSync78(configPath, "utf8");
44648
+ const raw = readFileSync80(configPath, "utf8");
44425
44649
  const parsed = JSON.parse(raw);
44426
44650
  const host = parsed.host;
44427
44651
  if (host?.substrate !== void 0 && host?.preferred_runtime !== void 0) {
@@ -44471,9 +44695,9 @@ async function phase0SubstratePicker(opts, deps) {
44471
44695
  const choice = SUBSTRATE_CHOICES[Number(pickedIndex)] ?? DEFAULT_SUBSTRATE_CHOICE;
44472
44696
  if (choice.requirePinnedContext) {
44473
44697
  let hasPinnedContext = false;
44474
- if (existsSync90(configPath)) {
44698
+ if (existsSync92(configPath)) {
44475
44699
  try {
44476
- const raw = readFileSync78(configPath, "utf8");
44700
+ const raw = readFileSync80(configPath, "utf8");
44477
44701
  const parsed = JSON.parse(raw);
44478
44702
  const host = parsed.host;
44479
44703
  hasPinnedContext = typeof host?.kubectl_context_pinned === "string" && host.kubectl_context_pinned.length > 0;
@@ -44630,7 +44854,7 @@ async function phase1SystemCheck(substrate, deps) {
44630
44854
  };
44631
44855
  }
44632
44856
  const platform2 = String(deps.osPlatform ?? process.platform);
44633
- const home = deps.home ?? homedir53();
44857
+ const home = deps.home ?? homedir54();
44634
44858
  const colimaLint = probeColimaKubernetesEnabled({ platform: platform2, home });
44635
44859
  if (colimaLint.ok && "warn" in colimaLint && colimaLint.warn === true) {
44636
44860
  const lintWithWarn = colimaLint;
@@ -44769,8 +44993,8 @@ async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reus
44769
44993
  process.stdout.write(`Creating k3d cluster ${clusterName}...
44770
44994
  `);
44771
44995
  const volumes = [];
44772
- const ghConfigDir = `${homedir53()}/.config/gh`;
44773
- if (existsSync90(ghConfigDir)) {
44996
+ const ghConfigDir = `${homedir54()}/.config/gh`;
44997
+ if (existsSync92(ghConfigDir)) {
44774
44998
  volumes.push("--volume", `${ghConfigDir}:/host/.config/gh`);
44775
44999
  } else {
44776
45000
  process.stdout.write(
@@ -44779,7 +45003,7 @@ async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reus
44779
45003
  );
44780
45004
  }
44781
45005
  if (opts.hostCpDevPath) {
44782
- if (!existsSync90(opts.hostCpDevPath)) {
45006
+ if (!existsSync92(opts.hostCpDevPath)) {
44783
45007
  return {
44784
45008
  ok: false,
44785
45009
  message: `--host-cp-dev-path ${opts.hostCpDevPath} does not exist`,
@@ -44944,7 +45168,7 @@ async function phase3_5K3dHttpsBootstrap(substrate, opts, _deps) {
44944
45168
  const result = await ensureTlsInstalled();
44945
45169
  let hostsWarning = "";
44946
45170
  try {
44947
- const hostsBody = readFileSync78("/etc/hosts", "utf-8");
45171
+ const hostsBody = readFileSync80("/etc/hosts", "utf-8");
44948
45172
  if (!/^[^#\n]*\bolam\.local\b/m.test(hostsBody)) {
44949
45173
  hostsWarning = " Add to /etc/hosts: echo '127.0.0.1 olam.local' | sudo tee -a /etc/hosts";
44950
45174
  }
@@ -44970,7 +45194,7 @@ async function phase4ShellInit(opts, deps) {
44970
45194
  if (opts.skipShellInit) {
44971
45195
  return { ok: true, skipped: true, message: "skipped via --skip-shell-init" };
44972
45196
  }
44973
- const home = deps.home ?? homedir53();
45197
+ const home = deps.home ?? homedir54();
44974
45198
  const shellEnv = deps.shellEnv ?? process.env.SHELL;
44975
45199
  const rcPath = resolveShellRc(home, shellEnv);
44976
45200
  if (rcPath === null) {
@@ -45484,24 +45708,24 @@ function registerSetupLinuxGate(program2) {
45484
45708
  }
45485
45709
 
45486
45710
  // src/commands/update.ts
45487
- import * as fs86 from "node:fs";
45711
+ import * as fs87 from "node:fs";
45488
45712
  import * as os49 from "node:os";
45489
45713
  import * as path87 from "node:path";
45490
45714
  import { execSync as execSync15 } from "node:child_process";
45491
45715
  import pc33 from "picocolors";
45492
45716
 
45493
45717
  // src/lib/symlink-reconcile.ts
45494
- import * as fs84 from "node:fs";
45718
+ import * as fs85 from "node:fs";
45495
45719
  import * as path85 from "node:path";
45496
45720
  var realFs = {
45497
- readdirSync: (p) => fs84.readdirSync(p),
45498
- existsSync: (p) => fs84.existsSync(p),
45499
- lstatSync: (p) => fs84.lstatSync(p),
45500
- readlinkSync: (p) => fs84.readlinkSync(p),
45501
- symlinkSync: (t, l) => fs84.symlinkSync(t, l),
45502
- unlinkSync: (p) => fs84.unlinkSync(p),
45721
+ readdirSync: (p) => fs85.readdirSync(p),
45722
+ existsSync: (p) => fs85.existsSync(p),
45723
+ lstatSync: (p) => fs85.lstatSync(p),
45724
+ readlinkSync: (p) => fs85.readlinkSync(p),
45725
+ symlinkSync: (t, l) => fs85.symlinkSync(t, l),
45726
+ unlinkSync: (p) => fs85.unlinkSync(p),
45503
45727
  mkdirSync: (p, o) => {
45504
- fs84.mkdirSync(p, o);
45728
+ fs85.mkdirSync(p, o);
45505
45729
  }
45506
45730
  };
45507
45731
  function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
@@ -45595,22 +45819,22 @@ function getCurrentVersion(_exec = defaultExec) {
45595
45819
  }
45596
45820
  function readLastStable(file = LAST_STABLE_FILE) {
45597
45821
  try {
45598
- const v = fs86.readFileSync(file, "utf-8").trim();
45822
+ const v = fs87.readFileSync(file, "utf-8").trim();
45599
45823
  return v || null;
45600
45824
  } catch {
45601
45825
  return null;
45602
45826
  }
45603
45827
  }
45604
45828
  function writeLastStable(version, file = LAST_STABLE_FILE) {
45605
- fs86.mkdirSync(path87.dirname(file), { recursive: true });
45606
- fs86.writeFileSync(file, version, { mode: 420 });
45829
+ fs87.mkdirSync(path87.dirname(file), { recursive: true });
45830
+ fs87.writeFileSync(file, version, { mode: 420 });
45607
45831
  }
45608
45832
  function logUpdateFailure(stderr) {
45609
45833
  const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
45610
45834
  const logFile = path87.join(LOG_DIR2, `update-${ts}.log`);
45611
45835
  try {
45612
- fs86.mkdirSync(LOG_DIR2, { recursive: true });
45613
- fs86.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
45836
+ fs87.mkdirSync(LOG_DIR2, { recursive: true });
45837
+ fs87.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
45614
45838
  ${stderr}
45615
45839
  `, "utf-8");
45616
45840
  } catch {
@@ -45831,7 +46055,7 @@ function registerBegin(program2) {
45831
46055
  // src/commands/config.ts
45832
46056
  init_global_config();
45833
46057
  init_store2();
45834
- import * as fs87 from "node:fs";
46058
+ import * as fs88 from "node:fs";
45835
46059
  import { createRequire as createRequire4 } from "node:module";
45836
46060
  var _require4 = createRequire4(import.meta.url);
45837
46061
  var { parse: parseWithMap } = _require4("json-source-map");
@@ -45848,14 +46072,14 @@ function registerConfig(program2) {
45848
46072
  const config = program2.command("config").description("Manage global olam configuration");
45849
46073
  config.command("validate [path]").description("Validate ~/.olam/config.json (or a custom path) against the schema").action((filePath) => {
45850
46074
  const resolvedPath = filePath ?? globalConfigPath();
45851
- if (!fs87.existsSync(resolvedPath)) {
46075
+ if (!fs88.existsSync(resolvedPath)) {
45852
46076
  process.stderr.write(`config file not found: ${resolvedPath}
45853
46077
  `);
45854
46078
  process.exit(1);
45855
46079
  }
45856
46080
  let raw;
45857
46081
  try {
45858
- raw = fs87.readFileSync(resolvedPath, "utf-8");
46082
+ raw = fs88.readFileSync(resolvedPath, "utf-8");
45859
46083
  } catch (err) {
45860
46084
  const msg = err instanceof Error ? err.message : String(err);
45861
46085
  process.stderr.write(`cannot read ${resolvedPath}: ${msg}
@@ -46303,9 +46527,9 @@ import * as readline3 from "node:readline";
46303
46527
  import pc37 from "picocolors";
46304
46528
 
46305
46529
  // src/commands/flywheel/install-shims.ts
46306
- import { copyFileSync as copyFileSync9, existsSync as existsSync94, mkdirSync as mkdirSync56, readFileSync as readFileSync82, writeFileSync as writeFileSync48 } from "node:fs";
46307
- import { homedir as homedir56 } from "node:os";
46308
- import { dirname as dirname52, join as join96 } from "node:path";
46530
+ import { copyFileSync as copyFileSync9, existsSync as existsSync96, mkdirSync as mkdirSync57, readFileSync as readFileSync84, writeFileSync as writeFileSync50 } from "node:fs";
46531
+ import { homedir as homedir57 } from "node:os";
46532
+ import { dirname as dirname53, join as join97 } from "node:path";
46309
46533
 
46310
46534
  // src/lib/shim-generator.ts
46311
46535
  var SHIM_SPECS = Object.freeze([
@@ -46368,7 +46592,7 @@ ${argsBlock}
46368
46592
  // src/commands/flywheel/install-shims.ts
46369
46593
  var SHIM_HEADER_MARKER = "# AUTO-GENERATED by `olam flywheel install-shims`";
46370
46594
  function refreshShims(opts = {}) {
46371
- const targetDir = opts.targetDir ?? join96(homedir56(), ".claude", "scripts");
46595
+ const targetDir = opts.targetDir ?? join97(homedir57(), ".claude", "scripts");
46372
46596
  const results = [];
46373
46597
  let written = 0;
46374
46598
  let overwritten = 0;
@@ -46398,22 +46622,22 @@ function isOlamGeneratedShim(text) {
46398
46622
  return text.includes(SHIM_HEADER_MARKER);
46399
46623
  }
46400
46624
  function installOne(spec, targetDir, opts) {
46401
- const targetPath = join96(targetDir, spec.basename);
46625
+ const targetPath = join97(targetDir, spec.basename);
46402
46626
  const newContent = generateShim(spec);
46403
- if (!existsSync94(targetPath)) {
46627
+ if (!existsSync96(targetPath)) {
46404
46628
  if (opts.dryRun !== true) {
46405
- mkdirSync56(dirname52(targetPath), { recursive: true });
46406
- writeFileSync48(targetPath, newContent, { mode: 493 });
46629
+ mkdirSync57(dirname53(targetPath), { recursive: true });
46630
+ writeFileSync50(targetPath, newContent, { mode: 493 });
46407
46631
  }
46408
46632
  return { basename: spec.basename, action: "written", targetPath };
46409
46633
  }
46410
- const existing = readFileSync82(targetPath, "utf8");
46634
+ const existing = readFileSync84(targetPath, "utf8");
46411
46635
  if (existing === newContent) {
46412
46636
  return { basename: spec.basename, action: "unchanged", targetPath };
46413
46637
  }
46414
46638
  if (isOlamGeneratedShim(existing)) {
46415
46639
  if (opts.dryRun !== true) {
46416
- writeFileSync48(targetPath, newContent, { mode: 493 });
46640
+ writeFileSync50(targetPath, newContent, { mode: 493 });
46417
46641
  }
46418
46642
  return { basename: spec.basename, action: "overwritten", targetPath };
46419
46643
  }
@@ -46421,7 +46645,7 @@ function installOne(spec, targetDir, opts) {
46421
46645
  const backupPath = `${targetPath}.shim-backup-${Math.floor(Date.now() / 1e3)}`;
46422
46646
  if (opts.dryRun !== true) {
46423
46647
  copyFileSync9(targetPath, backupPath);
46424
- writeFileSync48(targetPath, newContent, { mode: 493 });
46648
+ writeFileSync50(targetPath, newContent, { mode: 493 });
46425
46649
  }
46426
46650
  return { basename: spec.basename, action: "overwritten", targetPath, backupPath };
46427
46651
  }
@@ -46429,7 +46653,7 @@ function installOne(spec, targetDir, opts) {
46429
46653
  }
46430
46654
  function registerFlywheelInstallShims(parent) {
46431
46655
  parent.command("install-shims").description("Install backwards-compat bash shims under ~/.claude/scripts/ that delegate to olam flywheel <subcmd>").option("--force", "overwrite existing non-shim files (backs them up to .shim-backup-<ts>)").option("--dry-run", "preview which shims would be written without modifying disk").option("--target-dir <path>", "override target directory (default: ~/.claude/scripts/); for tests").action((opts) => {
46432
- const targetDir = opts.targetDir ?? join96(homedir56(), ".claude", "scripts");
46656
+ const targetDir = opts.targetDir ?? join97(homedir57(), ".claude", "scripts");
46433
46657
  const summary2 = refreshShims(opts);
46434
46658
  const lines = [];
46435
46659
  const dryRunSuffix = opts.dryRun === true ? " (dry-run)" : "";
@@ -46482,7 +46706,7 @@ async function decideTrust(opts) {
46482
46706
  return { granted: !denied, method: "interactive" };
46483
46707
  }
46484
46708
  function defaultTrustPrompt(gitUrl) {
46485
- return new Promise((resolve30) => {
46709
+ return new Promise((resolve31) => {
46486
46710
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
46487
46711
  process.stdout.write(
46488
46712
  `${pc37.yellow("Trust gate:")} register "${gitUrl}" as a skill source?
@@ -46492,12 +46716,12 @@ Trust this source? ${pc37.dim("[Y/n] ")}`
46492
46716
  );
46493
46717
  rl.question("", (a) => {
46494
46718
  rl.close();
46495
- resolve30(a);
46719
+ resolve31(a);
46496
46720
  });
46497
46721
  });
46498
46722
  }
46499
46723
  function defaultSourcePrefixPrompt(input2) {
46500
- return new Promise((resolve30) => {
46724
+ return new Promise((resolve31) => {
46501
46725
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
46502
46726
  const cfg = input2.newConfig;
46503
46727
  const prefixLabel = cfg.prefix !== void 0 ? `'${cfg.prefix}:'` : "(no prefix)";
@@ -46509,12 +46733,12 @@ Adopt for this host? ${pc37.dim("[Y/n] ")}`
46509
46733
  );
46510
46734
  rl.question("", (a) => {
46511
46735
  rl.close();
46512
- resolve30(!/^n(o)?$/i.test(a.trim()));
46736
+ resolve31(!/^n(o)?$/i.test(a.trim()));
46513
46737
  });
46514
46738
  });
46515
46739
  }
46516
46740
  function defaultPostAddPrompt(input2) {
46517
- return new Promise((resolve30) => {
46741
+ return new Promise((resolve31) => {
46518
46742
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
46519
46743
  process.stdout.write(`
46520
46744
  ${pc37.bold("Sync now?")} ${pc37.dim("[Y/n] ")}`);
@@ -46522,7 +46746,7 @@ ${pc37.bold("Sync now?")} ${pc37.dim("[Y/n] ")}`);
46522
46746
  const sync = !/^n(o)?$/i.test(syncAnswer.trim());
46523
46747
  if (input2.hookAlreadyInstalled) {
46524
46748
  rl.close();
46525
- resolve30({ syncNow: sync, installHook: false });
46749
+ resolve31({ syncNow: sync, installHook: false });
46526
46750
  return;
46527
46751
  }
46528
46752
  process.stdout.write(
@@ -46531,7 +46755,7 @@ ${pc37.bold("Sync now?")} ${pc37.dim("[Y/n] ")}`);
46531
46755
  rl.question("", (hookAnswer) => {
46532
46756
  rl.close();
46533
46757
  const installHook = !/^n(o)?$/i.test(hookAnswer.trim());
46534
- resolve30({ syncNow: sync, installHook });
46758
+ resolve31({ syncNow: sync, installHook });
46535
46759
  });
46536
46760
  });
46537
46761
  });
@@ -47188,7 +47412,7 @@ function registerSkillsSource(program2) {
47188
47412
  // src/commands/skills.ts
47189
47413
  init_skill_sources();
47190
47414
  init_output();
47191
- import * as fs88 from "node:fs";
47415
+ import * as fs89 from "node:fs";
47192
47416
  import * as os50 from "node:os";
47193
47417
  import * as path88 from "node:path";
47194
47418
  import * as readline4 from "node:readline";
@@ -47199,18 +47423,18 @@ init_markdown_merger();
47199
47423
  init_file_lock();
47200
47424
  import {
47201
47425
  copyFileSync as copyFileSync10,
47202
- existsSync as existsSync95,
47426
+ existsSync as existsSync97,
47203
47427
  lstatSync as lstatSync8,
47204
- mkdirSync as mkdirSync57,
47428
+ mkdirSync as mkdirSync58,
47205
47429
  readdirSync as readdirSync28,
47206
- readFileSync as readFileSync83,
47430
+ readFileSync as readFileSync85,
47207
47431
  readlinkSync as readlinkSync4,
47208
47432
  rmSync as rmSync11,
47209
47433
  statSync as statSync28,
47210
- writeFileSync as writeFileSync49
47434
+ writeFileSync as writeFileSync51
47211
47435
  } from "node:fs";
47212
- import { homedir as homedir57 } from "node:os";
47213
- import { basename as basename8, dirname as dirname53, isAbsolute as isAbsolute4, join as join97, relative as relative5, resolve as resolve23 } from "node:path";
47436
+ import { homedir as homedir58 } from "node:os";
47437
+ import { basename as basename8, dirname as dirname54, isAbsolute as isAbsolute4, join as join98, relative as relative5, resolve as resolve24 } from "node:path";
47214
47438
 
47215
47439
  // src/commands/flywheel/sanitize-persona-output.ts
47216
47440
  var FORBIDDEN_HEADERS = [
@@ -47272,23 +47496,23 @@ function registerFlywheelSanitizePersonaOutput(parent) {
47272
47496
 
47273
47497
  // src/lib/skills-apply-overlays.ts
47274
47498
  function claudeRoot(opts) {
47275
- return opts.claudeDir ?? opts.fixtureRoot ?? join97(homedir57(), ".claude");
47499
+ return opts.claudeDir ?? opts.fixtureRoot ?? join98(homedir58(), ".claude");
47276
47500
  }
47277
47501
  function ensureRealDir(p) {
47278
- if (!existsSync95(p)) {
47279
- mkdirSync57(p, { recursive: true });
47502
+ if (!existsSync97(p)) {
47503
+ mkdirSync58(p, { recursive: true });
47280
47504
  return;
47281
47505
  }
47282
47506
  const stat = lstatSync8(p);
47283
47507
  if (stat.isSymbolicLink()) {
47284
47508
  const targetRaw = readlinkSync4(p);
47285
- const target = isAbsolute4(targetRaw) ? targetRaw : resolve23(dirname53(p), targetRaw);
47509
+ const target = isAbsolute4(targetRaw) ? targetRaw : resolve24(dirname54(p), targetRaw);
47286
47510
  rmSync11(p);
47287
- mkdirSync57(p, { recursive: true });
47288
- if (existsSync95(target) && statSync28(target).isDirectory()) {
47511
+ mkdirSync58(p, { recursive: true });
47512
+ if (existsSync97(target) && statSync28(target).isDirectory()) {
47289
47513
  for (const entry of readdirSync28(target)) {
47290
- const src = join97(target, entry);
47291
- const dest = join97(p, entry);
47514
+ const src = join98(target, entry);
47515
+ const dest = join98(p, entry);
47292
47516
  const srcStat = lstatSync8(src);
47293
47517
  if (srcStat.isDirectory()) {
47294
47518
  try {
@@ -47310,8 +47534,8 @@ function postMergeSanitize(mergedText, label) {
47310
47534
  return { ok: false, reason: `[post-merge-sanitize] ${label} merged output failed sanitizer: ${result.reason}` };
47311
47535
  }
47312
47536
  function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages) {
47313
- const upstreamText = readFileSync83(upstreamPath, "utf8");
47314
- const overlayText = readFileSync83(overlayPath, "utf8");
47537
+ const upstreamText = readFileSync85(upstreamPath, "utf8");
47538
+ const overlayText = readFileSync85(overlayPath, "utf8");
47315
47539
  const result = mergeMarkdown(upstreamText, overlayText, label, upstreamPath, overlayPath);
47316
47540
  if ("error" in result) {
47317
47541
  messages.push(`ERROR ${result.error.reason}`);
@@ -47323,15 +47547,15 @@ function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages)
47323
47547
  return { ok: false, kind: "sanitize" };
47324
47548
  }
47325
47549
  if (!dryRun) {
47326
- mkdirSync57(dirname53(destPath2), { recursive: true });
47327
- writeFileSync49(destPath2, result.merged, "utf8");
47550
+ mkdirSync58(dirname54(destPath2), { recursive: true });
47551
+ writeFileSync51(destPath2, result.merged, "utf8");
47328
47552
  }
47329
47553
  messages.push(`MERGED ${label} \u2192 ${destPath2}${dryRun ? " (dry-run)" : ""}`);
47330
47554
  return { ok: true };
47331
47555
  }
47332
47556
  function isNewAgentOverlay(overlayPath) {
47333
47557
  try {
47334
- const text = readFileSync83(overlayPath, "utf8");
47558
+ const text = readFileSync85(overlayPath, "utf8");
47335
47559
  const { fm } = parseFrontmatter3(text);
47336
47560
  return fm["overlay-intent"] === "new-agent";
47337
47561
  } catch {
@@ -47340,18 +47564,18 @@ function isNewAgentOverlay(overlayPath) {
47340
47564
  }
47341
47565
  function copyNewAgent(overlayPath, destPath2, label, dryRun, messages) {
47342
47566
  if (!dryRun) {
47343
- mkdirSync57(dirname53(destPath2), { recursive: true });
47567
+ mkdirSync58(dirname54(destPath2), { recursive: true });
47344
47568
  copyFileSync10(overlayPath, destPath2);
47345
47569
  }
47346
47570
  messages.push(`NEW-AGENT ${label} \u2192 ${destPath2}${dryRun ? " (dry-run)" : ""}`);
47347
47571
  }
47348
47572
  function walkSkillsOverlays(skillsOverridesDir, skillsDir, opts, result) {
47349
- if (!existsSync95(skillsOverridesDir)) return;
47573
+ if (!existsSync97(skillsOverridesDir)) return;
47350
47574
  for (const skillName of readdirSync28(skillsOverridesDir)) {
47351
- const overlaySkillDir = join97(skillsOverridesDir, skillName);
47575
+ const overlaySkillDir = join98(skillsOverridesDir, skillName);
47352
47576
  if (!statSync28(overlaySkillDir).isDirectory()) continue;
47353
- const upstreamSkillDir = join97(skillsDir, skillName);
47354
- if (!existsSync95(upstreamSkillDir)) {
47577
+ const upstreamSkillDir = join98(skillsDir, skillName);
47578
+ if (!existsSync97(upstreamSkillDir)) {
47355
47579
  result.messages.push(`SKIP ${skillName}: no upstream skill at ${upstreamSkillDir} (skill overlays require an upstream skill dir)`);
47356
47580
  continue;
47357
47581
  }
@@ -47364,7 +47588,7 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
47364
47588
  while (stack.length > 0) {
47365
47589
  const current = stack.pop();
47366
47590
  for (const entry of readdirSync28(current)) {
47367
- const overlayPath = join97(current, entry);
47591
+ const overlayPath = join98(current, entry);
47368
47592
  const stat = lstatSync8(overlayPath);
47369
47593
  if (stat.isDirectory()) {
47370
47594
  stack.push(overlayPath);
@@ -47372,17 +47596,17 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
47372
47596
  }
47373
47597
  if (!stat.isFile() && !stat.isSymbolicLink()) continue;
47374
47598
  const rel = relative5(overlayRoot, overlayPath);
47375
- const upstreamPath = join97(upstreamRoot, rel);
47599
+ const upstreamPath = join98(upstreamRoot, rel);
47376
47600
  const label = `${labelPrefix} ${rel}`;
47377
47601
  if (!entry.endsWith(".md")) {
47378
47602
  if (!opts.dryRun) {
47379
- mkdirSync57(dirname53(upstreamPath), { recursive: true });
47603
+ mkdirSync58(dirname54(upstreamPath), { recursive: true });
47380
47604
  copyFileSync10(overlayPath, upstreamPath);
47381
47605
  }
47382
47606
  result.messages.push(`COPY ${label} \u2192 ${upstreamPath}${opts.dryRun === true ? " (dry-run)" : ""}`);
47383
47607
  continue;
47384
47608
  }
47385
- if (!existsSync95(upstreamPath)) {
47609
+ if (!existsSync97(upstreamPath)) {
47386
47610
  if (isAgentsContext && isNewAgentOverlay(overlayPath)) {
47387
47611
  copyNewAgent(overlayPath, upstreamPath, label, opts.dryRun === true, result.messages);
47388
47612
  result.newAgentsCreated += 1;
@@ -47391,7 +47615,7 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
47391
47615
  result.renameHalts += 1;
47392
47616
  } else {
47393
47617
  if (!opts.dryRun) {
47394
- mkdirSync57(dirname53(upstreamPath), { recursive: true });
47618
+ mkdirSync58(dirname54(upstreamPath), { recursive: true });
47395
47619
  copyFileSync10(overlayPath, upstreamPath);
47396
47620
  }
47397
47621
  result.messages.push(`NEW-FILE ${label} \u2192 ${upstreamPath}${opts.dryRun === true ? " (dry-run)" : ""}`);
@@ -47411,16 +47635,16 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
47411
47635
  }
47412
47636
  }
47413
47637
  function walkAgentsOverlays(agentsOverridesDir, agentsDir, opts, result) {
47414
- if (!existsSync95(agentsOverridesDir)) return;
47638
+ if (!existsSync97(agentsOverridesDir)) return;
47415
47639
  ensureRealDir(agentsDir);
47416
47640
  walkOverlayTree(agentsOverridesDir, agentsDir, "agent", opts, result, true);
47417
47641
  }
47418
47642
  async function applyOverlays(opts = {}) {
47419
47643
  const root = claudeRoot(opts);
47420
- const skillsDir = join97(root, "skills");
47421
- const agentsDir = join97(root, "agents");
47422
- const skillsOverridesDir = join97(root, "skills.overrides");
47423
- const agentsOverridesDir = join97(root, "agents.overrides");
47644
+ const skillsDir = join98(root, "skills");
47645
+ const agentsDir = join98(root, "agents");
47646
+ const skillsOverridesDir = join98(root, "skills.overrides");
47647
+ const agentsOverridesDir = join98(root, "agents.overrides");
47424
47648
  const result = {
47425
47649
  rc: 0,
47426
47650
  skillsMerged: 0,
@@ -47463,6 +47687,44 @@ function formatSummary(result) {
47463
47687
  return lines.join("\n") + "\n";
47464
47688
  }
47465
47689
 
47690
+ // src/commands/skills-install-model-router.ts
47691
+ init_model_router_deploy();
47692
+ init_output();
47693
+ function registerSkillsInstallModelRouter(skills) {
47694
+ skills.command("install-model-router").description("Deploy the model-router.py UserPromptSubmit hook script to ~/.claude/hooks/ (idempotent; auto-run by `olam skills sync`)").option("--dry-run", "preview the action without writing to disk").option("--target-dir <path>", "override target directory (default: ~/.claude/hooks/); for tests").option("--source-path <path>", "override canonical source path; for tests").action((opts) => {
47695
+ try {
47696
+ const result = deployModelRouterScript({
47697
+ ...opts.sourcePath !== void 0 ? { sourcePath: opts.sourcePath } : {},
47698
+ ...opts.targetDir !== void 0 ? { targetDir: opts.targetDir } : {},
47699
+ ...opts.dryRun !== void 0 ? { dryRun: opts.dryRun } : {}
47700
+ });
47701
+ const dryRunSuffix = opts.dryRun === true ? " (dry-run)" : "";
47702
+ switch (result.action) {
47703
+ case "written":
47704
+ process.stdout.write(` WRITTEN ${result.targetPath}${dryRunSuffix}
47705
+ `);
47706
+ break;
47707
+ case "unchanged":
47708
+ process.stdout.write(` UNCHANGED ${result.targetPath}
47709
+ `);
47710
+ break;
47711
+ case "source-missing":
47712
+ printError(
47713
+ `canonical model-router.py source not found \u2014 olam install may be corrupt. Expected at packages/cli/hooks/model-router.py.`
47714
+ );
47715
+ process.exitCode = 2;
47716
+ return;
47717
+ }
47718
+ process.stdout.write(`
47719
+ model-router hook script ready at ${result.targetPath}
47720
+ `);
47721
+ } catch (err) {
47722
+ printError(`[install-model-router-error] ${err instanceof Error ? err.message : "unknown error"}`);
47723
+ process.exitCode = 2;
47724
+ }
47725
+ });
47726
+ }
47727
+
47466
47728
  // src/commands/skills.ts
47467
47729
  function asMessage4(err) {
47468
47730
  return err instanceof Error ? err.message : String(err);
@@ -47470,11 +47732,11 @@ function asMessage4(err) {
47470
47732
  var ATLAS_USER_PICKER_RE = /^[a-z0-9][a-z0-9_-]{0,38}$/;
47471
47733
  function listMemberNames(clonePath) {
47472
47734
  const membersDir = path88.join(clonePath, "members");
47473
- if (!fs88.existsSync(membersDir)) return [];
47735
+ if (!fs89.existsSync(membersDir)) return [];
47474
47736
  try {
47475
- return fs88.readdirSync(membersDir).filter((e) => {
47737
+ return fs89.readdirSync(membersDir).filter((e) => {
47476
47738
  try {
47477
- return fs88.statSync(path88.join(membersDir, e)).isDirectory();
47739
+ return fs89.statSync(path88.join(membersDir, e)).isDirectory();
47478
47740
  } catch {
47479
47741
  return false;
47480
47742
  }
@@ -47490,7 +47752,7 @@ function formatSourcePrefix(cfg) {
47490
47752
  return `${p}${s}`;
47491
47753
  }
47492
47754
  function defaultSourcePrefixSyncPrompt(input2) {
47493
- return new Promise((resolve30) => {
47755
+ return new Promise((resolve31) => {
47494
47756
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
47495
47757
  const newLabel = formatSourcePrefix(input2.newConfig);
47496
47758
  let line;
@@ -47507,16 +47769,16 @@ Accept change? ${pc38.dim("[Y/n] ")}`;
47507
47769
  process.stdout.write(line);
47508
47770
  rl.question("", (a) => {
47509
47771
  rl.close();
47510
- resolve30(!/^n(o)?$/i.test(a.trim()));
47772
+ resolve31(!/^n(o)?$/i.test(a.trim()));
47511
47773
  });
47512
47774
  });
47513
47775
  }
47514
47776
  function defaultAtlasUserPrompt(question) {
47515
- return new Promise((resolve30) => {
47777
+ return new Promise((resolve31) => {
47516
47778
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
47517
47779
  rl.question(question, (a) => {
47518
47780
  rl.close();
47519
- resolve30(a);
47781
+ resolve31(a);
47520
47782
  });
47521
47783
  });
47522
47784
  }
@@ -47525,8 +47787,8 @@ async function resolveAtlasUserWithPicker(cliOverride, opts) {
47525
47787
  const ATLAS_USER_RE2 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
47526
47788
  const claudeDirPathForRead = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path88.join(os50.homedir(), ".claude"));
47527
47789
  const atlasUserFile = path88.join(claudeDirPathForRead, ".atlas-user");
47528
- if (fs88.existsSync(atlasUserFile)) {
47529
- const existing = fs88.readFileSync(atlasUserFile, "utf-8").trim();
47790
+ if (fs89.existsSync(atlasUserFile)) {
47791
+ const existing = fs89.readFileSync(atlasUserFile, "utf-8").trim();
47530
47792
  if (existing.length > 0) {
47531
47793
  if (ATLAS_USER_RE2.test(existing)) {
47532
47794
  return existing;
@@ -47586,8 +47848,8 @@ async function resolveAtlasUserWithPicker(cliOverride, opts) {
47586
47848
  return void 0;
47587
47849
  }
47588
47850
  const claudeDirPath = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path88.join(os50.homedir(), ".claude"));
47589
- fs88.mkdirSync(claudeDirPath, { recursive: true });
47590
- fs88.writeFileSync(path88.join(claudeDirPath, ".atlas-user"), picked + "\n", "utf8");
47851
+ fs89.mkdirSync(claudeDirPath, { recursive: true });
47852
+ fs89.writeFileSync(path88.join(claudeDirPath, ".atlas-user"), picked + "\n", "utf8");
47591
47853
  process.stdout.write(pc38.green(`\u2713 atlas-user set to "${picked}" (written to ${path88.join(claudeDirPath, ".atlas-user")})
47592
47854
  `));
47593
47855
  return picked;
@@ -47601,13 +47863,13 @@ function listDeployed() {
47601
47863
  const entries = [];
47602
47864
  for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
47603
47865
  const bucketDir = path88.join(dir, bucket);
47604
- if (!fs88.existsSync(bucketDir)) continue;
47605
- for (const name of fs88.readdirSync(bucketDir)) {
47866
+ if (!fs89.existsSync(bucketDir)) continue;
47867
+ for (const name of fs89.readdirSync(bucketDir)) {
47606
47868
  const full = path88.join(bucketDir, name);
47607
47869
  try {
47608
- const stat = fs88.lstatSync(full);
47870
+ const stat = fs89.lstatSync(full);
47609
47871
  if (!stat.isSymbolicLink()) continue;
47610
- const target = fs88.readlinkSync(full);
47872
+ const target = fs89.readlinkSync(full);
47611
47873
  let sourceId;
47612
47874
  for (const [clonePath, id] of sourcePaths.entries()) {
47613
47875
  if (target.startsWith(clonePath)) {
@@ -47823,17 +48085,18 @@ function registerSkills(program2) {
47823
48085
  process.exitCode = 2;
47824
48086
  }
47825
48087
  });
48088
+ registerSkillsInstallModelRouter(skills);
47826
48089
  }
47827
48090
 
47828
48091
  // src/commands/skills-hook.ts
47829
48092
  init_skill_sources();
47830
48093
  init_output();
47831
- import * as fs89 from "node:fs";
48094
+ import * as fs90 from "node:fs";
47832
48095
  function backup(filePath) {
47833
- if (!fs89.existsSync(filePath)) return null;
48096
+ if (!fs90.existsSync(filePath)) return null;
47834
48097
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
47835
48098
  const backupPath = `${filePath}.olam-bak.${ts}`;
47836
- fs89.copyFileSync(filePath, backupPath);
48099
+ fs90.copyFileSync(filePath, backupPath);
47837
48100
  return backupPath;
47838
48101
  }
47839
48102
  function registerSkillsHook(program2) {
@@ -47881,7 +48144,7 @@ function registerSkillsHook(program2) {
47881
48144
  printInfo("olam-skills hook", `not found in ${filePath} \u2014 already uninstalled`);
47882
48145
  if (backupPath) {
47883
48146
  try {
47884
- fs89.unlinkSync(backupPath);
48147
+ fs90.unlinkSync(backupPath);
47885
48148
  } catch {
47886
48149
  }
47887
48150
  }
@@ -48068,24 +48331,24 @@ init_skill_sources();
48068
48331
  init_merge_settings();
48069
48332
  init_skill_sources();
48070
48333
  init_output();
48071
- import * as fs90 from "node:fs";
48334
+ import * as fs91 from "node:fs";
48072
48335
  import * as path89 from "node:path";
48073
48336
  var MIGRATE_FROM_TOOLBOX_COMMAND = "migrate-from-toolbox";
48074
48337
  function asMessage6(err) {
48075
48338
  return err instanceof Error ? err.message : String(err);
48076
48339
  }
48077
48340
  function isOlamSkillsHookPresent(filePath) {
48078
- if (!fs90.existsSync(filePath)) return false;
48341
+ if (!fs91.existsSync(filePath)) return false;
48079
48342
  try {
48080
- const raw = fs90.readFileSync(filePath, "utf-8");
48343
+ const raw = fs91.readFileSync(filePath, "utf-8");
48081
48344
  return raw.includes(OLAM_SKILLS_HOOK_SENTINEL);
48082
48345
  } catch {
48083
48346
  return false;
48084
48347
  }
48085
48348
  }
48086
48349
  function uninstallLegacyToolboxSessionStartHook(filePath, toolboxPath) {
48087
- if (!fs90.existsSync(filePath)) return { removed: 0 };
48088
- const raw = fs90.readFileSync(filePath, "utf-8");
48350
+ if (!fs91.existsSync(filePath)) return { removed: 0 };
48351
+ const raw = fs91.readFileSync(filePath, "utf-8");
48089
48352
  const settings = raw.trim() ? JSON.parse(raw) : {};
48090
48353
  const ss = settings?.hooks?.SessionStart;
48091
48354
  if (!Array.isArray(ss)) return { removed: 0 };
@@ -48114,7 +48377,7 @@ function uninstallLegacyToolboxSessionStartHook(filePath, toolboxPath) {
48114
48377
  if (otherStages.length === 0) delete next.hooks;
48115
48378
  else delete next.hooks.SessionStart;
48116
48379
  }
48117
- fs90.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
48380
+ fs91.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
48118
48381
  return { removed };
48119
48382
  }
48120
48383
  function registerSkillsMigrate(program2) {
@@ -48193,7 +48456,7 @@ function registerSkillsMigrate(program2) {
48193
48456
  const scope = opts.scope === "user" ? "user" : "project";
48194
48457
  const olamHookPath = scope === "user" ? settingsFile : path89.join(process.cwd(), ".claude", "settings.json");
48195
48458
  try {
48196
- fs90.mkdirSync(path89.dirname(olamHookPath), { recursive: true });
48459
+ fs91.mkdirSync(path89.dirname(olamHookPath), { recursive: true });
48197
48460
  const result = mergeHomeSettingsJson(olamHookPath, {
48198
48461
  ensureHook: {
48199
48462
  stage: OLAM_SKILLS_HOOK_STAGE,
@@ -48226,7 +48489,7 @@ function registerSkillsMigrate(program2) {
48226
48489
  // src/commands/skills-migrate-back.ts
48227
48490
  init_skill_sources();
48228
48491
  init_output();
48229
- import * as fs91 from "node:fs";
48492
+ import * as fs92 from "node:fs";
48230
48493
  import * as path90 from "node:path";
48231
48494
  var MIGRATE_BACK_TO_TOOLBOX_COMMAND = "migrate-back-to-toolbox";
48232
48495
  function asMessage7(err) {
@@ -48242,9 +48505,9 @@ function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
48242
48505
  return { restored: false };
48243
48506
  }
48244
48507
  let settings;
48245
- if (fs91.existsSync(filePath)) {
48508
+ if (fs92.existsSync(filePath)) {
48246
48509
  try {
48247
- const raw = fs91.readFileSync(filePath, "utf-8");
48510
+ const raw = fs92.readFileSync(filePath, "utf-8");
48248
48511
  settings = raw.trim() ? JSON.parse(raw) : {};
48249
48512
  } catch {
48250
48513
  settings = {};
@@ -48260,8 +48523,8 @@ function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
48260
48523
  SessionStart: originalSessionStartHook
48261
48524
  }
48262
48525
  };
48263
- fs91.mkdirSync(path90.dirname(filePath), { recursive: true });
48264
- fs91.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
48526
+ fs92.mkdirSync(path90.dirname(filePath), { recursive: true });
48527
+ fs92.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
48265
48528
  return { restored: true };
48266
48529
  }
48267
48530
  function removeOlamManagedSymlinks() {
@@ -48271,15 +48534,15 @@ function removeOlamManagedSymlinks() {
48271
48534
  let removed = 0;
48272
48535
  for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
48273
48536
  const dir = path90.join(claude, bucket);
48274
- if (!fs91.existsSync(dir)) continue;
48275
- for (const name of fs91.readdirSync(dir)) {
48537
+ if (!fs92.existsSync(dir)) continue;
48538
+ for (const name of fs92.readdirSync(dir)) {
48276
48539
  const linkPath = path90.join(dir, name);
48277
48540
  try {
48278
- const stat = fs91.lstatSync(linkPath);
48541
+ const stat = fs92.lstatSync(linkPath);
48279
48542
  if (!stat.isSymbolicLink()) continue;
48280
- const target = fs91.readlinkSync(linkPath);
48543
+ const target = fs92.readlinkSync(linkPath);
48281
48544
  if (olamClonePaths.some((cp) => target.startsWith(cp))) {
48282
- fs91.unlinkSync(linkPath);
48545
+ fs92.unlinkSync(linkPath);
48283
48546
  removed += 1;
48284
48547
  }
48285
48548
  } catch {
@@ -48292,18 +48555,18 @@ function restoreToolboxSymlinks(symlinks) {
48292
48555
  let restored = 0;
48293
48556
  for (const { link, target } of symlinks) {
48294
48557
  try {
48295
- fs91.mkdirSync(path90.dirname(link), { recursive: true });
48296
- if (fs91.existsSync(link) || (() => {
48558
+ fs92.mkdirSync(path90.dirname(link), { recursive: true });
48559
+ if (fs92.existsSync(link) || (() => {
48297
48560
  try {
48298
- fs91.lstatSync(link);
48561
+ fs92.lstatSync(link);
48299
48562
  return true;
48300
48563
  } catch {
48301
48564
  return false;
48302
48565
  }
48303
48566
  })()) {
48304
- fs91.unlinkSync(link);
48567
+ fs92.unlinkSync(link);
48305
48568
  }
48306
- fs91.symlinkSync(target, link);
48569
+ fs92.symlinkSync(target, link);
48307
48570
  restored += 1;
48308
48571
  } catch {
48309
48572
  }
@@ -48313,8 +48576,8 @@ function restoreToolboxSymlinks(symlinks) {
48313
48576
  function restoreAtlasUserMarker(atlasUser) {
48314
48577
  if (!atlasUser) return false;
48315
48578
  const file = path90.join(claudeDirInternal4(), ".atlas-user");
48316
- fs91.mkdirSync(path90.dirname(file), { recursive: true });
48317
- fs91.writeFileSync(file, atlasUser);
48579
+ fs92.mkdirSync(path90.dirname(file), { recursive: true });
48580
+ fs92.writeFileSync(file, atlasUser);
48318
48581
  return true;
48319
48582
  }
48320
48583
  function registerSkillsMigrateBack(program2) {
@@ -48328,7 +48591,7 @@ function registerSkillsMigrateBack(program2) {
48328
48591
  try {
48329
48592
  if (opts.snapshot) {
48330
48593
  snapshotPath = path90.resolve(opts.snapshot);
48331
- if (!fs91.existsSync(snapshotPath)) {
48594
+ if (!fs92.existsSync(snapshotPath)) {
48332
48595
  printError(`snapshot not found at ${snapshotPath}`);
48333
48596
  process.exitCode = 1;
48334
48597
  return;
@@ -48412,7 +48675,7 @@ init_meta_hooks_migration_snapshot();
48412
48675
  init_trust_audit_log();
48413
48676
  init_atlas_hook_strip();
48414
48677
  init_output();
48415
- import * as fs92 from "node:fs";
48678
+ import * as fs93 from "node:fs";
48416
48679
  import * as path91 from "node:path";
48417
48680
  import pc40 from "picocolors";
48418
48681
  var MIGRATE_HOOKS_COMMAND = "migrate-hooks";
@@ -48434,16 +48697,16 @@ function settingsHasOlamMetaSentinel(settings) {
48434
48697
  return false;
48435
48698
  }
48436
48699
  function readSettings2(filePath) {
48437
- if (!fs92.existsSync(filePath)) return null;
48438
- const raw = fs92.readFileSync(filePath, "utf-8");
48700
+ if (!fs93.existsSync(filePath)) return null;
48701
+ const raw = fs93.readFileSync(filePath, "utf-8");
48439
48702
  if (raw.trim().length === 0) return {};
48440
48703
  return JSON.parse(raw);
48441
48704
  }
48442
48705
  function writeSettings(filePath, settings) {
48443
- fs92.mkdirSync(path91.dirname(filePath), { recursive: true });
48706
+ fs93.mkdirSync(path91.dirname(filePath), { recursive: true });
48444
48707
  const tmp = `${filePath}.tmp-migrate-hooks-${process.pid}-${Date.now()}`;
48445
- fs92.writeFileSync(tmp, JSON.stringify(settings, null, 2) + "\n");
48446
- fs92.renameSync(tmp, filePath);
48708
+ fs93.writeFileSync(tmp, JSON.stringify(settings, null, 2) + "\n");
48709
+ fs93.renameSync(tmp, filePath);
48447
48710
  }
48448
48711
  function printSummary(candidates2, opts) {
48449
48712
  if (candidates2.length === 0) {
@@ -48578,7 +48841,7 @@ function registerSkillsMigrateHooksBack(program2) {
48578
48841
  // src/commands/skills-shadow-backups.ts
48579
48842
  init_skill_sources();
48580
48843
  init_output();
48581
- import * as fs93 from "node:fs";
48844
+ import * as fs94 from "node:fs";
48582
48845
  import pc41 from "picocolors";
48583
48846
  function asMessage10(err) {
48584
48847
  return err instanceof Error ? err.message : String(err);
@@ -48661,7 +48924,7 @@ function registerSkillsShadowBackups(program2) {
48661
48924
  });
48662
48925
  sb.command("restore").description("Move a shadow-backup file back to its original path").argument("<path>", "Absolute path to the .shadow-backup-<epoch> file").option("--force", "Overwrite the original path if it already exists").action((p, opts) => {
48663
48926
  try {
48664
- if (!fs93.existsSync(p)) {
48927
+ if (!fs94.existsSync(p)) {
48665
48928
  printError(`backup file not found: ${p}`);
48666
48929
  process.exitCode = 1;
48667
48930
  return;
@@ -48684,11 +48947,11 @@ function asMessage11(err) {
48684
48947
  return err instanceof Error ? err.message : String(err);
48685
48948
  }
48686
48949
  function defaultDoctorPrompt(question) {
48687
- return new Promise((resolve30) => {
48950
+ return new Promise((resolve31) => {
48688
48951
  const rl = readline5.createInterface({ input: process.stdin, output: process.stdout });
48689
48952
  rl.question(question, (a) => {
48690
48953
  rl.close();
48691
- resolve30(a);
48954
+ resolve31(a);
48692
48955
  });
48693
48956
  });
48694
48957
  }
@@ -48779,23 +49042,26 @@ function registerSkillsDoctor(program2) {
48779
49042
  });
48780
49043
  }
48781
49044
 
48782
- // src/commands/skills-10x.ts
49045
+ // src/commands/skills-100x.ts
48783
49046
  init_skill_sources();
48784
49047
  init_cli_version();
48785
49048
  init_output();
48786
49049
  import { execFileSync as execFileSync17 } from "node:child_process";
48787
- import * as fs94 from "node:fs";
49050
+ import * as fs95 from "node:fs";
48788
49051
  import * as path93 from "node:path";
48789
49052
  var CHAIN_SKILL_NAMES = [
48790
- "10x:brainstorm",
48791
- "10x:plan-hard",
48792
- "10x:review-plan",
48793
- "10x:break-plan",
48794
- "10x:commit-plan",
48795
- "10x:execute",
48796
- "10x:retro",
48797
- "10x:learn"
49053
+ "100x:brainstorm",
49054
+ "100x:plan-hard",
49055
+ "100x:review-plan",
49056
+ "100x:break-plan",
49057
+ "100x:commit-plan",
49058
+ "100x:execute",
49059
+ "100x:retro",
49060
+ "100x:learn"
48798
49061
  ];
49062
+ var PLUGIN_MARKETPLACE = "atlas-builders/atlas-toolbox";
49063
+ var PLUGIN_SPEC = "100x@atlas-one";
49064
+ var PLUGIN_SCOPES = ["user", "project", "local"];
48799
49065
  function asMessage12(err) {
48800
49066
  return err instanceof Error ? err.message : String(err);
48801
49067
  }
@@ -48808,13 +49074,13 @@ function hasBeadsCli() {
48808
49074
  }
48809
49075
  }
48810
49076
  function hasBeadsProjectInit(cwd) {
48811
- return fs94.existsSync(path93.join(cwd, ".beads"));
49077
+ return fs95.existsSync(path93.join(cwd, ".beads"));
48812
49078
  }
48813
49079
  function hasBeadsClaudeSetup() {
48814
49080
  const settingsPath = path93.join(claudeDir(), "settings.json");
48815
- if (!fs94.existsSync(settingsPath)) return false;
49081
+ if (!fs95.existsSync(settingsPath)) return false;
48816
49082
  try {
48817
- const content = fs94.readFileSync(settingsPath, "utf8");
49083
+ const content = fs95.readFileSync(settingsPath, "utf8");
48818
49084
  return /"command"\s*:\s*"bd\b/.test(content) || /"bd setup\b/.test(content);
48819
49085
  } catch {
48820
49086
  return false;
@@ -48851,6 +49117,37 @@ async function bootstrapBeads(cwd) {
48851
49117
  console.log("beads Claude hooks already installed \u2014 skipping bd setup");
48852
49118
  }
48853
49119
  }
49120
+ function normalizeScope(raw) {
49121
+ if (raw === void 0) return "user";
49122
+ if (PLUGIN_SCOPES.includes(raw)) {
49123
+ return raw;
49124
+ }
49125
+ throw new Error(
49126
+ `invalid --scope '${raw}' \u2014 expected one of: ${PLUGIN_SCOPES.join(", ")}`
49127
+ );
49128
+ }
49129
+ function addPluginMarketplace(scope) {
49130
+ console.log(
49131
+ `claude plugin marketplace add ${PLUGIN_MARKETPLACE} (scope: ${scope})`
49132
+ );
49133
+ try {
49134
+ execFileSync17(
49135
+ "claude",
49136
+ ["plugin", "marketplace", "add", PLUGIN_MARKETPLACE, "--scope", scope],
49137
+ { stdio: "inherit" }
49138
+ );
49139
+ } catch (err) {
49140
+ printWarning(
49141
+ `claude plugin marketplace add returned an error (continuing \u2014 likely already added): ${asMessage12(err)}`
49142
+ );
49143
+ }
49144
+ }
49145
+ function installPlugin(scope) {
49146
+ console.log(`claude plugin install ${PLUGIN_SPEC} (scope: ${scope})`);
49147
+ execFileSync17("claude", ["plugin", "install", PLUGIN_SPEC, "--scope", scope], {
49148
+ stdio: "inherit"
49149
+ });
49150
+ }
48854
49151
  function captureSourceShas() {
48855
49152
  return listSkillSources().map((s) => ({
48856
49153
  id: s.id,
@@ -48880,11 +49177,11 @@ function shortSha(sha) {
48880
49177
  }
48881
49178
  function listInstalledClaudeSkills() {
48882
49179
  const skillsDir = path93.join(claudeDir(), "skills");
48883
- if (!fs94.existsSync(skillsDir)) return [];
49180
+ if (!fs95.existsSync(skillsDir)) return [];
48884
49181
  try {
48885
- return fs94.readdirSync(skillsDir).filter((name) => {
49182
+ return fs95.readdirSync(skillsDir).filter((name) => {
48886
49183
  try {
48887
- const stat = fs94.lstatSync(path93.join(skillsDir, name));
49184
+ const stat = fs95.lstatSync(path93.join(skillsDir, name));
48888
49185
  return stat.isSymbolicLink() || stat.isDirectory();
48889
49186
  } catch {
48890
49187
  return false;
@@ -48897,24 +49194,64 @@ function listInstalledClaudeSkills() {
48897
49194
  function isChainSkill(name) {
48898
49195
  const lower = name.toLowerCase();
48899
49196
  return CHAIN_SKILL_NAMES.some((canonical) => {
48900
- const slug = canonical.replace(/^10x:/, "");
48901
- return lower === canonical.toLowerCase() || lower === slug || lower === `10x-${slug}`;
49197
+ const slug = canonical.replace(/^100x:/, "");
49198
+ return lower === canonical.toLowerCase() || lower === slug || lower === `100x-${slug}` || // Legacy pre-rename forms (10x:slug / 10x-slug).
49199
+ lower === `10x:${slug}` || lower === `10x-${slug}`;
48902
49200
  });
48903
49201
  }
48904
- function registerSkills10x(program2) {
48905
- const skills = program2.commands.find((c) => c.name() === "skills") ?? program2.command("skills").description("Manage skill sources and synchronization");
48906
- const tenx = skills.command("10x").description(
48907
- "Manage the /10x: planning chain skills + beads integration"
49202
+ function registerSkills100x(program2) {
49203
+ registerTopLevel100x(program2);
49204
+ registerDeprecatedSkills10xAlias(program2);
49205
+ }
49206
+ function registerTopLevel100x(program2) {
49207
+ const onex = program2.command("100x").description(
49208
+ "Install the /100x: planning chain as a native Claude Code plugin + beads integration"
48908
49209
  );
49210
+ onex.command("install").description(
49211
+ "Install the native Claude Code plugin (claude plugin marketplace add + plugin install) + auto-bootstrap beads (bd init + bd setup claude)."
49212
+ ).option("--no-beads", "Skip beads auto-bootstrap (plugin install only)").option(
49213
+ "--scope <scope>",
49214
+ "Plugin scope passed through to claude (user|project|local)",
49215
+ "user"
49216
+ ).action(async (opts) => {
49217
+ try {
49218
+ const scope = normalizeScope(opts.scope);
49219
+ console.log(
49220
+ "Installing the /100x: chain via the native Claude Code plugin..."
49221
+ );
49222
+ addPluginMarketplace(scope);
49223
+ installPlugin(scope);
49224
+ printSuccess(`Installed plugin ${PLUGIN_SPEC} (scope: ${scope})`);
49225
+ if (opts.beads !== false) {
49226
+ await bootstrapBeads(process.cwd());
49227
+ } else {
49228
+ console.log("--no-beads \u2014 skipping beads auto-bootstrap");
49229
+ }
49230
+ printSuccess("olam 100x install complete");
49231
+ } catch (err) {
49232
+ printError(`Install failed: ${asMessage12(err)}`);
49233
+ process.exitCode = 1;
49234
+ }
49235
+ });
49236
+ }
49237
+ function registerDeprecatedSkills10xAlias(program2) {
49238
+ const skills = program2.commands.find((c) => c.name() === "skills") ?? program2.command("skills").description("Manage skill sources and synchronization");
49239
+ const tenx = skills.command("10x", { hidden: true }).description(
49240
+ "DEPRECATED \u2014 use `olam 100x install`. Manage the /100x: planning chain skills via syncSkills() + beads."
49241
+ ).hook("preAction", () => {
49242
+ printWarning(
49243
+ "DEPRECATED: `olam skills 10x` \u2014 use `olam 100x install` (native Claude Code plugin) instead."
49244
+ );
49245
+ });
48909
49246
  tenx.command("install").description(
48910
- "Sync /10x: chain skills from registered sources + auto-bootstrap beads (bd init + bd setup claude). Surfaces source-SHA bumps + shadow-backups for sentinel-versioned upgrade."
49247
+ "Sync /100x: chain skills from registered sources + auto-bootstrap beads (bd init + bd setup claude). Surfaces source-SHA bumps + shadow-backups for sentinel-versioned upgrade."
48911
49248
  ).option("--no-beads", "Skip beads auto-bootstrap (chain skills only)").option(
48912
49249
  "--force",
48913
49250
  "Suppress shadow-backup warning + proceed without operator attention (shadow backups are still created by the sync engine; this flag only suppresses the surface-prominence)"
48914
49251
  ).action(async (opts) => {
48915
49252
  try {
48916
49253
  const preSync = captureSourceShas();
48917
- console.log("Syncing /10x: chain skills from registered sources...");
49254
+ console.log("Syncing /100x: chain skills from registered sources...");
48918
49255
  const summary2 = await syncSkills({});
48919
49256
  printSuccess(
48920
49257
  `Synced ${summary2.artifactCount} artifact(s) from ${summary2.sourceCount} source(s)`
@@ -48957,43 +49294,43 @@ function registerSkills10x(program2) {
48957
49294
  }
48958
49295
  });
48959
49296
  tenx.command("uninstall").description(
48960
- "Remove /10x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)"
49297
+ "Remove /100x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)"
48961
49298
  ).action(() => {
48962
49299
  const skillsDir = path93.join(claudeDir(), "skills");
48963
- if (!fs94.existsSync(skillsDir)) {
49300
+ if (!fs95.existsSync(skillsDir)) {
48964
49301
  printWarning("No ~/.claude/skills/ directory found; nothing to uninstall");
48965
49302
  return;
48966
49303
  }
48967
49304
  let removed = 0;
48968
- for (const name of fs94.readdirSync(skillsDir)) {
49305
+ for (const name of fs95.readdirSync(skillsDir)) {
48969
49306
  const full = path93.join(skillsDir, name);
48970
49307
  try {
48971
- const stat = fs94.lstatSync(full);
49308
+ const stat = fs95.lstatSync(full);
48972
49309
  if (!stat.isSymbolicLink()) continue;
48973
- const target = fs94.readlinkSync(full);
48974
- if (isChainSkill(name) || /\/10x[-:]/.test(target)) {
48975
- fs94.unlinkSync(full);
49310
+ const target = fs95.readlinkSync(full);
49311
+ if (isChainSkill(name) || /\/(100x|10x)[-:]/.test(target)) {
49312
+ fs95.unlinkSync(full);
48976
49313
  removed += 1;
48977
49314
  }
48978
49315
  } catch {
48979
49316
  }
48980
49317
  }
48981
- printSuccess(`Removed ${removed} /10x: chain skill symlink(s)`);
49318
+ printSuccess(`Removed ${removed} /100x: chain skill symlink(s)`);
48982
49319
  console.log("User-authored + non-chain skill sources preserved");
48983
49320
  });
48984
49321
  tenx.command("doctor").description(
48985
- "Diagnose /10x: chain skill installation + beads bootstrap state"
49322
+ "Diagnose /100x: chain skill installation + beads bootstrap state"
48986
49323
  ).action(() => {
48987
- console.log("=== /10x: chain skills + beads health ===");
49324
+ console.log("=== /100x: chain skills + beads health ===");
48988
49325
  const installed = listInstalledClaudeSkills();
48989
49326
  const chainInstalled = installed.filter(isChainSkill);
48990
49327
  console.log(
48991
- ` /10x: chain skills: ${chainInstalled.length} / ${CHAIN_SKILL_NAMES.length} installed`
49328
+ ` /100x: chain skills: ${chainInstalled.length} / ${CHAIN_SKILL_NAMES.length} installed`
48992
49329
  );
48993
49330
  for (const canonical of CHAIN_SKILL_NAMES) {
48994
- const slug = canonical.replace(/^10x:/, "");
49331
+ const slug = canonical.replace(/^100x:/, "");
48995
49332
  const found = installed.some(
48996
- (n) => n.toLowerCase() === canonical.toLowerCase() || n.toLowerCase() === slug || n.toLowerCase() === `10x-${slug}`
49333
+ (n) => n.toLowerCase() === canonical.toLowerCase() || n.toLowerCase() === slug || n.toLowerCase() === `100x-${slug}` || n.toLowerCase() === `10x:${slug}` || n.toLowerCase() === `10x-${slug}`
48997
49334
  );
48998
49335
  console.log(` ${found ? "\u2713" : "\u2717"} ${canonical}`);
48999
49336
  }
@@ -49006,11 +49343,11 @@ function registerSkills10x(program2) {
49006
49343
  const allChainPresent = chainInstalled.length === CHAIN_SKILL_NAMES.length;
49007
49344
  const allOk = allChainPresent && bdCli && bdInit && bdHooks;
49008
49345
  if (allOk) {
49009
- printSuccess("All /10x: chain skill + beads checks pass");
49346
+ printSuccess("All /100x: chain skill + beads checks pass");
49010
49347
  return;
49011
49348
  }
49012
49349
  const fixHints = [];
49013
- if (!allChainPresent) fixHints.push("olam skills 10x install");
49350
+ if (!allChainPresent) fixHints.push("olam 100x install");
49014
49351
  if (!bdCli) fixHints.push("brew install beads OR npm i -g @beads/bd");
49015
49352
  if (!bdInit) fixHints.push("bd init");
49016
49353
  if (!bdHooks) fixHints.push("bd setup claude");
@@ -49024,7 +49361,7 @@ function registerSkills10x(program2) {
49024
49361
  const olamVersion = readCliVersion();
49025
49362
  const sources = listSkillSources();
49026
49363
  console.log(`olam-cli: ${olamVersion}`);
49027
- console.log(`chain canonical: ${CHAIN_SKILL_NAMES.length} skills (/10x: chain)`);
49364
+ console.log(`chain canonical: ${CHAIN_SKILL_NAMES.length} skills (/100x: chain)`);
49028
49365
  console.log(`registered sources: ${sources.length}`);
49029
49366
  for (const s of sources) {
49030
49367
  const shortId = s.id ? s.id.slice(0, 8) : "????????";
@@ -49040,7 +49377,7 @@ function registerSkills10x(program2) {
49040
49377
 
49041
49378
  // src/commands/hermes.ts
49042
49379
  init_output();
49043
- import * as fs95 from "node:fs";
49380
+ import * as fs96 from "node:fs";
49044
49381
  import * as os51 from "node:os";
49045
49382
  import * as path94 from "node:path";
49046
49383
  import * as child_process from "node:child_process";
@@ -49055,7 +49392,7 @@ function claudeSkillsDir() {
49055
49392
  return path94.join(os51.homedir(), ".claude", "skills");
49056
49393
  }
49057
49394
  function readHermesConfig(configPath) {
49058
- const raw = fs95.readFileSync(configPath, "utf-8");
49395
+ const raw = fs96.readFileSync(configPath, "utf-8");
49059
49396
  const parsed = yamlParse2(raw);
49060
49397
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
49061
49398
  throw new Error(`${configPath} is not a YAML mapping`);
@@ -49063,13 +49400,13 @@ function readHermesConfig(configPath) {
49063
49400
  return parsed;
49064
49401
  }
49065
49402
  function writeHermesConfig(configPath, config) {
49066
- fs95.writeFileSync(configPath, yamlStringify3(config), "utf-8");
49403
+ fs96.writeFileSync(configPath, yamlStringify3(config), "utf-8");
49067
49404
  }
49068
49405
  function resolveOlamBinary() {
49069
49406
  try {
49070
49407
  const result = child_process.spawnSync("which", ["olam"], { encoding: "utf-8" });
49071
49408
  const found = result.stdout.trim();
49072
- if (found && fs95.existsSync(found)) return found;
49409
+ if (found && fs96.existsSync(found)) return found;
49073
49410
  } catch {
49074
49411
  }
49075
49412
  return process.argv[1] ?? "olam";
@@ -49082,7 +49419,7 @@ function resolveWorkspaceDir() {
49082
49419
  { encoding: "utf-8" }
49083
49420
  );
49084
49421
  const out = result.stdout.trim();
49085
- if (out && fs95.existsSync(out)) return out;
49422
+ if (out && fs96.existsSync(out)) return out;
49086
49423
  } catch {
49087
49424
  }
49088
49425
  return process.cwd();
@@ -49152,22 +49489,22 @@ function ensureTerminalBackendLocal(config, dryRun, summary2) {
49152
49489
  }
49153
49490
  function mirrorSkillSymlinks(dryRun, summary2) {
49154
49491
  const srcDir = claudeSkillsDir();
49155
- if (!fs95.existsSync(srcDir)) {
49492
+ if (!fs96.existsSync(srcDir)) {
49156
49493
  summary2.skipped.push("skills mirror (no ~/.claude/skills/ found)");
49157
49494
  return;
49158
49495
  }
49159
49496
  const destDir = hermesSkillsDir();
49160
49497
  if (!dryRun) {
49161
- fs95.mkdirSync(destDir, { recursive: true });
49498
+ fs96.mkdirSync(destDir, { recursive: true });
49162
49499
  }
49163
- const entries = fs95.readdirSync(srcDir);
49500
+ const entries = fs96.readdirSync(srcDir);
49164
49501
  let mirrored = 0;
49165
49502
  let collisions = 0;
49166
49503
  for (const entry of entries) {
49167
49504
  const srcPath = path94.join(srcDir, entry);
49168
49505
  const destPath2 = path94.join(destDir, entry);
49169
- if (fs95.existsSync(destPath2) || fs95.lstatSync(srcPath).isFile()) {
49170
- if (fs95.existsSync(destPath2)) collisions++;
49506
+ if (fs96.existsSync(destPath2) || fs96.lstatSync(srcPath).isFile()) {
49507
+ if (fs96.existsSync(destPath2)) collisions++;
49171
49508
  continue;
49172
49509
  }
49173
49510
  if (dryRun) {
@@ -49175,7 +49512,7 @@ function mirrorSkillSymlinks(dryRun, summary2) {
49175
49512
  continue;
49176
49513
  }
49177
49514
  try {
49178
- fs95.symlinkSync(srcPath, destPath2);
49515
+ fs96.symlinkSync(srcPath, destPath2);
49179
49516
  mirrored++;
49180
49517
  } catch (err) {
49181
49518
  printWarning(`skills mirror: skipping ${entry} \u2014 ${err instanceof Error ? err.message : String(err)}`);
@@ -49194,7 +49531,7 @@ async function runHermesBootstrap(opts, deps = {}) {
49194
49531
  const writeConfig2 = deps.writeConfig ?? writeHermesConfig;
49195
49532
  const mirrorSkillsFn = deps.mirrorSkills ?? mirrorSkillSymlinks;
49196
49533
  const installHookFn = deps.installHook ?? installKgFirstHookForHermes;
49197
- if (!fs95.existsSync(configPath)) {
49534
+ if (!fs96.existsSync(configPath)) {
49198
49535
  printError(`~/.hermes/config.yaml not found at ${configPath}`);
49199
49536
  printInfo(
49200
49537
  "remedy",
@@ -49311,7 +49648,7 @@ function registerStop(program2) {
49311
49648
  }
49312
49649
 
49313
49650
  // src/lib/upgrade-check.ts
49314
- import * as fs96 from "node:fs";
49651
+ import * as fs97 from "node:fs";
49315
49652
  import * as os52 from "node:os";
49316
49653
  import * as path95 from "node:path";
49317
49654
  var UPGRADE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -49330,7 +49667,7 @@ function isNewer(latest, current) {
49330
49667
  }
49331
49668
  function readCache(cachePath) {
49332
49669
  try {
49333
- const raw = fs96.readFileSync(cachePath, "utf-8");
49670
+ const raw = fs97.readFileSync(cachePath, "utf-8");
49334
49671
  const parsed = JSON.parse(raw);
49335
49672
  if (typeof parsed === "object" && parsed !== null && typeof parsed["checkedAt"] === "number" && typeof parsed["latestVersion"] === "string") {
49336
49673
  return parsed;
@@ -49342,8 +49679,8 @@ function readCache(cachePath) {
49342
49679
  function writeCache(cachePath, data) {
49343
49680
  try {
49344
49681
  const dir = path95.dirname(cachePath);
49345
- fs96.mkdirSync(dir, { recursive: true });
49346
- fs96.writeFileSync(cachePath, JSON.stringify(data), "utf-8");
49682
+ fs97.mkdirSync(dir, { recursive: true });
49683
+ fs97.writeFileSync(cachePath, JSON.stringify(data), "utf-8");
49347
49684
  } catch {
49348
49685
  }
49349
49686
  }
@@ -49486,17 +49823,17 @@ function registerWorldUpgrade(program2) {
49486
49823
 
49487
49824
  // src/commands/mcp/serve.ts
49488
49825
  init_output();
49489
- import { existsSync as existsSync104 } from "node:fs";
49490
- import { dirname as dirname59, resolve as resolve26 } from "node:path";
49491
- import { fileURLToPath as fileURLToPath9 } from "node:url";
49492
- var here2 = dirname59(fileURLToPath9(import.meta.url));
49826
+ import { existsSync as existsSync106 } from "node:fs";
49827
+ import { dirname as dirname60, resolve as resolve27 } from "node:path";
49828
+ import { fileURLToPath as fileURLToPath10 } from "node:url";
49829
+ var here2 = dirname60(fileURLToPath10(import.meta.url));
49493
49830
  var BUNDLE_PATH_CANDIDATES = [
49494
49831
  // bundled (`dist/index.js` after bundle-cli.mjs) — sibling
49495
- resolve26(here2, "mcp-server.js"),
49832
+ resolve27(here2, "mcp-server.js"),
49496
49833
  // dev / tsc-only (`dist/commands/mcp/serve.js`) — up two levels
49497
- resolve26(here2, "..", "..", "mcp-server.js")
49834
+ resolve27(here2, "..", "..", "mcp-server.js")
49498
49835
  ];
49499
- function resolveBundlePath(candidates2 = BUNDLE_PATH_CANDIDATES, exists = existsSync104) {
49836
+ function resolveBundlePath(candidates2 = BUNDLE_PATH_CANDIDATES, exists = existsSync106) {
49500
49837
  return candidates2.find(exists) ?? null;
49501
49838
  }
49502
49839
  var MISSING_BUNDLE_REMEDY = "olam mcp server bundle missing. Searched: " + BUNDLE_PATH_CANDIDATES.join(", ") + ". For local dev, run: node packages/cli/scripts/bundle-mcp-server.mjs. A fresh `npm install -g @pleri/olam-cli@latest` should always include the bundle (see prepublishOnly in packages/cli/package.json); file an issue if it does not.";
@@ -49760,7 +50097,7 @@ function registerMcpComplete(cmd) {
49760
50097
  init_output();
49761
50098
  import * as readline6 from "node:readline";
49762
50099
  async function readTokenSilent(prompt) {
49763
- return new Promise((resolve30, reject) => {
50100
+ return new Promise((resolve31, reject) => {
49764
50101
  const rl = readline6.createInterface({
49765
50102
  input: process.stdin,
49766
50103
  output: process.stdout,
@@ -49778,7 +50115,7 @@ async function readTokenSilent(prompt) {
49778
50115
  process.stdin.removeListener("data", onData);
49779
50116
  process.stdout.write("\n");
49780
50117
  rl.close();
49781
- resolve30(token);
50118
+ resolve31(token);
49782
50119
  } else if (char === "") {
49783
50120
  if (process.stdin.isTTY) process.stdin.setRawMode(false);
49784
50121
  process.stdin.removeListener("data", onData);
@@ -49933,12 +50270,12 @@ import * as readline7 from "node:readline";
49933
50270
  import pc45 from "picocolors";
49934
50271
 
49935
50272
  // src/commands/mcp/import-discovery.ts
49936
- import * as fs97 from "node:fs";
50273
+ import * as fs98 from "node:fs";
49937
50274
  import * as os53 from "node:os";
49938
50275
  import * as path96 from "node:path";
49939
50276
  function readJsonFile(filePath) {
49940
50277
  try {
49941
- const raw = fs97.readFileSync(filePath, "utf-8");
50278
+ const raw = fs98.readFileSync(filePath, "utf-8");
49942
50279
  return JSON.parse(raw);
49943
50280
  } catch {
49944
50281
  return null;
@@ -49982,9 +50319,9 @@ function getOlamRepoPaths() {
49982
50319
  ];
49983
50320
  const paths = [];
49984
50321
  for (const configPath of configPaths) {
49985
- if (!fs97.existsSync(configPath)) continue;
50322
+ if (!fs98.existsSync(configPath)) continue;
49986
50323
  try {
49987
- const raw = fs97.readFileSync(configPath, "utf-8");
50324
+ const raw = fs98.readFileSync(configPath, "utf-8");
49988
50325
  const repoMatches = [...raw.matchAll(/path:\s*["']?([^\s"'\n]+)/g)];
49989
50326
  for (const m of repoMatches) {
49990
50327
  if (m[1]) paths.push(m[1]);
@@ -50053,7 +50390,7 @@ async function discoverMcpSources(repoPaths) {
50053
50390
  import { spawn as spawn10 } from "node:child_process";
50054
50391
  var VALIDATION_TIMEOUT_MS = 5e3;
50055
50392
  async function validateMcpEntry(entry) {
50056
- return new Promise((resolve30) => {
50393
+ return new Promise((resolve31) => {
50057
50394
  let stdout = "";
50058
50395
  let timedOut = false;
50059
50396
  let child;
@@ -50063,7 +50400,7 @@ async function validateMcpEntry(entry) {
50063
50400
  env: { ...process.env, ...entry.env ?? {} }
50064
50401
  });
50065
50402
  } catch (err) {
50066
- resolve30({
50403
+ resolve31({
50067
50404
  name: entry.name,
50068
50405
  validated: false,
50069
50406
  reason: err instanceof Error ? err.message : "spawn failed"
@@ -50080,11 +50417,11 @@ async function validateMcpEntry(entry) {
50080
50417
  child.on("close", (code) => {
50081
50418
  clearTimeout(timer);
50082
50419
  if (timedOut) {
50083
- resolve30({ name: entry.name, validated: false, reason: "timeout (5s)" });
50420
+ resolve31({ name: entry.name, validated: false, reason: "timeout (5s)" });
50084
50421
  return;
50085
50422
  }
50086
50423
  const validated = code === 0 && stdout.trim().length > 0;
50087
- resolve30({
50424
+ resolve31({
50088
50425
  name: entry.name,
50089
50426
  validated,
50090
50427
  reason: validated ? "ok" : `exit code ${code ?? "null"}`
@@ -50092,7 +50429,7 @@ async function validateMcpEntry(entry) {
50092
50429
  });
50093
50430
  child.on("error", (err) => {
50094
50431
  clearTimeout(timer);
50095
- resolve30({ name: entry.name, validated: false, reason: err.message });
50432
+ resolve31({ name: entry.name, validated: false, reason: err.message });
50096
50433
  });
50097
50434
  });
50098
50435
  }
@@ -50107,11 +50444,11 @@ async function multiSelectPicker(entries) {
50107
50444
  );
50108
50445
  });
50109
50446
  console.log("\n" + pc45.dim('Enter numbers to import (e.g. 1,2,3 or "all" or Enter to skip):'));
50110
- const answer = await new Promise((resolve30) => {
50447
+ const answer = await new Promise((resolve31) => {
50111
50448
  const rl = readline7.createInterface({ input: process.stdin, output: process.stdout });
50112
50449
  rl.question("> ", (ans) => {
50113
50450
  rl.close();
50114
- resolve30(ans.trim());
50451
+ resolve31(ans.trim());
50115
50452
  });
50116
50453
  });
50117
50454
  if (!answer || answer === "") return [];
@@ -50258,14 +50595,14 @@ init_output();
50258
50595
 
50259
50596
  // src/lib/memory-host-process-migration.ts
50260
50597
  init_paths2();
50261
- import { existsSync as existsSync106, readFileSync as readFileSync92, unlinkSync as unlinkSync23 } from "node:fs";
50598
+ import { existsSync as existsSync108, readFileSync as readFileSync94, unlinkSync as unlinkSync23 } from "node:fs";
50262
50599
  import { spawnSync as spawnSync31 } from "node:child_process";
50263
50600
  var KILL_TIMEOUT_MS = 5e3;
50264
50601
  function migrateFromHostProcess(opts = {}) {
50265
50602
  const pidPath2 = opts.pidPath ?? MEMORY_PID_PATH;
50266
50603
  const logPath = opts.logPath ?? MEMORY_LOG_PATH;
50267
- const pidfileExists = existsSync106(pidPath2);
50268
- const logExists = existsSync106(logPath);
50604
+ const pidfileExists = existsSync108(pidPath2);
50605
+ const logExists = existsSync108(logPath);
50269
50606
  if (!pidfileExists && !logExists) {
50270
50607
  return { cleaned: false, summary: "no legacy host-process state to clean" };
50271
50608
  }
@@ -50304,7 +50641,7 @@ function migrateFromHostProcess(opts = {}) {
50304
50641
  }
50305
50642
  function readPidFromFile(pidPath2) {
50306
50643
  try {
50307
- const raw = readFileSync92(pidPath2, "utf8").trim();
50644
+ const raw = readFileSync94(pidPath2, "utf8").trim();
50308
50645
  const pid = parseInt(raw, 10);
50309
50646
  if (!Number.isFinite(pid) || pid <= 0) return null;
50310
50647
  return pid;
@@ -50434,7 +50771,7 @@ function registerMemoryStop(cmd) {
50434
50771
  init_output();
50435
50772
  init_memory_secret();
50436
50773
  init_paths2();
50437
- import { existsSync as existsSync107 } from "node:fs";
50774
+ import { existsSync as existsSync109 } from "node:fs";
50438
50775
  var RESTART_CHURN_THRESHOLD = 3;
50439
50776
  async function probe(secret) {
50440
50777
  try {
@@ -50461,7 +50798,7 @@ async function collectMemoryStatus() {
50461
50798
  livez,
50462
50799
  secretSet: hasMemorySecret(),
50463
50800
  port: MEMORY_REST_PORT,
50464
- legacyPidfilePresent: existsSync107(MEMORY_PID_PATH),
50801
+ legacyPidfilePresent: existsSync109(MEMORY_PID_PATH),
50465
50802
  startedAt: runtime?.startedAt ?? null,
50466
50803
  restartCount: runtime?.restartCount ?? null,
50467
50804
  health: runtime?.health ?? "unknown"
@@ -50548,8 +50885,8 @@ async function runMemoryLogs(opts) {
50548
50885
  args.push(MEMORY_SERVICE_CONTAINER);
50549
50886
  printHeader(`olam memory logs (${opts.follow ? "follow" : `tail -n ${tailN}`})`);
50550
50887
  const child = spawn11("docker", args, { stdio: "inherit" });
50551
- return new Promise((resolve30) => {
50552
- child.on("exit", (code) => resolve30(code ?? 0));
50888
+ return new Promise((resolve31) => {
50889
+ child.on("exit", (code) => resolve31(code ?? 0));
50553
50890
  });
50554
50891
  }
50555
50892
  function registerMemoryLogs(cmd) {
@@ -50685,14 +51022,14 @@ function registerMemoryUninstall(cmd) {
50685
51022
  init_schema2();
50686
51023
  init_output();
50687
51024
  init_memory_secret();
50688
- import { existsSync as existsSync108, readFileSync as readFileSync93, writeFileSync as writeFileSync56 } from "node:fs";
50689
- import { join as join105 } from "node:path";
51025
+ import { existsSync as existsSync110, readFileSync as readFileSync95, writeFileSync as writeFileSync58 } from "node:fs";
51026
+ import { join as join106 } from "node:path";
50690
51027
  import * as readline8 from "node:readline/promises";
50691
51028
  import { parse as parseYaml9, stringify as stringifyYaml7 } from "yaml";
50692
51029
  var CONFIG_REL = ".olam/config.yaml";
50693
51030
  function locateConfig(cwd) {
50694
- const absPath = join105(cwd, CONFIG_REL);
50695
- if (!existsSync108(absPath)) {
51031
+ const absPath = join106(cwd, CONFIG_REL);
51032
+ if (!existsSync110(absPath)) {
50696
51033
  throw new Error(
50697
51034
  `No ${CONFIG_REL} at ${cwd}. Run \`olam init\` in your workspace root first.`
50698
51035
  );
@@ -50700,7 +51037,7 @@ function locateConfig(cwd) {
50700
51037
  return { absPath };
50701
51038
  }
50702
51039
  function readConfigYaml(absPath) {
50703
- const raw = readFileSync93(absPath, "utf-8");
51040
+ const raw = readFileSync95(absPath, "utf-8");
50704
51041
  const parsed = parseYaml9(raw) ?? {};
50705
51042
  if (typeof parsed !== "object" || parsed === null) {
50706
51043
  throw new Error(`${absPath} is not a YAML object`);
@@ -50709,7 +51046,7 @@ function readConfigYaml(absPath) {
50709
51046
  }
50710
51047
  function writeConfigYaml(absPath, parsed) {
50711
51048
  const out = stringifyYaml7(parsed, { aliasDuplicateObjects: false });
50712
- writeFileSync56(absPath, out, "utf-8");
51049
+ writeFileSync58(absPath, out, "utf-8");
50713
51050
  }
50714
51051
  async function defaultPromptText(question) {
50715
51052
  const rl = readline8.createInterface({ input: process.stdin, output: process.stdout });
@@ -50830,20 +51167,20 @@ init_output();
50830
51167
  init_memory_secret();
50831
51168
  init_paths2();
50832
51169
  import { spawn as spawn12 } from "node:child_process";
50833
- import { existsSync as existsSync109 } from "node:fs";
50834
- import { join as join106 } from "node:path";
51170
+ import { existsSync as existsSync111 } from "node:fs";
51171
+ import { join as join107 } from "node:path";
50835
51172
  var DEFAULT_PORT2 = 8788;
50836
51173
  function resolveMemoryServiceDir() {
50837
51174
  for (const c of MEMORY_SERVICE_CANDIDATES) {
50838
- if (existsSync109(c)) return c;
51175
+ if (existsSync111(c)) return c;
50839
51176
  }
50840
51177
  throw new Error(
50841
51178
  `Could not find packages/memory-service/. Searched: ${MEMORY_SERVICE_CANDIDATES.join(", ")}. If running from a published @pleri/olam-cli tarball, this is a packaging bug \u2014 please file an issue.`
50842
51179
  );
50843
51180
  }
50844
51181
  function resolveLocalBridgeScript(serviceDir) {
50845
- const path106 = join106(serviceDir, "scripts", "local-bridge-server.mjs");
50846
- if (!existsSync109(path106)) {
51182
+ const path106 = join107(serviceDir, "scripts", "local-bridge-server.mjs");
51183
+ if (!existsSync111(path106)) {
50847
51184
  throw new Error(
50848
51185
  `Could not find local-bridge-server.mjs at ${path106}. Verify packages/memory-service ships the scripts/ directory.`
50849
51186
  );
@@ -50891,12 +51228,12 @@ async function runBridgeServe(opts, deps = {}) {
50891
51228
  stdio: "inherit"
50892
51229
  }));
50893
51230
  const child = spawner(process.execPath, [scriptPath, ...args], env);
50894
- return new Promise((resolve30) => {
51231
+ return new Promise((resolve31) => {
50895
51232
  let resolved = false;
50896
51233
  const finish = (code) => {
50897
51234
  if (resolved) return;
50898
51235
  resolved = true;
50899
- resolve30(code);
51236
+ resolve31(code);
50900
51237
  };
50901
51238
  const forward = (signal) => () => {
50902
51239
  if (!child.killed) {
@@ -51184,38 +51521,38 @@ function registerMemoryStats(cmd) {
51184
51521
  }
51185
51522
 
51186
51523
  // src/commands/memory/install-hooks.ts
51187
- import { copyFileSync as copyFileSync12, existsSync as existsSync110, mkdirSync as mkdirSync64, readFileSync as readFileSync94, writeFileSync as writeFileSync57 } from "node:fs";
51188
- import { homedir as homedir62 } from "node:os";
51189
- import { dirname as dirname60, join as join107, resolve as resolve27 } from "node:path";
51190
- import { fileURLToPath as fileURLToPath10 } from "node:url";
51524
+ import { copyFileSync as copyFileSync12, existsSync as existsSync112, mkdirSync as mkdirSync65, readFileSync as readFileSync96, writeFileSync as writeFileSync59 } from "node:fs";
51525
+ import { homedir as homedir63 } from "node:os";
51526
+ import { dirname as dirname61, join as join108, resolve as resolve28 } from "node:path";
51527
+ import { fileURLToPath as fileURLToPath11 } from "node:url";
51191
51528
  var HOOK_BASENAMES = [
51192
51529
  "agentmemory-session-recall.js",
51193
51530
  "agentmemory-recall-trigger.mjs",
51194
51531
  "agentmemory-classify-queue.mjs"
51195
51532
  ];
51196
51533
  function defaultSourceDir() {
51197
- const here3 = dirname60(fileURLToPath10(import.meta.url));
51198
- const candidate = resolve27(here3, "..", "..", "..", "memory-service", "hooks");
51199
- if (existsSync110(candidate)) return candidate;
51200
- const srcCandidate = resolve27(here3, "..", "..", "..", "..", "memory-service", "hooks");
51201
- if (existsSync110(srcCandidate)) return srcCandidate;
51534
+ const here3 = dirname61(fileURLToPath11(import.meta.url));
51535
+ const candidate = resolve28(here3, "..", "..", "..", "memory-service", "hooks");
51536
+ if (existsSync112(candidate)) return candidate;
51537
+ const srcCandidate = resolve28(here3, "..", "..", "..", "..", "memory-service", "hooks");
51538
+ if (existsSync112(srcCandidate)) return srcCandidate;
51202
51539
  return candidate;
51203
51540
  }
51204
51541
  function installOne2(basename17, sourceDir, targetDir, opts) {
51205
- const sourcePath = join107(sourceDir, basename17);
51206
- const targetPath = join107(targetDir, basename17);
51207
- if (!existsSync110(sourcePath)) {
51542
+ const sourcePath = join108(sourceDir, basename17);
51543
+ const targetPath = join108(targetDir, basename17);
51544
+ if (!existsSync112(sourcePath)) {
51208
51545
  throw new Error(`canonical hook source missing at ${sourcePath} \u2014 olam install corrupt or sourceDir is wrong`);
51209
51546
  }
51210
- const newContent = readFileSync94(sourcePath, "utf8");
51211
- if (!existsSync110(targetPath)) {
51547
+ const newContent = readFileSync96(sourcePath, "utf8");
51548
+ if (!existsSync112(targetPath)) {
51212
51549
  if (opts.dryRun !== true) {
51213
- mkdirSync64(dirname60(targetPath), { recursive: true });
51214
- writeFileSync57(targetPath, newContent, { mode: 493 });
51550
+ mkdirSync65(dirname61(targetPath), { recursive: true });
51551
+ writeFileSync59(targetPath, newContent, { mode: 493 });
51215
51552
  }
51216
51553
  return { basename: basename17, action: "written", targetPath };
51217
51554
  }
51218
- const existing = readFileSync94(targetPath, "utf8");
51555
+ const existing = readFileSync96(targetPath, "utf8");
51219
51556
  if (existing === newContent) {
51220
51557
  return { basename: basename17, action: "unchanged", targetPath };
51221
51558
  }
@@ -51223,7 +51560,7 @@ function installOne2(basename17, sourceDir, targetDir, opts) {
51223
51560
  const backupPath = `${targetPath}.agentmemory-hook-backup-${Math.floor(Date.now() / 1e3)}`;
51224
51561
  if (opts.dryRun !== true) {
51225
51562
  copyFileSync12(targetPath, backupPath);
51226
- writeFileSync57(targetPath, newContent, { mode: 493 });
51563
+ writeFileSync59(targetPath, newContent, { mode: 493 });
51227
51564
  }
51228
51565
  return { basename: basename17, action: "force-overwritten", targetPath, backupPath };
51229
51566
  }
@@ -51238,13 +51575,13 @@ Add these hook entries to ~/.claude/settings.json:
51238
51575
  {
51239
51576
  "hooks": {
51240
51577
  "SessionStart": [
51241
- { "command": "node ${join107(targetDir, "agentmemory-session-recall.js")}" }
51578
+ { "command": "node ${join108(targetDir, "agentmemory-session-recall.js")}" }
51242
51579
  ],
51243
51580
  "PreToolUse": [
51244
- { "command": "node ${join107(targetDir, "agentmemory-recall-trigger.mjs")}" }
51581
+ { "command": "node ${join108(targetDir, "agentmemory-recall-trigger.mjs")}" }
51245
51582
  ],
51246
51583
  "PostToolUse": [
51247
- { "command": "node ${join107(targetDir, "agentmemory-classify-queue.mjs")}" }
51584
+ { "command": "node ${join108(targetDir, "agentmemory-classify-queue.mjs")}" }
51248
51585
  ]
51249
51586
  }
51250
51587
  }
@@ -51254,7 +51591,7 @@ If existing entries already point at the same paths, no edit needed.
51254
51591
  }
51255
51592
  function registerMemoryInstallHooks(parent) {
51256
51593
  parent.command("install-hooks").description("Install agentmemory hooks (PreToolUse + PostToolUse + SessionStart) to ~/.claude/scripts/hooks/").option("--force", "overwrite existing non-canonical files (backs them up to .agentmemory-hook-backup-<ts>)").option("--dry-run", "preview which hooks would be written without modifying disk").option("--target-dir <path>", "override target directory (default: ~/.claude/scripts/hooks/); for tests").option("--source-dir <path>", "override source directory (default: packages/memory-service/hooks/); for tests").action((opts) => {
51257
- const targetDir = opts.targetDir ?? join107(homedir62(), ".claude", "scripts", "hooks");
51594
+ const targetDir = opts.targetDir ?? join108(homedir63(), ".claude", "scripts", "hooks");
51258
51595
  const sourceDir = opts.sourceDir ?? defaultSourceDir();
51259
51596
  let written = 0;
51260
51597
  let unchanged = 0;
@@ -51330,7 +51667,7 @@ function registerMemory(program2) {
51330
51667
  // src/commands/kg-build.ts
51331
51668
  init_storage_paths();
51332
51669
  init_workspace_name();
51333
- import * as fs103 from "node:fs";
51670
+ import * as fs104 from "node:fs";
51334
51671
  import * as os57 from "node:os";
51335
51672
  import * as path102 from "node:path";
51336
51673
 
@@ -51424,11 +51761,11 @@ init_storage_paths();
51424
51761
  init_workspace_name();
51425
51762
  init_kg_caps();
51426
51763
  init_output();
51427
- import fs98 from "node:fs";
51428
- import { homedir as homedir63 } from "node:os";
51764
+ import fs99 from "node:fs";
51765
+ import { homedir as homedir64 } from "node:os";
51429
51766
  import path97 from "node:path";
51430
51767
  function olamHome5() {
51431
- return process.env.OLAM_HOME ?? path97.join(homedir63(), ".olam");
51768
+ return process.env.OLAM_HOME ?? path97.join(homedir64(), ".olam");
51432
51769
  }
51433
51770
  function kgRoot2() {
51434
51771
  return path97.join(olamHome5(), "kg");
@@ -51437,14 +51774,14 @@ function worldsRoot2() {
51437
51774
  return path97.join(olamHome5(), "worlds");
51438
51775
  }
51439
51776
  function dirSizeBytes2(dir) {
51440
- if (!fs98.existsSync(dir)) return 0;
51777
+ if (!fs99.existsSync(dir)) return 0;
51441
51778
  let total = 0;
51442
51779
  const stack = [dir];
51443
51780
  while (stack.length > 0) {
51444
51781
  const cur = stack.pop();
51445
51782
  let entries;
51446
51783
  try {
51447
- entries = fs98.readdirSync(cur, { withFileTypes: true });
51784
+ entries = fs99.readdirSync(cur, { withFileTypes: true });
51448
51785
  } catch {
51449
51786
  continue;
51450
51787
  }
@@ -51456,7 +51793,7 @@ function dirSizeBytes2(dir) {
51456
51793
  continue;
51457
51794
  }
51458
51795
  try {
51459
- total += fs98.statSync(full).size;
51796
+ total += fs99.statSync(full).size;
51460
51797
  } catch {
51461
51798
  }
51462
51799
  }
@@ -51471,9 +51808,9 @@ function formatBytes5(n) {
51471
51808
  }
51472
51809
  function readFreshness(workspace) {
51473
51810
  const file = path97.join(kgPristinePath(workspace), "freshness.json");
51474
- if (!fs98.existsSync(file)) return null;
51811
+ if (!fs99.existsSync(file)) return null;
51475
51812
  try {
51476
- const raw = JSON.parse(fs98.readFileSync(file, "utf-8"));
51813
+ const raw = JSON.parse(fs99.readFileSync(file, "utf-8"));
51477
51814
  if (raw && typeof raw === "object") return raw;
51478
51815
  return null;
51479
51816
  } catch {
@@ -51482,9 +51819,9 @@ function readFreshness(workspace) {
51482
51819
  }
51483
51820
  function readOverlayNodeCount(graphifyOutDir) {
51484
51821
  const graphPath = path97.join(graphifyOutDir, "graph.json");
51485
- if (!fs98.existsSync(graphPath)) return null;
51822
+ if (!fs99.existsSync(graphPath)) return null;
51486
51823
  try {
51487
- const raw = JSON.parse(fs98.readFileSync(graphPath, "utf-8"));
51824
+ const raw = JSON.parse(fs99.readFileSync(graphPath, "utf-8"));
51488
51825
  if (raw && typeof raw === "object") {
51489
51826
  const nodes = raw.nodes;
51490
51827
  if (Array.isArray(nodes)) return nodes.length;
@@ -51496,11 +51833,11 @@ function readOverlayNodeCount(graphifyOutDir) {
51496
51833
  }
51497
51834
  function listOverlays() {
51498
51835
  const root = worldsRoot2();
51499
- if (!fs98.existsSync(root)) return [];
51836
+ if (!fs99.existsSync(root)) return [];
51500
51837
  const records = [];
51501
51838
  let worldDirs;
51502
51839
  try {
51503
- worldDirs = fs98.readdirSync(root, { withFileTypes: true });
51840
+ worldDirs = fs99.readdirSync(root, { withFileTypes: true });
51504
51841
  } catch {
51505
51842
  return [];
51506
51843
  }
@@ -51510,14 +51847,14 @@ function listOverlays() {
51510
51847
  const worldDir = path97.join(root, worldId);
51511
51848
  let cloneDirs;
51512
51849
  try {
51513
- cloneDirs = fs98.readdirSync(worldDir, { withFileTypes: true });
51850
+ cloneDirs = fs99.readdirSync(worldDir, { withFileTypes: true });
51514
51851
  } catch {
51515
51852
  continue;
51516
51853
  }
51517
51854
  for (const cloneEntry of cloneDirs) {
51518
51855
  if (!cloneEntry.isDirectory()) continue;
51519
51856
  const graphifyOut = path97.join(worldDir, cloneEntry.name, "graphify-out");
51520
- if (!fs98.existsSync(graphifyOut)) continue;
51857
+ if (!fs99.existsSync(graphifyOut)) continue;
51521
51858
  records.push({
51522
51859
  world_id: worldId,
51523
51860
  clone_dir: cloneEntry.name,
@@ -51531,11 +51868,11 @@ function listOverlays() {
51531
51868
  }
51532
51869
  function listPristines(overlays) {
51533
51870
  const root = kgRoot2();
51534
- if (!fs98.existsSync(root)) return [];
51871
+ if (!fs99.existsSync(root)) return [];
51535
51872
  const records = [];
51536
51873
  let entries;
51537
51874
  try {
51538
- entries = fs98.readdirSync(root, { withFileTypes: true });
51875
+ entries = fs99.readdirSync(root, { withFileTypes: true });
51539
51876
  } catch {
51540
51877
  return [];
51541
51878
  }
@@ -51684,7 +52021,7 @@ init_storage_paths();
51684
52021
  init_workspace_name();
51685
52022
  init_output();
51686
52023
  import { spawn as spawn13 } from "node:child_process";
51687
- import fs99 from "node:fs";
52024
+ import fs100 from "node:fs";
51688
52025
  import path98 from "node:path";
51689
52026
  function pidFilePath2(workspace) {
51690
52027
  return path98.join(kgPristinePath(workspace), ".watch.pid");
@@ -51702,33 +52039,33 @@ function isPidAlive3(pid) {
51702
52039
  }
51703
52040
  function readAndClassifyPid(workspace) {
51704
52041
  const file = pidFilePath2(workspace);
51705
- if (!fs99.existsSync(file)) return { status: "no-pidfile", pid: null };
52042
+ if (!fs100.existsSync(file)) return { status: "no-pidfile", pid: null };
51706
52043
  let pid;
51707
52044
  try {
51708
- const raw = fs99.readFileSync(file, "utf-8").trim();
52045
+ const raw = fs100.readFileSync(file, "utf-8").trim();
51709
52046
  pid = Number.parseInt(raw, 10);
51710
52047
  } catch {
51711
- fs99.rmSync(file, { force: true });
52048
+ fs100.rmSync(file, { force: true });
51712
52049
  return { status: "stale-reclaimed", pid: null };
51713
52050
  }
51714
52051
  if (!Number.isInteger(pid) || pid <= 0) {
51715
- fs99.rmSync(file, { force: true });
52052
+ fs100.rmSync(file, { force: true });
51716
52053
  return { status: "stale-reclaimed", pid: null };
51717
52054
  }
51718
52055
  if (isPidAlive3(pid)) return { status: "active", pid };
51719
- fs99.rmSync(file, { force: true });
52056
+ fs100.rmSync(file, { force: true });
51720
52057
  return { status: "stale-reclaimed", pid: null };
51721
52058
  }
51722
52059
  function writePidFile2(workspace, pid) {
51723
52060
  const file = pidFilePath2(workspace);
51724
52061
  const dir = path98.dirname(file);
51725
- fs99.mkdirSync(dir, { recursive: true });
51726
- fs99.writeFileSync(file, String(pid), { encoding: "utf-8" });
52062
+ fs100.mkdirSync(dir, { recursive: true });
52063
+ fs100.writeFileSync(file, String(pid), { encoding: "utf-8" });
51727
52064
  }
51728
52065
  function removePidFile(workspace) {
51729
52066
  const file = pidFilePath2(workspace);
51730
52067
  try {
51731
- fs99.rmSync(file, { force: true });
52068
+ fs100.rmSync(file, { force: true });
51732
52069
  } catch {
51733
52070
  }
51734
52071
  }
@@ -51782,16 +52119,16 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
51782
52119
  process.on("SIGINT", () => forward("SIGINT"));
51783
52120
  process.on("SIGTERM", () => forward("SIGTERM"));
51784
52121
  }
51785
- return new Promise((resolve30) => {
52122
+ return new Promise((resolve31) => {
51786
52123
  child.on("exit", (code, signal) => {
51787
52124
  removePidFile(name);
51788
52125
  const exitCode = typeof code === "number" ? code : signal === "SIGINT" || signal === "SIGTERM" ? 0 : 1;
51789
- resolve30({ exitCode, pidWritten: true });
52126
+ resolve31({ exitCode, pidWritten: true });
51790
52127
  });
51791
52128
  child.on("error", (err) => {
51792
52129
  removePidFile(name);
51793
52130
  printError(`graphify subprocess error: ${err.message}`);
51794
- resolve30({ exitCode: 1, pidWritten: true });
52131
+ resolve31({ exitCode: 1, pidWritten: true });
51795
52132
  });
51796
52133
  });
51797
52134
  }
@@ -52055,7 +52392,7 @@ function registerKgDoctorCommand(kg) {
52055
52392
  init_merge_settings();
52056
52393
  init_hook_template2();
52057
52394
  init_output();
52058
- import * as fs100 from "node:fs";
52395
+ import * as fs101 from "node:fs";
52059
52396
  import * as path99 from "node:path";
52060
52397
  import * as os54 from "node:os";
52061
52398
  import { parse as yamlParse3, stringify as yamlStringify4 } from "yaml";
@@ -52066,10 +52403,10 @@ function settingsPathFor2(scope) {
52066
52403
  return path99.join(process.cwd(), ".claude", "settings.json");
52067
52404
  }
52068
52405
  function backup2(filePath) {
52069
- if (!fs100.existsSync(filePath)) return null;
52406
+ if (!fs101.existsSync(filePath)) return null;
52070
52407
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
52071
52408
  const backupPath = `${filePath}.olam-bak.${ts}`;
52072
- fs100.copyFileSync(filePath, backupPath);
52409
+ fs101.copyFileSync(filePath, backupPath);
52073
52410
  return backupPath;
52074
52411
  }
52075
52412
  var HERMES_HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
@@ -52081,7 +52418,7 @@ function hermesHooksDir() {
52081
52418
  }
52082
52419
  function patchHermesConfigForHook(action) {
52083
52420
  const configPath = hermesConfigPath2();
52084
- const raw = fs100.readFileSync(configPath, "utf-8");
52421
+ const raw = fs101.readFileSync(configPath, "utf-8");
52085
52422
  const config = yamlParse3(raw);
52086
52423
  const hooks = config["hooks"] ?? {};
52087
52424
  const preToolCall = Array.isArray(hooks["pre_tool_call"]) ? hooks["pre_tool_call"] : [];
@@ -52100,7 +52437,7 @@ function patchHermesConfigForHook(action) {
52100
52437
  hooks: { ...hooks, pre_tool_call: [...preToolCall, entry] },
52101
52438
  hooks_auto_accept: true
52102
52439
  };
52103
- fs100.writeFileSync(configPath, yamlStringify4(updated2), "utf-8");
52440
+ fs101.writeFileSync(configPath, yamlStringify4(updated2), "utf-8");
52104
52441
  return "patched";
52105
52442
  }
52106
52443
  const filtered = preToolCall.filter(
@@ -52111,12 +52448,12 @@ function patchHermesConfigForHook(action) {
52111
52448
  ...config,
52112
52449
  hooks: { ...hooks, pre_tool_call: filtered }
52113
52450
  };
52114
- fs100.writeFileSync(configPath, yamlStringify4(updated), "utf-8");
52451
+ fs101.writeFileSync(configPath, yamlStringify4(updated), "utf-8");
52115
52452
  return "patched";
52116
52453
  }
52117
52454
  function doInstallForHermes() {
52118
52455
  const configPath = hermesConfigPath2();
52119
- if (!fs100.existsSync(configPath)) {
52456
+ if (!fs101.existsSync(configPath)) {
52120
52457
  printError(`~/.hermes/config.yaml not found at ${configPath}`);
52121
52458
  printInfo("remedy", "Install Hermes first, then re-run `olam kg install-hook --for hermes`");
52122
52459
  process.exitCode = 1;
@@ -52146,15 +52483,15 @@ function doUninstallForHermes() {
52146
52483
  const hooksDir = hermesHooksDir();
52147
52484
  const hookScriptPath = path99.join(hooksDir, "kg-first.sh");
52148
52485
  let scriptRemoved = false;
52149
- if (fs100.existsSync(hookScriptPath)) {
52150
- const content = fs100.readFileSync(hookScriptPath, "utf-8");
52486
+ if (fs101.existsSync(hookScriptPath)) {
52487
+ const content = fs101.readFileSync(hookScriptPath, "utf-8");
52151
52488
  if (content.includes(HERMES_KG_HOOK_SENTINEL)) {
52152
- fs100.unlinkSync(hookScriptPath);
52489
+ fs101.unlinkSync(hookScriptPath);
52153
52490
  scriptRemoved = true;
52154
52491
  }
52155
52492
  }
52156
52493
  let configPatched = false;
52157
- if (fs100.existsSync(configPath)) {
52494
+ if (fs101.existsSync(configPath)) {
52158
52495
  const result = patchHermesConfigForHook("uninstall");
52159
52496
  configPatched = result === "patched";
52160
52497
  }
@@ -52179,7 +52516,7 @@ function registerKgInstallHookCommand(kg) {
52179
52516
  const scope = opts.scope === "user" ? "user" : "project";
52180
52517
  const filePath = settingsPathFor2(scope);
52181
52518
  try {
52182
- fs100.mkdirSync(path99.dirname(filePath), { recursive: true });
52519
+ fs101.mkdirSync(path99.dirname(filePath), { recursive: true });
52183
52520
  } catch (err) {
52184
52521
  printError(`could not create ${path99.dirname(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
52185
52522
  process.exitCode = 1;
@@ -52205,7 +52542,7 @@ function registerKgInstallHookCommand(kg) {
52205
52542
  printInfo("kg-service hook", `already installed at ${filePath}`);
52206
52543
  if (backupPath) {
52207
52544
  try {
52208
- fs100.unlinkSync(backupPath);
52545
+ fs101.unlinkSync(backupPath);
52209
52546
  } catch {
52210
52547
  }
52211
52548
  }
@@ -52225,7 +52562,7 @@ function registerKgInstallHookCommand(kg) {
52225
52562
  // src/commands/kg-uninstall-hook.ts
52226
52563
  init_hook_template2();
52227
52564
  init_output();
52228
- import * as fs101 from "node:fs";
52565
+ import * as fs102 from "node:fs";
52229
52566
  import * as path100 from "node:path";
52230
52567
  import * as os55 from "node:os";
52231
52568
  function settingsPathFor3(scope) {
@@ -52262,13 +52599,13 @@ function registerKgUninstallHookCommand(kg) {
52262
52599
  kg.command("uninstall-hook").description("Remove kg-service PreToolUse hook from .claude/settings.json (sentinel-matched; surgical)").option("--scope <scope>", "project (default) or user", "project").action((opts) => {
52263
52600
  const scope = opts.scope === "user" ? "user" : "project";
52264
52601
  const filePath = settingsPathFor3(scope);
52265
- if (!fs101.existsSync(filePath)) {
52602
+ if (!fs102.existsSync(filePath)) {
52266
52603
  printInfo("kg-service hook", `no settings.json at ${filePath} \u2014 nothing to remove`);
52267
52604
  return;
52268
52605
  }
52269
52606
  let settings;
52270
52607
  try {
52271
- const raw = fs101.readFileSync(filePath, "utf-8");
52608
+ const raw = fs102.readFileSync(filePath, "utf-8");
52272
52609
  settings = raw.trim() ? JSON.parse(raw) : {};
52273
52610
  } catch (err) {
52274
52611
  printError(`could not parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
@@ -52288,7 +52625,7 @@ function registerKgUninstallHookCommand(kg) {
52288
52625
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
52289
52626
  const backupPath = `${filePath}.olam-bak.${ts}`;
52290
52627
  try {
52291
- fs101.copyFileSync(filePath, backupPath);
52628
+ fs102.copyFileSync(filePath, backupPath);
52292
52629
  } catch {
52293
52630
  }
52294
52631
  const next = {
@@ -52307,7 +52644,7 @@ function registerKgUninstallHookCommand(kg) {
52307
52644
  }
52308
52645
  }
52309
52646
  try {
52310
- fs101.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
52647
+ fs102.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
52311
52648
  printSuccess(`kg-service hook removed from ${filePath}`);
52312
52649
  printInfo("backup", backupPath);
52313
52650
  } catch (err) {
@@ -52380,7 +52717,7 @@ function registerKgSavingsCommand(kg) {
52380
52717
 
52381
52718
  // src/commands/kg-mirror.ts
52382
52719
  init_output();
52383
- import * as fs102 from "node:fs";
52720
+ import * as fs103 from "node:fs";
52384
52721
  import * as os56 from "node:os";
52385
52722
  import * as path101 from "node:path";
52386
52723
  function readEnvOrFile(envVar, fileName) {
@@ -52388,7 +52725,7 @@ function readEnvOrFile(envVar, fileName) {
52388
52725
  if (fromEnv && fromEnv.length > 0) return fromEnv.trim();
52389
52726
  try {
52390
52727
  const file = path101.join(os56.homedir(), ".olam", fileName);
52391
- const content = fs102.readFileSync(file, "utf-8").trim();
52728
+ const content = fs103.readFileSync(file, "utf-8").trim();
52392
52729
  if (content.length > 0) return content;
52393
52730
  } catch {
52394
52731
  }
@@ -52568,6 +52905,76 @@ async function runKgMirrorClassify(question, options = {}) {
52568
52905
  printInfo("est. savings", `~${Math.round(Number(savings2) / 1e3)}k tokens`);
52569
52906
  return { exitCode: 0 };
52570
52907
  }
52908
+ async function runKgMirrorGraph(symbol, options = {}) {
52909
+ const cfg = resolveClassifier();
52910
+ if (!cfg) {
52911
+ printError(
52912
+ "kg-mirror URL/bearer not configured. Set OLAM_KG_PROXY_URL + OLAM_KG_PROXY_BEARER (or ~/.olam/kg-proxy-url + ~/.olam/kg-proxy-bearer)."
52913
+ );
52914
+ return { exitCode: 3 };
52915
+ }
52916
+ if (!options.workspace) {
52917
+ printError("graph query needs a --workspace (e.g. --workspace atlas-one).");
52918
+ return { exitCode: 2 };
52919
+ }
52920
+ const sym = (symbol ?? "").trim();
52921
+ if (!sym && !options.repo) {
52922
+ printError("provide a <symbol> to search, and/or --repo <name> to browse a repo.");
52923
+ return { exitCode: 2 };
52924
+ }
52925
+ const mode = options.relates ? "relates" : "where";
52926
+ const body = { workspace: options.workspace, symbol: sym, mode };
52927
+ if (options.repo) body.repo = options.repo;
52928
+ if (options.limit) {
52929
+ const n = Number.parseInt(options.limit, 10);
52930
+ if (Number.isFinite(n) && n > 0) body.limit = n;
52931
+ }
52932
+ let res;
52933
+ try {
52934
+ res = await fetch(`${cfg.url}/v1/graph`, {
52935
+ method: "POST",
52936
+ headers: { Authorization: `Bearer ${cfg.bearer}`, "Content-Type": "application/json" },
52937
+ body: JSON.stringify(body)
52938
+ });
52939
+ } catch (err) {
52940
+ printError(`kg-mirror unreachable: ${err instanceof Error ? err.message : String(err)}`);
52941
+ return { exitCode: 4 };
52942
+ }
52943
+ const text = await res.text();
52944
+ if (options.json) {
52945
+ process.stdout.write(text + "\n");
52946
+ return { exitCode: res.ok ? 0 : 1 };
52947
+ }
52948
+ let j;
52949
+ try {
52950
+ j = JSON.parse(text);
52951
+ } catch {
52952
+ printError(`kg-mirror returned non-JSON (HTTP ${res.status}): ${text.slice(0, 200)}`);
52953
+ return { exitCode: 1 };
52954
+ }
52955
+ if (!res.ok) {
52956
+ printError(`graph /v1/graph failed (HTTP ${res.status}): ${j.error ?? "?"}`);
52957
+ if (j.detail) printInfo("detail", String(j.detail));
52958
+ return { exitCode: 1 };
52959
+ }
52960
+ const matched = j.matched ?? [];
52961
+ printInfo("graph", `${options.workspace} \xB7 ${mode} \xB7 "${symbol}"`);
52962
+ if (matched.length === 0) {
52963
+ printInfo("matched", "no nodes match that symbol");
52964
+ }
52965
+ for (const m of matched) {
52966
+ printSuccess(`${m.label} ${m.file}:${String(m.loc ?? "").replace(/^L/, "")}`);
52967
+ }
52968
+ if (mode === "relates") {
52969
+ const relates = j.relates ?? [];
52970
+ for (const e of relates) {
52971
+ const arrow = e.direction === "out" ? "\u2192" : "\u2190";
52972
+ printInfo(String(e.relation), `${arrow} ${e.label} (${e.file})`);
52973
+ }
52974
+ }
52975
+ if (j.truncated) printInfo("note", "results truncated \u2014 pass --limit to widen");
52976
+ return { exitCode: 0 };
52977
+ }
52571
52978
  function guessGitUrl(workspace) {
52572
52979
  try {
52573
52980
  const { spawnSync: spawnSync35 } = __require("node:child_process");
@@ -52578,7 +52985,7 @@ function guessGitUrl(workspace) {
52578
52985
  path101.join(os56.homedir(), "Projects", workspace)
52579
52986
  ];
52580
52987
  for (const dir of candidates2) {
52581
- if (!fs102.existsSync(path101.join(dir, ".git"))) continue;
52988
+ if (!fs103.existsSync(path101.join(dir, ".git"))) continue;
52582
52989
  const r = spawnSync35("git", ["-C", dir, "remote", "get-url", "origin"], {
52583
52990
  encoding: "utf-8"
52584
52991
  });
@@ -52607,12 +53014,16 @@ function registerKgMirrorCommand(kg) {
52607
53014
  const r = await runKgMirrorClassify(question, opts);
52608
53015
  if (r.exitCode !== 0) process.exitCode = r.exitCode;
52609
53016
  });
53017
+ mirror.command("graph").description("Query the cross-repo graph: locate a symbol, its relationships, or browse a repo (POST /v1/graph)").argument("[symbol]", "symbol/label to look up (e.g. UserService); omit with --repo to browse a repo").requiredOption("--workspace <name>", "workspace to query (e.g. atlas-one)").option("--repo <name>", "scope to / browse a submodule by path prefix (e.g. diner-app)").option("--relates", "return relationships (calls/imports/contains) instead of just locations").option("--limit <n>", "max results (default 50)").option("--json", "emit raw JSON response").action(async (symbol, opts) => {
53018
+ const r = await runKgMirrorGraph(symbol, opts);
53019
+ if (r.exitCode !== 0) process.exitCode = r.exitCode;
53020
+ });
52610
53021
  }
52611
53022
 
52612
53023
  // src/commands/kg-build.ts
52613
53024
  function readQueueFromDisk(queuePath) {
52614
- if (!fs103.existsSync(queuePath)) return [];
52615
- const raw = fs103.readFileSync(queuePath, "utf-8");
53025
+ if (!fs104.existsSync(queuePath)) return [];
53026
+ const raw = fs104.readFileSync(queuePath, "utf-8");
52616
53027
  const entries = [];
52617
53028
  for (const line of raw.split("\n")) {
52618
53029
  const t = line.trim();
@@ -52625,9 +53036,9 @@ function readQueueFromDisk(queuePath) {
52625
53036
  return entries;
52626
53037
  }
52627
53038
  function writeQueueToDisk(queuePath, entries) {
52628
- fs103.mkdirSync(path102.dirname(queuePath), { recursive: true });
53039
+ fs104.mkdirSync(path102.dirname(queuePath), { recursive: true });
52629
53040
  const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
52630
- fs103.writeFileSync(queuePath, content, "utf-8");
53041
+ fs104.writeFileSync(queuePath, content, "utf-8");
52631
53042
  }
52632
53043
  async function runKgBuildPending(opts = {}) {
52633
53044
  const queuePath = opts.queuePath ?? (() => {
@@ -52717,7 +53128,7 @@ async function runKgBuild(workspaceArg, options = {}) {
52717
53128
  return { exitCode: 2 };
52718
53129
  }
52719
53130
  const outDir = kgPristinePath(workspace.name);
52720
- fs103.mkdirSync(outDir, { recursive: true });
53131
+ fs104.mkdirSync(outDir, { recursive: true });
52721
53132
  const human = !options.json;
52722
53133
  if (human) {
52723
53134
  printInfo("kg build", `workspace=${workspace.name} source=${workspace.sourcePath}`);
@@ -52750,7 +53161,7 @@ async function runKgBuild(workspaceArg, options = {}) {
52750
53161
  workspace: workspace.name,
52751
53162
  graphify_path: "container"
52752
53163
  };
52753
- fs103.writeFileSync(
53164
+ fs104.writeFileSync(
52754
53165
  path102.join(outDir, "freshness.json"),
52755
53166
  JSON.stringify(freshness, null, 2) + "\n",
52756
53167
  "utf-8"
@@ -52797,13 +53208,13 @@ function registerKg(program2) {
52797
53208
 
52798
53209
  // src/commands/flywheel/emit-breadcrumb.ts
52799
53210
  init_file_lock();
52800
- import { mkdirSync as mkdirSync67, appendFileSync as appendFileSync6 } from "node:fs";
52801
- import { homedir as homedir68 } from "node:os";
52802
- import { dirname as dirname64, join as join112 } from "node:path";
53211
+ import { mkdirSync as mkdirSync68, appendFileSync as appendFileSync6 } from "node:fs";
53212
+ import { homedir as homedir69 } from "node:os";
53213
+ import { dirname as dirname65, join as join113 } from "node:path";
52803
53214
  import { randomUUID as randomUUID4 } from "node:crypto";
52804
53215
  var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info", "warn"]);
52805
53216
  var PROMPT_FEEDING_FIELDS = ["extracted_pattern", "severity", "affected_persona", "proposed_edit"];
52806
- var BREADCRUMBS_BASE = join112(homedir68(), ".local", "share", "claude", "breadcrumbs");
53217
+ var BREADCRUMBS_BASE = join113(homedir69(), ".local", "share", "claude", "breadcrumbs");
52807
53218
  var LOCK_FILENAME = ".flywheel-emit.lock";
52808
53219
  function buildRecord(opts) {
52809
53220
  const rec = {
@@ -52850,7 +53261,7 @@ function validatePromptFeeding(rec) {
52850
53261
  }
52851
53262
  function destPath(projectSlug) {
52852
53263
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
52853
- return join112(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
53264
+ return join113(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
52854
53265
  }
52855
53266
  async function emitBreadcrumb(opts) {
52856
53267
  if (!VALID_SEVERITIES.has(opts.severity)) {
@@ -52870,8 +53281,8 @@ async function emitBreadcrumb(opts) {
52870
53281
  process.exit(2);
52871
53282
  }
52872
53283
  const path106 = destPath(rec.project_slug);
52873
- const lockDir = dirname64(path106);
52874
- mkdirSync67(lockDir, { recursive: true });
53284
+ const lockDir = dirname65(path106);
53285
+ mkdirSync68(lockDir, { recursive: true });
52875
53286
  const line = JSON.stringify(rec) + "\n";
52876
53287
  await withFileLock(
52877
53288
  lockDir,
@@ -52951,7 +53362,7 @@ function registerFlywheelK5Score(parent) {
52951
53362
  }
52952
53363
 
52953
53364
  // src/commands/flywheel/k5-validate.ts
52954
- import { readFileSync as readFileSync99, statSync as statSync31 } from "node:fs";
53365
+ import { readFileSync as readFileSync101, statSync as statSync31 } from "node:fs";
52955
53366
  import { parse as parseYAML } from "yaml";
52956
53367
  var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
52957
53368
  var MAX_PLAN_BYTES = 1048576;
@@ -53033,7 +53444,7 @@ function validatePlan(path106) {
53033
53444
  }
53034
53445
  let text;
53035
53446
  try {
53036
- text = readFileSync99(path106, "utf8");
53447
+ text = readFileSync101(path106, "utf8");
53037
53448
  } catch (err) {
53038
53449
  const m = `FAIL cannot read ${path106}: ${err instanceof Error ? err.message : "unknown"}`;
53039
53450
  return { ok: false, message: m, json: emptyJson("error", [m]) };
@@ -53157,7 +53568,7 @@ function registerFlywheelK5Validate(parent) {
53157
53568
  }
53158
53569
 
53159
53570
  // src/commands/flywheel/k10-measure.ts
53160
- import { readFileSync as readFileSync100 } from "node:fs";
53571
+ import { readFileSync as readFileSync102 } from "node:fs";
53161
53572
 
53162
53573
  // ../core/dist/lib/k10-budget.js
53163
53574
  var K10_TOKEN_CAP = 5500;
@@ -53214,7 +53625,7 @@ function registerFlywheelK10Measure(parent) {
53214
53625
  parent.command("k10-measure").description("Measure K10 token budget for upstream + optional overlay; emit PASS/REJECT verdict").requiredOption("--upstream <path>", "path to upstream file (e.g. persona prompt)").option("--overlay <path>", "path to overlay file (omit if none \u2014 PASS without enforcement)").option("--json", "emit verdict as JSON instead of human-readable").action((opts) => {
53215
53626
  let upstreamText;
53216
53627
  try {
53217
- upstreamText = readFileSync100(opts.upstream, "utf8");
53628
+ upstreamText = readFileSync102(opts.upstream, "utf8");
53218
53629
  } catch (err) {
53219
53630
  process.stderr.write(
53220
53631
  `[k10-measure-error] cannot read upstream ${opts.upstream}: ${err instanceof Error ? err.message : "unknown"}
@@ -53226,7 +53637,7 @@ function registerFlywheelK10Measure(parent) {
53226
53637
  let overlayTokens = null;
53227
53638
  if (opts.overlay !== void 0) {
53228
53639
  try {
53229
- const overlayText = readFileSync100(opts.overlay, "utf8");
53640
+ const overlayText = readFileSync102(opts.overlay, "utf8");
53230
53641
  overlayTokens = tokensFromText(overlayText);
53231
53642
  } catch (err) {
53232
53643
  process.stderr.write(
@@ -53260,13 +53671,13 @@ function registerFlywheelK10Measure(parent) {
53260
53671
  }
53261
53672
 
53262
53673
  // src/commands/flywheel/check-persona-skeleton.ts
53263
- import { existsSync as existsSync115, readFileSync as readFileSync101, statSync as statSync32 } from "node:fs";
53264
- import { homedir as homedir69 } from "node:os";
53265
- import { basename as basename14, join as join113 } from "node:path";
53674
+ import { existsSync as existsSync117, readFileSync as readFileSync103, statSync as statSync32 } from "node:fs";
53675
+ import { homedir as homedir70 } from "node:os";
53676
+ import { basename as basename14, join as join114 } from "node:path";
53266
53677
  import { parse as parseYAML2 } from "yaml";
53267
53678
  var CHARS_PER_TOKEN3 = 4;
53268
53679
  var K10_TOKEN_CAP2 = 6e3;
53269
- var AGENTS_DIR = join113(homedir69(), ".claude", "agents");
53680
+ var AGENTS_DIR = join114(homedir70(), ".claude", "agents");
53270
53681
  var REQUIRED_FRONTMATTER_KEYS = ["name", "description", "allowed-tools"];
53271
53682
  var REQUIRED_SECTIONS = [
53272
53683
  "## Role",
@@ -53306,10 +53717,10 @@ function countNamedPatterns(sectionText) {
53306
53717
  return Math.max(h3Count, bulletCount);
53307
53718
  }
53308
53719
  function checkFile(filepath) {
53309
- if (!existsSync115(filepath) || !statSync32(filepath).isFile()) {
53720
+ if (!existsSync117(filepath) || !statSync32(filepath).isFile()) {
53310
53721
  return { passed: false, failures: [`file not found: ${filepath}`], tokens: 0, mergedSkipped: false };
53311
53722
  }
53312
- const text = readFileSync101(filepath, "utf8");
53723
+ const text = readFileSync103(filepath, "utf8");
53313
53724
  const { fm, body } = parseFile(text);
53314
53725
  const failures = [];
53315
53726
  for (const key of REQUIRED_FRONTMATTER_KEYS) {
@@ -53322,8 +53733,8 @@ function checkFile(filepath) {
53322
53733
  const agentName = typeof fm.name === "string" ? fm.name : "";
53323
53734
  let mergedSkipped = false;
53324
53735
  if (!isNewAgent && agentName !== "") {
53325
- const upstreamPath = join113(AGENTS_DIR, `${agentName}.md`);
53326
- if (existsSync115(upstreamPath)) {
53736
+ const upstreamPath = join114(AGENTS_DIR, `${agentName}.md`);
53737
+ if (existsSync117(upstreamPath)) {
53327
53738
  mergedSkipped = true;
53328
53739
  }
53329
53740
  }
@@ -53375,7 +53786,7 @@ Results: ${passCount} passed, ${failCount} failed
53375
53786
  }
53376
53787
 
53377
53788
  // src/commands/flywheel/diversity-check.ts
53378
- import { readFileSync as readFileSync102 } from "node:fs";
53789
+ import { readFileSync as readFileSync104 } from "node:fs";
53379
53790
  import { basename as basename15 } from "node:path";
53380
53791
  import { globSync as globSync2 } from "node:fs";
53381
53792
 
@@ -53455,7 +53866,7 @@ function formatRedivergencePrompt(personaA, personaB, score, drifted, revisionCo
53455
53866
  ` jaccard: ${score.toFixed(3)} (threshold: ${threshold})`,
53456
53867
  ` drifted: ${driftedName}`,
53457
53868
  "",
53458
- ` Suggestion for next /10x:learn revision of ${driftedName}:`,
53869
+ ` Suggestion for next /100x:learn revision of ${driftedName}:`,
53459
53870
  ` ADD content that reinforces ${driftedName}'s historically-owned cognitive patterns.`,
53460
53871
  ` DO NOT remove shared content \u2014 removing shared boilerplate lowers Jaccard arithmetically`,
53461
53872
  ` but does not restore identity differentiation.`,
@@ -53485,7 +53896,7 @@ function registerFlywheelDiversityCheck(parent) {
53485
53896
  const personas = /* @__PURE__ */ new Map();
53486
53897
  for (const filepath of files) {
53487
53898
  try {
53488
- const body = readFileSync102(filepath, "utf8");
53899
+ const body = readFileSync104(filepath, "utf8");
53489
53900
  if (body.trim().length > 0) {
53490
53901
  personas.set(basename15(filepath, ".md"), body);
53491
53902
  }
@@ -53516,9 +53927,9 @@ ${formatRedivergencePrompt(persona_a, persona_b, score, void 0, void 0, threshol
53516
53927
  }
53517
53928
 
53518
53929
  // src/commands/flywheel/ping.ts
53519
- import { mkdirSync as mkdirSync68, writeFileSync as writeFileSync61 } from "node:fs";
53520
- import { homedir as homedir70 } from "node:os";
53521
- import { dirname as dirname65, join as join114 } from "node:path";
53930
+ import { mkdirSync as mkdirSync69, writeFileSync as writeFileSync63 } from "node:fs";
53931
+ import { homedir as homedir71 } from "node:os";
53932
+ import { dirname as dirname66, join as join115 } from "node:path";
53522
53933
  var COLD_START_BUDGET_GOOD_MS = 200;
53523
53934
  var COLD_START_BUDGET_FAIR_MS = 500;
53524
53935
  function classifyColdStart(coldStartMs) {
@@ -53534,9 +53945,9 @@ function readOlamVersion() {
53534
53945
  }
53535
53946
  }
53536
53947
  function writeBaseline(record) {
53537
- const baselinePath = join114(homedir70(), ".local", "share", "olam", "flywheel-baseline.json");
53538
- mkdirSync68(dirname65(baselinePath), { recursive: true });
53539
- writeFileSync61(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
53948
+ const baselinePath = join115(homedir71(), ".local", "share", "olam", "flywheel-baseline.json");
53949
+ mkdirSync69(dirname66(baselinePath), { recursive: true });
53950
+ writeFileSync63(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
53540
53951
  return baselinePath;
53541
53952
  }
53542
53953
  function registerFlywheelPing(parent) {
@@ -53576,16 +53987,16 @@ init_skill_sources();
53576
53987
  init_prefix_rules();
53577
53988
  import {
53578
53989
  copyFileSync as copyFileSync15,
53579
- existsSync as existsSync116,
53580
- mkdirSync as mkdirSync69,
53581
- readFileSync as readFileSync103,
53990
+ existsSync as existsSync118,
53991
+ mkdirSync as mkdirSync70,
53992
+ readFileSync as readFileSync105,
53582
53993
  readdirSync as readdirSync33,
53583
53994
  statSync as statSync33,
53584
- writeFileSync as writeFileSync62
53995
+ writeFileSync as writeFileSync64
53585
53996
  } from "node:fs";
53586
53997
  import { spawnSync as spawnSync32 } from "node:child_process";
53587
- import { homedir as homedir71 } from "node:os";
53588
- import { dirname as dirname66, join as join115, relative as relative7 } from "node:path";
53998
+ import { homedir as homedir72 } from "node:os";
53999
+ import { dirname as dirname67, join as join116, relative as relative7 } from "node:path";
53589
54000
  function escapeRegex(s) {
53590
54001
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
53591
54002
  }
@@ -53622,7 +54033,7 @@ function walkOverlayFiles(dir) {
53622
54033
  return [];
53623
54034
  }
53624
54035
  for (const entry of entries) {
53625
- const fullPath = join115(dir, entry);
54036
+ const fullPath = join116(dir, entry);
53626
54037
  let stat;
53627
54038
  try {
53628
54039
  stat = statSync33(fullPath);
@@ -53661,10 +54072,10 @@ function resolveAtlasUser2(opts) {
53661
54072
  assertValidAtlasUser(v);
53662
54073
  return v;
53663
54074
  }
53664
- const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join115(homedir71(), ".claude");
53665
- const f = join115(claudeDir2, ".atlas-user");
53666
- if (existsSync116(f)) {
53667
- const v = readFileSync103(f, "utf-8").trim();
54075
+ const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join116(homedir72(), ".claude");
54076
+ const f = join116(claudeDir2, ".atlas-user");
54077
+ if (existsSync118(f)) {
54078
+ const v = readFileSync105(f, "utf-8").trim();
53668
54079
  if (v.length === 0) return null;
53669
54080
  assertValidAtlasUser(v);
53670
54081
  return v;
@@ -53686,8 +54097,8 @@ function runGit2(args, cwd) {
53686
54097
  function walkPushSourceFiles(claudeDir2) {
53687
54098
  const result = [];
53688
54099
  const roots = [
53689
- { dir: join115(claudeDir2, "skills.overrides"), overlayKind: "skills" },
53690
- { dir: join115(claudeDir2, "agents.overrides"), overlayKind: "agents" }
54100
+ { dir: join116(claudeDir2, "skills.overrides"), overlayKind: "skills" },
54101
+ { dir: join116(claudeDir2, "agents.overrides"), overlayKind: "agents" }
53691
54102
  ];
53692
54103
  for (const { dir, overlayKind } of roots) {
53693
54104
  const files = walkOverlayFiles(dir);
@@ -53798,7 +54209,7 @@ function pushOverlays(opts) {
53798
54209
  Run \`olam skills atlas-user set <name>\` to configure your atlas user.`
53799
54210
  );
53800
54211
  }
53801
- const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join115(homedir71(), ".claude");
54212
+ const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join116(homedir72(), ".claude");
53802
54213
  const sourceFiles = walkPushSourceFiles(claudeDir2);
53803
54214
  const registeredPrefixes = (opts._testSkillSources ?? listSkillSources()).map((s) => s.prefix).filter((p) => typeof p === "string" && p.length > 0);
53804
54215
  if (registeredPrefixes.length > 0) {
@@ -53806,7 +54217,7 @@ function pushOverlays(opts) {
53806
54217
  const basename17 = relPath.split("/").pop() ?? relPath;
53807
54218
  let content;
53808
54219
  try {
53809
- content = readFileSync103(srcFile);
54220
+ content = readFileSync105(srcFile);
53810
54221
  } catch {
53811
54222
  continue;
53812
54223
  }
@@ -53845,21 +54256,21 @@ function pushOverlays(opts) {
53845
54256
  ` + preflightWarnings.map((w) => ` - ${w.split("\n")[0]}`).join("\n") + "\n"
53846
54257
  );
53847
54258
  }
53848
- const membersBase2 = join115(clonePath, "members", atlasUser);
54259
+ const membersBase2 = join116(clonePath, "members", atlasUser);
53849
54260
  let wouldCopy = 0;
53850
54261
  let wouldUnchange = 0;
53851
54262
  let wouldCreate = 0;
53852
54263
  for (const { srcFile, overlayKind, relPath } of sourceFiles) {
53853
- const targetDir = join115(membersBase2, `${overlayKind}.overrides`);
53854
- const targetFile = join115(targetDir, relPath);
54264
+ const targetDir = join116(membersBase2, `${overlayKind}.overrides`);
54265
+ const targetFile = join116(targetDir, relPath);
53855
54266
  let srcBuf;
53856
54267
  try {
53857
- srcBuf = readFileSync103(srcFile);
54268
+ srcBuf = readFileSync105(srcFile);
53858
54269
  } catch {
53859
54270
  continue;
53860
54271
  }
53861
- if (existsSync116(targetFile)) {
53862
- const dstBuf = readFileSync103(targetFile);
54272
+ if (existsSync118(targetFile)) {
54273
+ const dstBuf = readFileSync105(targetFile);
53863
54274
  if (srcBuf.equals(dstBuf)) {
53864
54275
  wouldUnchange += 1;
53865
54276
  process.stdout.write(` [skip] ${overlayKind}.overrides/${relPath} (unchanged)
@@ -53900,32 +54311,32 @@ function pushOverlays(opts) {
53900
54311
  `failed to create branch "${branchName}": ${err instanceof Error ? err.message : String(err)}`
53901
54312
  );
53902
54313
  }
53903
- const membersBase = join115(clonePath, "members", atlasUser);
54314
+ const membersBase = join116(clonePath, "members", atlasUser);
53904
54315
  let filesCopied = 0;
53905
54316
  let filesUnchanged = 0;
53906
54317
  let filesCreated = 0;
53907
54318
  try {
53908
54319
  for (const { srcFile, overlayKind, relPath } of sourceFiles) {
53909
- const targetDir = join115(membersBase, `${overlayKind}.overrides`, dirname66(relPath));
53910
- const targetFile = join115(membersBase, `${overlayKind}.overrides`, relPath);
54320
+ const targetDir = join116(membersBase, `${overlayKind}.overrides`, dirname67(relPath));
54321
+ const targetFile = join116(membersBase, `${overlayKind}.overrides`, relPath);
53911
54322
  let srcBuf;
53912
54323
  try {
53913
- srcBuf = readFileSync103(srcFile);
54324
+ srcBuf = readFileSync105(srcFile);
53914
54325
  } catch {
53915
54326
  continue;
53916
54327
  }
53917
- const targetExists = existsSync116(targetFile);
54328
+ const targetExists = existsSync118(targetFile);
53918
54329
  if (targetExists) {
53919
- const dstBuf = readFileSync103(targetFile);
54330
+ const dstBuf = readFileSync105(targetFile);
53920
54331
  if (srcBuf.equals(dstBuf)) {
53921
54332
  filesUnchanged += 1;
53922
54333
  continue;
53923
54334
  }
53924
- mkdirSync69(targetDir, { recursive: true });
54335
+ mkdirSync70(targetDir, { recursive: true });
53925
54336
  copyFileSync15(srcFile, targetFile);
53926
54337
  filesCopied += 1;
53927
54338
  } else {
53928
- mkdirSync69(targetDir, { recursive: true });
54339
+ mkdirSync70(targetDir, { recursive: true });
53929
54340
  copyFileSync15(srcFile, targetFile);
53930
54341
  filesCreated += 1;
53931
54342
  }
@@ -53993,8 +54404,8 @@ function initMember(opts) {
53993
54404
  clonePath = skillSourceClonePath(source.id);
53994
54405
  }
53995
54406
  const atlasUser = resolveAtlasUser2(opts) ?? memberName;
53996
- const memberDir = join115(clonePath, "members", memberName);
53997
- if (existsSync116(memberDir)) {
54407
+ const memberDir = join116(clonePath, "members", memberName);
54408
+ if (existsSync118(memberDir)) {
53998
54409
  throw new PushError(
53999
54410
  1,
54000
54411
  `members/${memberName}/ already exists; use --push to update; or remove manually first
@@ -54002,9 +54413,9 @@ function initMember(opts) {
54002
54413
  );
54003
54414
  }
54004
54415
  const wouldCreate = [
54005
- join115(memberDir, "skills.overrides", ".gitkeep"),
54006
- join115(memberDir, "agents.overrides", ".gitkeep"),
54007
- join115(memberDir, "README.md")
54416
+ join116(memberDir, "skills.overrides", ".gitkeep"),
54417
+ join116(memberDir, "agents.overrides", ".gitkeep"),
54418
+ join116(memberDir, "README.md")
54008
54419
  ];
54009
54420
  if (opts.dryRun === true) {
54010
54421
  const { preflightWarnings } = runPreFlight(clonePath, opts.forceCurrentBranch === true, true);
@@ -54060,12 +54471,12 @@ function initMember(opts) {
54060
54471
  );
54061
54472
  }
54062
54473
  try {
54063
- mkdirSync69(join115(memberDir, "skills.overrides"), { recursive: true });
54064
- writeFileSync62(join115(memberDir, "skills.overrides", ".gitkeep"), "");
54065
- mkdirSync69(join115(memberDir, "agents.overrides"), { recursive: true });
54066
- writeFileSync62(join115(memberDir, "agents.overrides", ".gitkeep"), "");
54067
- writeFileSync62(
54068
- join115(memberDir, "README.md"),
54474
+ mkdirSync70(join116(memberDir, "skills.overrides"), { recursive: true });
54475
+ writeFileSync64(join116(memberDir, "skills.overrides", ".gitkeep"), "");
54476
+ mkdirSync70(join116(memberDir, "agents.overrides"), { recursive: true });
54477
+ writeFileSync64(join116(memberDir, "agents.overrides", ".gitkeep"), "");
54478
+ writeFileSync64(
54479
+ join116(memberDir, "README.md"),
54069
54480
  `# Member overlays for \`${memberName}\`
54070
54481
 
54071
54482
  See docs/plans/member-overlays-sync/ for layer architecture.
@@ -54106,10 +54517,10 @@ Next steps (run in ${clonePath}):`,
54106
54517
  };
54107
54518
  }
54108
54519
  function migrateOverlays(opts = {}) {
54109
- const root = opts.targetDir ?? join115(homedir71(), ".claude");
54520
+ const root = opts.targetDir ?? join116(homedir72(), ".claude");
54110
54521
  const overrideRoots = [
54111
- join115(root, "skills.overrides"),
54112
- join115(root, "agents.overrides")
54522
+ join116(root, "skills.overrides"),
54523
+ join116(root, "agents.overrides")
54113
54524
  ];
54114
54525
  const allFiles = [];
54115
54526
  for (const overrideRoot of overrideRoots) {
@@ -54125,7 +54536,7 @@ function migrateOverlays(opts = {}) {
54125
54536
  for (const filePath of allFiles) {
54126
54537
  let original;
54127
54538
  try {
54128
- original = readFileSync103(filePath, "utf8");
54539
+ original = readFileSync105(filePath, "utf8");
54129
54540
  } catch {
54130
54541
  continue;
54131
54542
  }
@@ -54136,7 +54547,7 @@ function migrateOverlays(opts = {}) {
54136
54547
  continue;
54137
54548
  }
54138
54549
  if (opts.dryRun !== true) {
54139
- writeFileSync62(filePath, newContent, "utf8");
54550
+ writeFileSync64(filePath, newContent, "utf8");
54140
54551
  }
54141
54552
  summary2.modified += 1;
54142
54553
  summary2.totalReplacements += totalReplacements;
@@ -54228,7 +54639,7 @@ function registerFlywheelMigrateOverlays(parent) {
54228
54639
  }
54229
54640
  return;
54230
54641
  }
54231
- const root = opts.targetDir ?? join115(homedir71(), ".claude");
54642
+ const root = opts.targetDir ?? join116(homedir72(), ".claude");
54232
54643
  const summary2 = migrateOverlays(opts);
54233
54644
  if (opts.json === true) {
54234
54645
  process.stdout.write(JSON.stringify(summary2, null, 2) + "\n");
@@ -54267,9 +54678,9 @@ Per-file changes:
54267
54678
  }
54268
54679
 
54269
54680
  // src/commands/flywheel/session-start.ts
54270
- import { readFileSync as readFileSync104, statSync as statSync34 } from "node:fs";
54271
- import { homedir as homedir72 } from "node:os";
54272
- import { join as join116 } from "node:path";
54681
+ import { readFileSync as readFileSync106, statSync as statSync34 } from "node:fs";
54682
+ import { homedir as homedir73 } from "node:os";
54683
+ import { join as join117 } from "node:path";
54273
54684
  var SESSIONSTART_HOOK_SENTINEL = "olam-sessionstart-context-hook-v1";
54274
54685
  var MAX_WAKE_BRIEF_BYTES = 8 * 1024;
54275
54686
  var MAX_ACTIVE_WORLD_BYTES = 4 * 1024;
@@ -54285,7 +54696,7 @@ function tryReadCapped(path106, maxBytes) {
54285
54696
  );
54286
54697
  return null;
54287
54698
  }
54288
- return readFileSync104(path106, "utf-8");
54699
+ return readFileSync106(path106, "utf-8");
54289
54700
  } catch (err) {
54290
54701
  const code = err?.code;
54291
54702
  if (code === "ENOENT") return null;
@@ -54310,15 +54721,15 @@ function tryParseJson(raw, label) {
54310
54721
  }
54311
54722
  function buildContextBlock(olamHome6) {
54312
54723
  const config = tryParseJson(
54313
- tryReadCapped(join116(olamHome6, "config.json"), MAX_CONFIG_BYTES),
54724
+ tryReadCapped(join117(olamHome6, "config.json"), MAX_CONFIG_BYTES),
54314
54725
  "config.json"
54315
54726
  );
54316
54727
  const activeWorld = tryParseJson(
54317
- tryReadCapped(join116(olamHome6, "state", "active-world.json"), MAX_ACTIVE_WORLD_BYTES),
54728
+ tryReadCapped(join117(olamHome6, "state", "active-world.json"), MAX_ACTIVE_WORLD_BYTES),
54318
54729
  "active-world.json"
54319
54730
  );
54320
54731
  const wakeBrief = tryReadCapped(
54321
- join116(olamHome6, "state", "wake-brief.md"),
54732
+ join117(olamHome6, "state", "wake-brief.md"),
54322
54733
  MAX_WAKE_BRIEF_BYTES
54323
54734
  );
54324
54735
  const sections = [];
@@ -54370,7 +54781,7 @@ function registerFlywheelSessionStart(parent) {
54370
54781
  parent.command("session-start").description(
54371
54782
  "Emit operator-state context for the SessionStart hook (4th defense layer). Reads ~/.olam/state/* and writes the additionalContext JSON to stdout. Fail-soft: always exits 0."
54372
54783
  ).action(() => {
54373
- const olamHome6 = process.env.OLAM_HOME ?? join116(homedir72(), ".olam");
54784
+ const olamHome6 = process.env.OLAM_HOME ?? join117(homedir73(), ".olam");
54374
54785
  emitSessionStartContext(olamHome6);
54375
54786
  process.exit(0);
54376
54787
  });
@@ -54379,9 +54790,9 @@ function registerFlywheelSessionStart(parent) {
54379
54790
  // src/commands/flywheel/install-sessionstart-hook.ts
54380
54791
  init_merge_settings();
54381
54792
  init_output();
54382
- import { existsSync as existsSync117, copyFileSync as copyFileSync16, mkdirSync as mkdirSync70, readFileSync as readFileSync105, unlinkSync as unlinkSync25, writeFileSync as writeFileSync63 } from "node:fs";
54383
- import { homedir as homedir73 } from "node:os";
54384
- import { dirname as dirname67, join as join117 } from "node:path";
54793
+ import { existsSync as existsSync119, copyFileSync as copyFileSync16, mkdirSync as mkdirSync71, readFileSync as readFileSync107, unlinkSync as unlinkSync25, writeFileSync as writeFileSync65 } from "node:fs";
54794
+ import { homedir as homedir74 } from "node:os";
54795
+ import { dirname as dirname68, join as join118 } from "node:path";
54385
54796
  var SESSIONSTART_HOOK_STAGE = "SessionStart";
54386
54797
  var SESSIONSTART_HOOK_TIMEOUT_MS = 5e3;
54387
54798
  var NOOP_GUARD = "command -v olam >/dev/null 2>&1 || exit 0;";
@@ -54398,18 +54809,18 @@ function buildSessionStartHookEntry() {
54398
54809
  };
54399
54810
  }
54400
54811
  function settingsPathFor4(scope, cwd) {
54401
- if (scope === "user") return join117(homedir73(), ".claude", "settings.json");
54402
- return join117(cwd ?? process.cwd(), ".claude", "settings.json");
54812
+ if (scope === "user") return join118(homedir74(), ".claude", "settings.json");
54813
+ return join118(cwd ?? process.cwd(), ".claude", "settings.json");
54403
54814
  }
54404
54815
  function backup3(filePath) {
54405
- if (!existsSync117(filePath)) return null;
54816
+ if (!existsSync119(filePath)) return null;
54406
54817
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
54407
54818
  const backupPath = `${filePath}.olam-bak.${ts}`;
54408
54819
  copyFileSync16(filePath, backupPath);
54409
54820
  return backupPath;
54410
54821
  }
54411
54822
  function installSessionStartHook(filePath) {
54412
- mkdirSync70(dirname67(filePath), { recursive: true });
54823
+ mkdirSync71(dirname68(filePath), { recursive: true });
54413
54824
  const backupPath = backup3(filePath);
54414
54825
  const result = mergeHomeSettingsJson(filePath, {
54415
54826
  ensureHook: {
@@ -54428,8 +54839,8 @@ function installSessionStartHook(filePath) {
54428
54839
  return { status: result.status, filePath, backupPath };
54429
54840
  }
54430
54841
  function uninstallSessionStartHook(filePath) {
54431
- if (!existsSync117(filePath)) return { status: "no-settings", filePath };
54432
- const raw = readFileSync105(filePath, "utf-8");
54842
+ if (!existsSync119(filePath)) return { status: "no-settings", filePath };
54843
+ const raw = readFileSync107(filePath, "utf-8");
54433
54844
  const settings = raw.trim() ? JSON.parse(raw) : {};
54434
54845
  const matchers = settings.hooks?.SessionStart;
54435
54846
  if (!Array.isArray(matchers) || matchers.length === 0) {
@@ -54469,7 +54880,7 @@ function uninstallSessionStartHook(filePath) {
54469
54880
  delete next.hooks.SessionStart;
54470
54881
  }
54471
54882
  }
54472
- writeFileSync63(filePath, JSON.stringify(next, null, 2) + "\n");
54883
+ writeFileSync65(filePath, JSON.stringify(next, null, 2) + "\n");
54473
54884
  return { status: "removed", filePath };
54474
54885
  }
54475
54886
  function registerFlywheelInstallSessionStartHook(parent) {
@@ -54787,7 +55198,7 @@ init_manager();
54787
55198
  init_context();
54788
55199
  init_output();
54789
55200
  import { spawnSync as defaultSpawnSync } from "node:child_process";
54790
- import * as fs104 from "node:fs";
55201
+ import * as fs105 from "node:fs";
54791
55202
  import * as os58 from "node:os";
54792
55203
  import * as path103 from "node:path";
54793
55204
  function devboxContainerName(worldId) {
@@ -54807,8 +55218,8 @@ function defaultRestartContainer(name, spawn14 = defaultSpawnSync) {
54807
55218
  };
54808
55219
  }
54809
55220
  function defaultAppendAuditLog(homeDir, line) {
54810
- fs104.mkdirSync(homeDir, { recursive: true });
54811
- fs104.appendFileSync(path103.join(homeDir, "usage.log"), line.endsWith("\n") ? line : line + "\n", {
55221
+ fs105.mkdirSync(homeDir, { recursive: true });
55222
+ fs105.appendFileSync(path103.join(homeDir, "usage.log"), line.endsWith("\n") ? line : line + "\n", {
54812
55223
  encoding: "utf-8"
54813
55224
  });
54814
55225
  }
@@ -54854,18 +55265,18 @@ async function doRekey(worldId, deps) {
54854
55265
  const rotatedAt = deps.now().toISOString();
54855
55266
  const homeDir = deps.olamHomeDir();
54856
55267
  const worldDir = path103.join(homeDir, "worlds", worldId);
54857
- fs104.mkdirSync(worldDir, { recursive: true });
55268
+ fs105.mkdirSync(worldDir, { recursive: true });
54858
55269
  const credentialsPath = path103.join(worldDir, "credentials.json");
54859
55270
  const payload = {
54860
55271
  worldRoleName,
54861
55272
  password,
54862
55273
  rotatedAt
54863
55274
  };
54864
- fs104.writeFileSync(credentialsPath, JSON.stringify(payload, null, 2) + "\n", {
55275
+ fs105.writeFileSync(credentialsPath, JSON.stringify(payload, null, 2) + "\n", {
54865
55276
  encoding: "utf-8",
54866
55277
  mode: 384
54867
55278
  });
54868
- fs104.chmodSync(credentialsPath, 384);
55279
+ fs105.chmodSync(credentialsPath, 384);
54869
55280
  const restart = deps.restartContainer(devboxContainerName(worldId));
54870
55281
  deps.appendAuditLog(`${rotatedAt} ${worldId} rekey`);
54871
55282
  if (!restart.ok) {
@@ -54931,7 +55342,7 @@ function registerRekey(program2) {
54931
55342
  // src/commands/yolo.ts
54932
55343
  init_output();
54933
55344
  import * as childProcess2 from "node:child_process";
54934
- import * as fs105 from "node:fs";
55345
+ import * as fs106 from "node:fs";
54935
55346
  import * as os59 from "node:os";
54936
55347
  import * as path104 from "node:path";
54937
55348
  import pc49 from "picocolors";
@@ -54956,12 +55367,12 @@ function defaultRunner(cmd, args, opts) {
54956
55367
  };
54957
55368
  }
54958
55369
  function defaultSleeper(ms) {
54959
- return new Promise((resolve30) => setTimeout(resolve30, ms));
55370
+ return new Promise((resolve31) => setTimeout(resolve31, ms));
54960
55371
  }
54961
55372
  function detectTmuxBinary(runner = defaultRunner) {
54962
55373
  for (const p of TMUX_PROBE_PATHS) {
54963
55374
  if (TMUX_SHIM_MARKERS.some((m) => p.includes(m))) continue;
54964
- if (fs105.existsSync(p)) return p;
55375
+ if (fs106.existsSync(p)) return p;
54965
55376
  }
54966
55377
  const result = runner("which", ["tmux"]);
54967
55378
  if (result.status === 0 && result.stdout) {
@@ -54976,8 +55387,8 @@ function resolveWorktreeRoot(runner = defaultRunner, cwd = process.cwd()) {
54976
55387
  return process.env["OLAM_TMUX_YOLO_ROOT"];
54977
55388
  }
54978
55389
  const rootFile = path104.join(os59.homedir(), ".olam-tmux-yolo-root");
54979
- if (fs105.existsSync(rootFile)) {
54980
- const line = fs105.readFileSync(rootFile, "utf-8").trim();
55390
+ if (fs106.existsSync(rootFile)) {
55391
+ const line = fs106.readFileSync(rootFile, "utf-8").trim();
54981
55392
  if (line) return line;
54982
55393
  }
54983
55394
  const gitResult = runner("git", ["rev-parse", "--show-toplevel"], { cwd });
@@ -55011,7 +55422,7 @@ async function spawnYolo(opts) {
55011
55422
  );
55012
55423
  }
55013
55424
  try {
55014
- fs105.accessSync(opts.promptFile, fs105.constants.R_OK);
55425
+ fs106.accessSync(opts.promptFile, fs106.constants.R_OK);
55015
55426
  } catch {
55016
55427
  throw new Error(
55017
55428
  `Prompt file not found or not readable: ${opts.promptFile}
@@ -55027,7 +55438,7 @@ Create the file with your task description and try again.`
55027
55438
  Run: olam yolo --cleanup ${opts.name} (or use --force to bypass the merged check)`
55028
55439
  );
55029
55440
  }
55030
- if (fs105.existsSync(worktreePath)) {
55441
+ if (fs106.existsSync(worktreePath)) {
55031
55442
  throw new Error(
55032
55443
  `Worktree directory already exists: ${worktreePath}
55033
55444
  Run: olam yolo --cleanup ${opts.name} to remove it first.`
@@ -55095,7 +55506,7 @@ function listYoloWindows(opts = {}) {
55095
55506
  const worktreePath = path104.join(worktreeRoot, name);
55096
55507
  return {
55097
55508
  name,
55098
- worktreePath: fs105.existsSync(worktreePath) ? worktreePath : void 0
55509
+ worktreePath: fs106.existsSync(worktreePath) ? worktreePath : void 0
55099
55510
  };
55100
55511
  });
55101
55512
  }
@@ -55229,18 +55640,18 @@ function registerYolo(program2) {
55229
55640
  }
55230
55641
 
55231
55642
  // src/pleri-config.ts
55232
- import * as fs106 from "node:fs";
55643
+ import * as fs107 from "node:fs";
55233
55644
  import * as path105 from "node:path";
55234
55645
  function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
55235
55646
  if (process.env.PLERI_BASE_URL) {
55236
55647
  return true;
55237
55648
  }
55238
55649
  const configPath = path105.join(configDir, "config.yaml");
55239
- if (!fs106.existsSync(configPath)) {
55650
+ if (!fs107.existsSync(configPath)) {
55240
55651
  return false;
55241
55652
  }
55242
55653
  try {
55243
- const contents = fs106.readFileSync(configPath, "utf8");
55654
+ const contents = fs107.readFileSync(configPath, "utf8");
55244
55655
  return /^[^#\n]*\bpleri:/m.test(contents);
55245
55656
  } catch {
55246
55657
  return false;
@@ -55279,7 +55690,7 @@ var HELP_GROUPS = [
55279
55690
  },
55280
55691
  {
55281
55692
  title: "Skills & knowledge",
55282
- names: ["skills", "kg", "ask", "flywheel"]
55693
+ names: ["skills", "100x", "kg", "ask", "flywheel"]
55283
55694
  },
55284
55695
  {
55285
55696
  title: "Substrate & infra",
@@ -55442,7 +55853,7 @@ registerSkillsMigrateHooks(program);
55442
55853
  registerSkillsMigrateHooksBack(program);
55443
55854
  registerSkillsShadowBackups(program);
55444
55855
  registerSkillsDoctor(program);
55445
- registerSkills10x(program);
55856
+ registerSkills100x(program);
55446
55857
  registerHermes(program);
55447
55858
  void scheduleUpgradeCheck(cliVersion);
55448
55859
  await program.parseAsync();