@pleri/olam-cli 0.1.106 → 0.1.107

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.
package/dist/index.js CHANGED
@@ -487,8 +487,8 @@ var init_parseUtil = __esm({
487
487
  init_errors();
488
488
  init_en();
489
489
  makeIssue = (params) => {
490
- const { data, path: path52, errorMaps, issueData } = params;
491
- const fullPath = [...path52, ...issueData.path || []];
490
+ const { data, path: path53, errorMaps, issueData } = params;
491
+ const fullPath = [...path53, ...issueData.path || []];
492
492
  const fullIssue = {
493
493
  ...issueData,
494
494
  path: fullPath
@@ -796,11 +796,11 @@ var init_types = __esm({
796
796
  init_parseUtil();
797
797
  init_util();
798
798
  ParseInputLazyPath = class {
799
- constructor(parent, value, path52, key) {
799
+ constructor(parent, value, path53, key) {
800
800
  this._cachedPath = [];
801
801
  this.parent = parent;
802
802
  this.data = value;
803
- this._path = path52;
803
+ this._path = path53;
804
804
  this._key = key;
805
805
  }
806
806
  get path() {
@@ -4281,7 +4281,7 @@ import YAML from "yaml";
4281
4281
  function bootstrapStepCmd(entry) {
4282
4282
  return typeof entry === "string" ? entry : entry.cmd;
4283
4283
  }
4284
- function refineForbiddenKeys(value, path52, ctx, rejectSource) {
4284
+ function refineForbiddenKeys(value, path53, ctx, rejectSource) {
4285
4285
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
4286
4286
  return;
4287
4287
  }
@@ -4289,12 +4289,12 @@ function refineForbiddenKeys(value, path52, ctx, rejectSource) {
4289
4289
  if (FORBIDDEN_KEYS.has(key)) {
4290
4290
  ctx.addIssue({
4291
4291
  code: external_exports.ZodIssueCode.custom,
4292
- path: [...path52, key],
4292
+ path: [...path53, key],
4293
4293
  message: `forbidden key "${key}" (prototype-pollution surface)`
4294
4294
  });
4295
4295
  continue;
4296
4296
  }
4297
- if (rejectSource && path52.length === 0 && key === "source") {
4297
+ if (rejectSource && path53.length === 0 && key === "source") {
4298
4298
  ctx.addIssue({
4299
4299
  code: external_exports.ZodIssueCode.custom,
4300
4300
  path: ["source"],
@@ -4302,21 +4302,21 @@ function refineForbiddenKeys(value, path52, ctx, rejectSource) {
4302
4302
  });
4303
4303
  continue;
4304
4304
  }
4305
- refineForbiddenKeys(value[key], [...path52, key], ctx, false);
4305
+ refineForbiddenKeys(value[key], [...path53, key], ctx, false);
4306
4306
  }
4307
4307
  }
4308
- function rejectForbiddenKeys(value, path52, rejectSource) {
4308
+ function rejectForbiddenKeys(value, path53, rejectSource) {
4309
4309
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
4310
4310
  return;
4311
4311
  }
4312
4312
  for (const key of Object.keys(value)) {
4313
4313
  if (FORBIDDEN_KEYS.has(key)) {
4314
- throw new Error(`[manifest] ${path52}: forbidden key "${key}" (prototype-pollution surface)`);
4314
+ throw new Error(`[manifest] ${path53}: forbidden key "${key}" (prototype-pollution surface)`);
4315
4315
  }
4316
4316
  if (rejectSource && key === "source") {
4317
- throw new Error(`[manifest] ${path52}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
4317
+ throw new Error(`[manifest] ${path53}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
4318
4318
  }
4319
- rejectForbiddenKeys(value[key], `${path52}.${key}`, false);
4319
+ rejectForbiddenKeys(value[key], `${path53}.${key}`, false);
4320
4320
  }
4321
4321
  }
4322
4322
  function unknownTopLevelKeys(parsed) {
@@ -5309,8 +5309,8 @@ var init_client = __esm({
5309
5309
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
5310
5310
  }
5311
5311
  }
5312
- async request(method, path52, body, attempt = 0) {
5313
- const url = `${this.baseUrl}${path52}`;
5312
+ async request(method, path53, body, attempt = 0) {
5313
+ const url = `${this.baseUrl}${path53}`;
5314
5314
  const controller = new AbortController();
5315
5315
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
5316
5316
  const headers = {};
@@ -5328,7 +5328,7 @@ var init_client = __esm({
5328
5328
  } catch (err) {
5329
5329
  if (attempt < RETRY_COUNT && isTransient(err)) {
5330
5330
  await sleep(RETRY_BACKOFF_MS * (attempt + 1));
5331
- return this.request(method, path52, body, attempt + 1);
5331
+ return this.request(method, path53, body, attempt + 1);
5332
5332
  }
5333
5333
  throw err;
5334
5334
  } finally {
@@ -6877,8 +6877,8 @@ var init_provider3 = __esm({
6877
6877
  // -----------------------------------------------------------------------
6878
6878
  // Internal fetch helper
6879
6879
  // -----------------------------------------------------------------------
6880
- async request(path52, method, body) {
6881
- const url = `${this.config.workerUrl}${path52}`;
6880
+ async request(path53, method, body) {
6881
+ const url = `${this.config.workerUrl}${path53}`;
6882
6882
  const bearer = await this.config.mintToken();
6883
6883
  const headers = {
6884
6884
  Authorization: `Bearer ${bearer}`
@@ -8170,8 +8170,8 @@ import { execFileSync as execFileSync3 } from "node:child_process";
8170
8170
  import * as fs14 from "node:fs";
8171
8171
  import * as os9 from "node:os";
8172
8172
  import * as path15 from "node:path";
8173
- function expandHome(p, homedir28) {
8174
- return p.replace(/^~(?=$|\/|\\)/, homedir28());
8173
+ function expandHome(p, homedir29) {
8174
+ return p.replace(/^~(?=$|\/|\\)/, homedir29());
8175
8175
  }
8176
8176
  function sanitizeRepoFilename(name) {
8177
8177
  const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -8194,7 +8194,7 @@ ${stderr}`;
8194
8194
  }
8195
8195
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
8196
8196
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
8197
- const homedir28 = deps.homedir ?? (() => os9.homedir());
8197
+ const homedir29 = deps.homedir ?? (() => os9.homedir());
8198
8198
  const baselineDir = path15.join(workspacePath, ".olam", "baseline");
8199
8199
  try {
8200
8200
  fs14.mkdirSync(baselineDir, { recursive: true });
@@ -8210,7 +8210,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
8210
8210
  continue;
8211
8211
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
8212
8212
  const outPath = path15.join(baselineDir, filename);
8213
- const repoPath = expandHome(repo.path, homedir28);
8213
+ const repoPath = expandHome(repo.path, homedir29);
8214
8214
  if (!fs14.existsSync(repoPath)) {
8215
8215
  writeBaselineFile(outPath, `# repo: ${repo.name}
8216
8216
  # (skipped: path ${repoPath} does not exist)
@@ -13822,10 +13822,10 @@ async function readHostCpToken2() {
13822
13822
  if (!fs25.existsSync(tp)) return null;
13823
13823
  return fs25.readFileSync(tp, "utf-8").trim();
13824
13824
  }
13825
- async function callHostCpProxy(method, worldId, path52, body) {
13825
+ async function callHostCpProxy(method, worldId, path53, body) {
13826
13826
  const token = await readHostCpToken2();
13827
13827
  if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
13828
- const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path52}`;
13828
+ const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path53}`;
13829
13829
  try {
13830
13830
  const headers = {
13831
13831
  Authorization: `Bearer ${token}`
@@ -14285,7 +14285,7 @@ __export(machine_schema_exports, {
14285
14285
  writeMachineConfig: () => writeMachineConfig
14286
14286
  });
14287
14287
  import * as fs41 from "node:fs";
14288
- import * as path44 from "node:path";
14288
+ import * as path45 from "node:path";
14289
14289
  import * as os24 from "node:os";
14290
14290
  import { parse as parseYaml5, stringify as stringifyYaml5 } from "yaml";
14291
14291
  function readMachineConfig(configPath) {
@@ -14302,7 +14302,7 @@ function readMachineConfig(configPath) {
14302
14302
  }
14303
14303
  function writeMachineConfig(config, configPath) {
14304
14304
  const p = configPath ?? DEFAULT_CONFIG_PATH;
14305
- fs41.mkdirSync(path44.dirname(p), { recursive: true });
14305
+ fs41.mkdirSync(path45.dirname(p), { recursive: true });
14306
14306
  fs41.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
14307
14307
  }
14308
14308
  function initMachineConfig(opts = {}) {
@@ -14326,9 +14326,9 @@ var init_machine_schema = __esm({
14326
14326
  channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
14327
14327
  auto_update: external_exports.boolean().default(true),
14328
14328
  telemetry: external_exports.boolean().default(true),
14329
- worlds_dir: external_exports.string().default(() => path44.join(os24.homedir(), ".olam", "worlds"))
14329
+ worlds_dir: external_exports.string().default(() => path45.join(os24.homedir(), ".olam", "worlds"))
14330
14330
  });
14331
- DEFAULT_CONFIG_PATH = path44.join(os24.homedir(), ".olam", "config.yaml");
14331
+ DEFAULT_CONFIG_PATH = path45.join(os24.homedir(), ".olam", "config.yaml");
14332
14332
  }
14333
14333
  });
14334
14334
 
@@ -14710,9 +14710,9 @@ var UnknownArchetypeError = class extends Error {
14710
14710
  };
14711
14711
  var ArchetypeCycleError = class extends Error {
14712
14712
  path;
14713
- constructor(path52) {
14714
- super(`Archetype inheritance cycle detected: ${path52.join(" \u2192 ")} \u2192 ${path52[0] ?? "?"}`);
14715
- this.path = path52;
14713
+ constructor(path53) {
14714
+ super(`Archetype inheritance cycle detected: ${path53.join(" \u2192 ")} \u2192 ${path53[0] ?? "?"}`);
14715
+ this.path = path53;
14716
14716
  this.name = "ArchetypeCycleError";
14717
14717
  }
14718
14718
  };
@@ -16093,9 +16093,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
16093
16093
  "These source files have changed since the image was built; the",
16094
16094
  "changes will NOT take effect in fresh worlds until you rebuild:"
16095
16095
  ];
16096
- for (const { path: path52, mtimeMs } of result.newerSources) {
16096
+ for (const { path: path53, mtimeMs } of result.newerSources) {
16097
16097
  const when = new Date(mtimeMs).toISOString();
16098
- lines.push(` \u2022 ${path52} (modified ${when})`);
16098
+ lines.push(` \u2022 ${path53} (modified ${when})`);
16099
16099
  }
16100
16100
  lines.push("");
16101
16101
  lines.push("Rebuild with:");
@@ -16256,9 +16256,9 @@ async function readHostCpTokenForCreate() {
16256
16256
  try {
16257
16257
  const { default: fs50 } = await import("node:fs");
16258
16258
  const { default: os28 } = await import("node:os");
16259
- const { default: path52 } = await import("node:path");
16260
- const tp = path52.join(
16261
- process.env.OLAM_HOME ?? path52.join(os28.homedir(), ".olam"),
16259
+ const { default: path53 } = await import("node:path");
16260
+ const tp = path53.join(
16261
+ process.env.OLAM_HOME ?? path53.join(os28.homedir(), ".olam"),
16262
16262
  "host-cp.token"
16263
16263
  );
16264
16264
  if (!fs50.existsSync(tp)) return null;
@@ -16627,8 +16627,8 @@ async function readHostCpToken3() {
16627
16627
  try {
16628
16628
  const { default: fs50 } = await import("node:fs");
16629
16629
  const { default: os28 } = await import("node:os");
16630
- const { default: path52 } = await import("node:path");
16631
- const tp = path52.join(os28.homedir(), ".olam", "host-cp.token");
16630
+ const { default: path53 } = await import("node:path");
16631
+ const tp = path53.join(os28.homedir(), ".olam", "host-cp.token");
16632
16632
  if (!fs50.existsSync(tp)) return null;
16633
16633
  const raw = fs50.readFileSync(tp, "utf-8").trim();
16634
16634
  return raw.length > 0 ? raw : null;
@@ -20361,11 +20361,11 @@ function zodIssueToError(issue, doc, lineCounter) {
20361
20361
  suggestion: deriveSuggestion(issue)
20362
20362
  };
20363
20363
  }
20364
- function formatJsonPath(path52) {
20365
- if (path52.length === 0)
20364
+ function formatJsonPath(path53) {
20365
+ if (path53.length === 0)
20366
20366
  return "<root>";
20367
20367
  let out = "";
20368
- for (const seg of path52) {
20368
+ for (const seg of path53) {
20369
20369
  if (typeof seg === "number") {
20370
20370
  out += `[${seg}]`;
20371
20371
  } else {
@@ -20374,11 +20374,11 @@ function formatJsonPath(path52) {
20374
20374
  }
20375
20375
  return out;
20376
20376
  }
20377
- function resolveYamlLocation(path52, doc, lineCounter) {
20377
+ function resolveYamlLocation(path53, doc, lineCounter) {
20378
20378
  let bestLine = 0;
20379
20379
  let bestColumn = 0;
20380
- for (let depth = path52.length; depth >= 0; depth -= 1) {
20381
- const segment = path52.slice(0, depth);
20380
+ for (let depth = path53.length; depth >= 0; depth -= 1) {
20381
+ const segment = path53.slice(0, depth);
20382
20382
  try {
20383
20383
  const node = doc.getIn(segment, true);
20384
20384
  if (node && typeof node === "object" && "range" in node) {
@@ -20596,11 +20596,11 @@ function topoSort(nodes) {
20596
20596
  }
20597
20597
  function traceCycle(start, byId) {
20598
20598
  const seen = /* @__PURE__ */ new Set();
20599
- const path52 = [];
20599
+ const path53 = [];
20600
20600
  let current = start;
20601
20601
  while (current && !seen.has(current)) {
20602
20602
  seen.add(current);
20603
- path52.push(current);
20603
+ path53.push(current);
20604
20604
  const node = byId.get(current);
20605
20605
  const next = node?.dependsOn[0];
20606
20606
  if (next === void 0)
@@ -20608,10 +20608,10 @@ function traceCycle(start, byId) {
20608
20608
  current = next;
20609
20609
  }
20610
20610
  if (current && seen.has(current)) {
20611
- const idx = path52.indexOf(current);
20612
- return [...path52.slice(idx), current];
20611
+ const idx = path53.indexOf(current);
20612
+ return [...path53.slice(idx), current];
20613
20613
  }
20614
- return path52;
20614
+ return path53;
20615
20615
  }
20616
20616
 
20617
20617
  // ../core/dist/executor/types.js
@@ -23987,7 +23987,7 @@ function registerLogs(program2) {
23987
23987
  resolveStream();
23988
23988
  }
23989
23989
  };
23990
- const emit = (line, service) => {
23990
+ const emit2 = (line, service) => {
23991
23991
  process.stdout.write(formatLine(line, service, showService) + "\n");
23992
23992
  lineCount++;
23993
23993
  if (!opts.follow && lineCount >= tailLimit) {
@@ -24016,13 +24016,13 @@ function registerLogs(program2) {
24016
24016
  if (!ev) continue;
24017
24017
  if (ev.type === "replay") {
24018
24018
  for (const l of ev.lines) {
24019
- if (!emit(l, ev.service)) {
24019
+ if (!emit2(l, ev.service)) {
24020
24020
  req.destroy();
24021
24021
  break;
24022
24022
  }
24023
24023
  }
24024
24024
  } else if (ev.type === "line") {
24025
- if (!emit(ev.line, ev.service)) req.destroy();
24025
+ if (!emit2(ev.line, ev.service)) req.destroy();
24026
24026
  }
24027
24027
  }
24028
24028
  });
@@ -25037,16 +25037,348 @@ function registerDiagnose(program2) {
25037
25037
  });
25038
25038
  }
25039
25039
 
25040
+ // src/lib/health-probes.ts
25041
+ import { spawnSync as spawnSync14 } from "node:child_process";
25042
+ import { existsSync as existsSync43, readdirSync as readdirSync11, readFileSync as readFileSync30, statSync as statSync13 } from "node:fs";
25043
+ import { homedir as homedir22 } from "node:os";
25044
+ import path43 from "node:path";
25045
+
25046
+ // src/lib/kg-caps.ts
25047
+ var SOFT_CAP_BYTES = 15e8;
25048
+ var HARD_CAP_BYTES = 5e9;
25049
+
25050
+ // src/lib/health-probes.ts
25051
+ var HEALTH_TIMEOUT_MS2 = 5e3;
25052
+ var defaultDockerExec2 = (cmd, args) => {
25053
+ const r = spawnSync14(cmd, [...args], {
25054
+ encoding: "utf-8",
25055
+ stdio: ["ignore", "pipe", "pipe"]
25056
+ });
25057
+ return {
25058
+ status: r.status,
25059
+ stdout: r.stdout ?? "",
25060
+ stderr: r.stderr ?? ""
25061
+ };
25062
+ };
25063
+ var defaultFetch = (input, init) => fetch(input, init);
25064
+ async function probeDockerDaemon(dockerExec = defaultDockerExec2) {
25065
+ const r = dockerExec("docker", ["info", "--format", "{{.ServerVersion}}"]);
25066
+ if (r.status === 0 && r.stdout.trim().length > 0) {
25067
+ return { ok: true, message: `docker ${r.stdout.trim()} reachable` };
25068
+ }
25069
+ return {
25070
+ ok: false,
25071
+ message: "docker daemon not reachable",
25072
+ remedy: "Start Docker Desktop (or your docker daemon) and re-run."
25073
+ };
25074
+ }
25075
+ async function probeImagePresence(refs, dockerExec = defaultDockerExec2) {
25076
+ for (const ref of refs) {
25077
+ const r = dockerExec("docker", ["image", "inspect", "--format", "{{.Id}}", ref]);
25078
+ if (r.status !== 0) {
25079
+ return {
25080
+ ok: false,
25081
+ message: `image ${ref} not present locally`,
25082
+ remedy: "Run `olam bootstrap` to pull the published image, or build locally."
25083
+ };
25084
+ }
25085
+ }
25086
+ return { ok: true, message: `${refs.length} image(s) present` };
25087
+ }
25088
+ async function probeHostCpHealth(fetchImpl = defaultFetch) {
25089
+ const controller = new AbortController();
25090
+ const timeout = setTimeout(() => controller.abort(), HEALTH_TIMEOUT_MS2);
25091
+ try {
25092
+ const res = await fetchImpl("http://127.0.0.1:19000/health", { signal: controller.signal });
25093
+ const body = await res.text().catch(() => "");
25094
+ if (res.status !== 200) {
25095
+ return {
25096
+ ok: false,
25097
+ message: `host-cp /health returned ${res.status}`,
25098
+ remedy: "Restart host-cp via `olam host-cp start`; verify port 19000 is bound to 127.0.0.1."
25099
+ };
25100
+ }
25101
+ if (isHostCpHealthEnvelope(body)) {
25102
+ return { ok: true, message: "host-cp /health returned 200" };
25103
+ }
25104
+ return {
25105
+ ok: false,
25106
+ message: "host-cp /health returned 200 but body did not match the host-cp envelope (possible port collision on :19000)",
25107
+ remedy: "Check `lsof -iTCP:19000`; another process may have bound the port. Restart host-cp via `olam host-cp start`."
25108
+ };
25109
+ } catch (err) {
25110
+ const e = err;
25111
+ const reason = e.name === "AbortError" ? `timeout (${HEALTH_TIMEOUT_MS2}ms)` : e.message;
25112
+ return {
25113
+ ok: false,
25114
+ message: `host-cp /health unreachable: ${reason}`,
25115
+ remedy: "Restart host-cp via `olam host-cp start`; verify port 19000 is bound to 127.0.0.1."
25116
+ };
25117
+ } finally {
25118
+ clearTimeout(timeout);
25119
+ }
25120
+ }
25121
+ function isHostCpHealthEnvelope(body) {
25122
+ let parsed;
25123
+ try {
25124
+ parsed = JSON.parse(body);
25125
+ } catch {
25126
+ return false;
25127
+ }
25128
+ if (!parsed || typeof parsed !== "object") return false;
25129
+ const obj = parsed;
25130
+ if (typeof obj.phase !== "string") return false;
25131
+ if (!obj.cache || typeof obj.cache !== "object") return false;
25132
+ const mode = obj.mode;
25133
+ if (!mode || typeof mode !== "object") return false;
25134
+ if (typeof mode.deployment !== "string") return false;
25135
+ return true;
25136
+ }
25137
+ async function probeAuthVault(olamHomeOverride) {
25138
+ const vaultPath = resolveAccountsPath(olamHomeOverride);
25139
+ if (!existsSync43(vaultPath)) {
25140
+ return {
25141
+ ok: false,
25142
+ message: `auth vault missing at ${vaultPath}`,
25143
+ remedy: "Run `olam auth up && olam auth login` to provision the vault."
25144
+ };
25145
+ }
25146
+ let parsed;
25147
+ try {
25148
+ parsed = JSON.parse(readFileSync30(vaultPath, "utf-8"));
25149
+ } catch (err) {
25150
+ return {
25151
+ ok: false,
25152
+ message: `auth vault malformed: ${err.message}`,
25153
+ remedy: "Inspect the accounts.json file; restore from backup or re-run `olam auth up`."
25154
+ };
25155
+ }
25156
+ if (!Array.isArray(parsed)) {
25157
+ return {
25158
+ ok: false,
25159
+ message: "auth vault malformed: expected JSON array at top level",
25160
+ remedy: "Restore the vault from backup or re-run `olam auth up && olam auth login`."
25161
+ };
25162
+ }
25163
+ const accounts = parsed.filter((a) => a !== null && typeof a === "object");
25164
+ const now = Date.now();
25165
+ const activeClaude = accounts.filter((a) => a.provider === "claude" && effectiveState2(a, now) === "active");
25166
+ if (activeClaude.length === 0) {
25167
+ return {
25168
+ ok: false,
25169
+ message: `no active claude credentials (vault has ${accounts.length} account(s))`,
25170
+ remedy: "Run `olam auth login` to add a credential, or wait for the next reset."
25171
+ };
25172
+ }
25173
+ return { ok: true, message: `${activeClaude.length} active claude credential(s)` };
25174
+ }
25175
+ function resolveAccountsPath(olamHomeOverride) {
25176
+ const explicit = process.env.OLAM_AUTH_DATA_PATH;
25177
+ if (explicit) return explicit;
25178
+ const olamHome5 = olamHomeOverride ?? process.env.OLAM_HOME ?? path43.join(homedir22(), ".olam");
25179
+ return path43.join(olamHome5, "auth-data", "accounts.json");
25180
+ }
25181
+ function effectiveState2(account, now) {
25182
+ const persisted = account.state ?? (account.rateLimited ? "cooldown" : "active");
25183
+ if (persisted === "disabled") return "disabled";
25184
+ if (typeof account.expiresAt === "number" && account.expiresAt <= now) return "expired";
25185
+ if (persisted === "cooldown") {
25186
+ const reset = account.rateLimitResetsAt ? new Date(account.rateLimitResetsAt).getTime() : 0;
25187
+ if (reset > 0 && reset <= now) return "active";
25188
+ }
25189
+ return persisted;
25190
+ }
25191
+ async function probeKgStorage(olamHomeOverride) {
25192
+ const olamHome5 = olamHomeOverride ?? process.env.OLAM_HOME ?? path43.join(homedir22(), ".olam");
25193
+ const kgRoot3 = path43.join(olamHome5, "kg");
25194
+ const worldsRoot3 = path43.join(olamHome5, "worlds");
25195
+ const kgBytes = enumerateGraphifyOut(kgRoot3, "pristine");
25196
+ const overlayBytes = enumerateGraphifyOut(worldsRoot3, "overlay");
25197
+ const totalBytes = kgBytes + overlayBytes;
25198
+ if (totalBytes >= HARD_CAP_BYTES) {
25199
+ return {
25200
+ ok: false,
25201
+ message: `KG storage ${formatBytes4(totalBytes)} exceeds 5 GB hard cap`,
25202
+ remedy: "Prune stale pristines: `rm -rf ~/.olam/kg/<workspace>` after operator review."
25203
+ };
25204
+ }
25205
+ if (totalBytes >= SOFT_CAP_BYTES) {
25206
+ return {
25207
+ ok: true,
25208
+ message: `KG storage ${formatBytes4(totalBytes)} (soft-warn \u2014 exceeds 1.5 GB; consider pruning)`
25209
+ };
25210
+ }
25211
+ return { ok: true, message: `KG storage ${formatBytes4(totalBytes)} (under cap)` };
25212
+ }
25213
+ function enumerateGraphifyOut(root, layout) {
25214
+ if (!existsSync43(root)) return 0;
25215
+ let total = 0;
25216
+ let entries;
25217
+ try {
25218
+ entries = readdirSync11(root, { withFileTypes: true });
25219
+ } catch {
25220
+ return 0;
25221
+ }
25222
+ for (const entry of entries) {
25223
+ if (!entry.isDirectory()) continue;
25224
+ if (layout === "pristine") {
25225
+ total += dirSizeBytes(path43.join(root, entry.name, "graphify-out"));
25226
+ } else {
25227
+ const worldDir = path43.join(root, entry.name);
25228
+ let clones;
25229
+ try {
25230
+ clones = readdirSync11(worldDir, { withFileTypes: true });
25231
+ } catch {
25232
+ continue;
25233
+ }
25234
+ for (const clone of clones) {
25235
+ if (!clone.isDirectory()) continue;
25236
+ total += dirSizeBytes(path43.join(worldDir, clone.name, "graphify-out"));
25237
+ }
25238
+ }
25239
+ }
25240
+ return total;
25241
+ }
25242
+ function dirSizeBytes(dir) {
25243
+ if (!existsSync43(dir)) return 0;
25244
+ let total = 0;
25245
+ const stack = [dir];
25246
+ while (stack.length > 0) {
25247
+ const cur = stack.pop();
25248
+ let entries;
25249
+ try {
25250
+ entries = readdirSync11(cur, { withFileTypes: true });
25251
+ } catch {
25252
+ continue;
25253
+ }
25254
+ for (const entry of entries) {
25255
+ const full = path43.join(cur, entry.name);
25256
+ if (entry.isSymbolicLink()) continue;
25257
+ if (entry.isDirectory()) {
25258
+ stack.push(full);
25259
+ continue;
25260
+ }
25261
+ try {
25262
+ total += statSync13(full).size;
25263
+ } catch {
25264
+ }
25265
+ }
25266
+ }
25267
+ return total;
25268
+ }
25269
+ function formatBytes4(n) {
25270
+ if (n < 1024) return `${n} B`;
25271
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
25272
+ if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
25273
+ return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
25274
+ }
25275
+
25276
+ // src/commands/doctor.ts
25277
+ init_output();
25278
+ var DEFAULT_REGISTRY = "ghcr.io/pleri";
25279
+ var REQUIRED_IMAGE_PAIRS = [
25280
+ { bare: "olam-host-cp:latest", registryName: "olam-host-cp:latest" },
25281
+ { bare: "olam-auth:local" },
25282
+ { bare: "olam-devbox:base", registryName: "olam-devbox:base" },
25283
+ { bare: "olam-mcp-auth:local" }
25284
+ ];
25285
+ function buildRequiredImageRefs(registry) {
25286
+ const refs = [];
25287
+ for (const pair of REQUIRED_IMAGE_PAIRS) {
25288
+ refs.push(pair.bare);
25289
+ if (pair.registryName) refs.push(`${registry}/${pair.registryName}`);
25290
+ }
25291
+ return refs;
25292
+ }
25293
+ async function runDoctor(opts, deps = {}) {
25294
+ const dockerExec = deps.dockerExec;
25295
+ const fetchImpl = deps.fetchImpl;
25296
+ const olamHomeOverride = deps.olamHomeOverride;
25297
+ const registry = deps.registry ?? DEFAULT_REGISTRY;
25298
+ const dockerResult = await probeDockerDaemon(dockerExec);
25299
+ const rows = [{ name: "docker daemon", result: dockerResult }];
25300
+ if (!dockerResult.ok) {
25301
+ return emit({ rows, summary: "FAILED", failureCount: 1 }, opts);
25302
+ }
25303
+ const imageRefs = buildRequiredImageRefs(registry);
25304
+ const [imageResult, hostCpResult, authResult, kgResult] = await Promise.all([
25305
+ probeImagePresence(imageRefs, dockerExec),
25306
+ probeHostCpHealth(fetchImpl),
25307
+ probeAuthVault(olamHomeOverride),
25308
+ probeKgStorage(olamHomeOverride)
25309
+ ]);
25310
+ rows.push(
25311
+ { name: "images", result: imageResult },
25312
+ { name: "host-cp /health", result: hostCpResult },
25313
+ { name: "auth vault", result: authResult },
25314
+ { name: "KG storage", result: kgResult }
25315
+ );
25316
+ const failureCount = rows.filter((r) => !r.result.ok).length;
25317
+ const summary = failureCount === 0 ? "OK" : "FAILED";
25318
+ return emit({ rows, summary, failureCount }, opts);
25319
+ }
25320
+ function emit(report, opts) {
25321
+ if (opts.json) {
25322
+ process.stdout.write(
25323
+ JSON.stringify(
25324
+ {
25325
+ summary: report.summary,
25326
+ failureCount: report.failureCount,
25327
+ probes: report.rows.map((r) => ({
25328
+ name: r.name,
25329
+ ok: r.result.ok,
25330
+ message: r.result.message,
25331
+ ...r.result.ok ? {} : { remedy: r.result.remedy }
25332
+ }))
25333
+ },
25334
+ null,
25335
+ 2
25336
+ ) + "\n"
25337
+ );
25338
+ } else {
25339
+ renderHuman(report);
25340
+ }
25341
+ const exitCode = report.summary === "OK" ? 0 : 1;
25342
+ return { exitCode, report };
25343
+ }
25344
+ function renderHuman(report) {
25345
+ printHeader("olam doctor");
25346
+ const namePad = Math.max(...report.rows.map((r) => r.name.length));
25347
+ for (const row of report.rows) {
25348
+ const label = row.name.padEnd(namePad);
25349
+ if (row.result.ok) {
25350
+ printSuccess(`${label} ${row.result.message}`);
25351
+ } else {
25352
+ printError(`${label} ${row.result.message}`);
25353
+ printWarning(`${"".padEnd(namePad)} remedy: ${row.result.remedy}`);
25354
+ }
25355
+ }
25356
+ process.stdout.write("\n");
25357
+ if (report.summary === "OK") {
25358
+ printSuccess(`OK \u2014 all ${report.rows.length} probes green`);
25359
+ } else {
25360
+ printError(`FAILED \u2014 ${report.failureCount} of ${report.rows.length} probes failed`);
25361
+ }
25362
+ }
25363
+ function registerDoctor(program2) {
25364
+ program2.command("doctor").description(
25365
+ "Pass/fail host-health check. Exits 0 on a healthy host; 1 on any failed probe. Runs Docker daemon / image presence / host-cp /health / auth vault / KG storage probes."
25366
+ ).option("--json", "emit the report as JSON instead of a human-readable table").action(async (opts) => {
25367
+ const r = await runDoctor(opts);
25368
+ if (r.exitCode !== 0) process.exitCode = r.exitCode;
25369
+ });
25370
+ }
25371
+
25040
25372
  // src/commands/update.ts
25041
25373
  import * as fs42 from "node:fs";
25042
25374
  import * as os25 from "node:os";
25043
- import * as path45 from "node:path";
25375
+ import * as path46 from "node:path";
25044
25376
  import { execSync as execSync13 } from "node:child_process";
25045
25377
  import pc23 from "picocolors";
25046
25378
 
25047
25379
  // src/lib/symlink-reconcile.ts
25048
25380
  import * as fs40 from "node:fs";
25049
- import * as path43 from "node:path";
25381
+ import * as path44 from "node:path";
25050
25382
  var realFs = {
25051
25383
  readdirSync: (p) => fs40.readdirSync(p),
25052
25384
  existsSync: (p) => fs40.existsSync(p),
@@ -25065,8 +25397,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
25065
25397
  _fs.mkdirSync(claudeSkillsDir, { recursive: true });
25066
25398
  const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
25067
25399
  for (const skill of sourceSkills) {
25068
- const linkPath = path43.join(claudeSkillsDir, skill);
25069
- const target = path43.join(npmSkillsDir, skill);
25400
+ const linkPath = path44.join(claudeSkillsDir, skill);
25401
+ const target = path44.join(npmSkillsDir, skill);
25070
25402
  if (!_fs.existsSync(linkPath)) {
25071
25403
  try {
25072
25404
  _fs.symlinkSync(target, linkPath);
@@ -25079,7 +25411,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
25079
25411
  }
25080
25412
  const deployedEntries = _fs.existsSync(claudeSkillsDir) ? _fs.readdirSync(claudeSkillsDir).filter((d) => d.startsWith("olam-")) : [];
25081
25413
  for (const entry of deployedEntries) {
25082
- const linkPath = path43.join(claudeSkillsDir, entry);
25414
+ const linkPath = path44.join(claudeSkillsDir, entry);
25083
25415
  let isSymlink = false;
25084
25416
  try {
25085
25417
  isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
@@ -25104,9 +25436,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
25104
25436
 
25105
25437
  // src/commands/update.ts
25106
25438
  var PACKAGE_NAME = "@pleri/olam-cli";
25107
- var CACHE_DIR2 = path45.join(os25.homedir(), ".olam", "cache");
25108
- var LOG_DIR2 = path45.join(os25.homedir(), ".olam", "log");
25109
- var LAST_STABLE_FILE = path45.join(CACHE_DIR2, "last-stable.txt");
25439
+ var CACHE_DIR2 = path46.join(os25.homedir(), ".olam", "cache");
25440
+ var LOG_DIR2 = path46.join(os25.homedir(), ".olam", "log");
25441
+ var LAST_STABLE_FILE = path46.join(CACHE_DIR2, "last-stable.txt");
25110
25442
  function defaultExec(cmd) {
25111
25443
  try {
25112
25444
  const stdout = execSync13(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
@@ -25135,12 +25467,12 @@ function readLastStable(file = LAST_STABLE_FILE) {
25135
25467
  }
25136
25468
  }
25137
25469
  function writeLastStable(version, file = LAST_STABLE_FILE) {
25138
- fs42.mkdirSync(path45.dirname(file), { recursive: true });
25470
+ fs42.mkdirSync(path46.dirname(file), { recursive: true });
25139
25471
  fs42.writeFileSync(file, version, { mode: 420 });
25140
25472
  }
25141
25473
  function logUpdateFailure(stderr) {
25142
25474
  const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
25143
- const logFile = path45.join(LOG_DIR2, `update-${ts}.log`);
25475
+ const logFile = path46.join(LOG_DIR2, `update-${ts}.log`);
25144
25476
  try {
25145
25477
  fs42.mkdirSync(LOG_DIR2, { recursive: true });
25146
25478
  fs42.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
@@ -25230,8 +25562,8 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
25230
25562
  let symlinkResult = { added: [], removed: [] };
25231
25563
  if (npmRootResult.exitCode === 0) {
25232
25564
  const npmRoot = npmRootResult.stdout.trim();
25233
- const npmSkillsDir = path45.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
25234
- const claudeSkillsDir = path45.join(os25.homedir(), ".claude", "skills");
25565
+ const npmSkillsDir = path46.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
25566
+ const claudeSkillsDir = path46.join(os25.homedir(), ".claude", "skills");
25235
25567
  const rec = _reconcile(npmSkillsDir, claudeSkillsDir);
25236
25568
  symlinkResult = { added: rec.added, removed: rec.removed };
25237
25569
  if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
@@ -25277,8 +25609,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
25277
25609
  if (npmRootResult.exitCode === 0) {
25278
25610
  const npmRoot = npmRootResult.stdout.trim();
25279
25611
  _reconcile(
25280
- path45.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
25281
- path45.join(os25.homedir(), ".claude", "skills")
25612
+ path46.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
25613
+ path46.join(os25.homedir(), ".claude", "skills")
25282
25614
  );
25283
25615
  }
25284
25616
  return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
@@ -25370,10 +25702,10 @@ init_store2();
25370
25702
  init_store2();
25371
25703
  import * as fs43 from "node:fs";
25372
25704
  import * as os26 from "node:os";
25373
- import * as path46 from "node:path";
25705
+ import * as path47 from "node:path";
25374
25706
  function expandPath(p) {
25375
25707
  if (p === "~" || p.startsWith("~/")) {
25376
- return path46.join(os26.homedir(), p.slice(1));
25708
+ return path47.join(os26.homedir(), p.slice(1));
25377
25709
  }
25378
25710
  return p;
25379
25711
  }
@@ -25782,8 +26114,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
25782
26114
  function authHeaders() {
25783
26115
  return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
25784
26116
  }
25785
- async function apiFetch(path52, init = {}) {
25786
- const res = await fetch(`${BASE_URL}${path52}`, {
26117
+ async function apiFetch(path53, init = {}) {
26118
+ const res = await fetch(`${BASE_URL}${path53}`, {
25787
26119
  ...init,
25788
26120
  headers: {
25789
26121
  "Content-Type": "application/json",
@@ -26045,7 +26377,7 @@ import pc29 from "picocolors";
26045
26377
  // src/commands/mcp/import-discovery.ts
26046
26378
  import * as fs45 from "node:fs";
26047
26379
  import * as os27 from "node:os";
26048
- import * as path47 from "node:path";
26380
+ import * as path48 from "node:path";
26049
26381
  function readJsonFile(filePath) {
26050
26382
  try {
26051
26383
  const raw = fs45.readFileSync(filePath, "utf-8");
@@ -26077,18 +26409,18 @@ function extractMcpServers(obj, source, sourceLabel) {
26077
26409
  }
26078
26410
  function getClaudeDesktopPath() {
26079
26411
  if (process.platform === "darwin") {
26080
- return path47.join(os27.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
26412
+ return path48.join(os27.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
26081
26413
  }
26082
26414
  if (process.platform === "win32") {
26083
- const appData = process.env["APPDATA"] ?? path47.join(os27.homedir(), "AppData", "Roaming");
26084
- return path47.join(appData, "Claude", "claude_desktop_config.json");
26415
+ const appData = process.env["APPDATA"] ?? path48.join(os27.homedir(), "AppData", "Roaming");
26416
+ return path48.join(appData, "Claude", "claude_desktop_config.json");
26085
26417
  }
26086
- return path47.join(os27.homedir(), ".config", "Claude", "claude_desktop_config.json");
26418
+ return path48.join(os27.homedir(), ".config", "Claude", "claude_desktop_config.json");
26087
26419
  }
26088
26420
  function getOlamRepoPaths() {
26089
26421
  const configPaths = [
26090
- path47.join(os27.homedir(), ".olam", "config.yaml"),
26091
- path47.join(process.cwd(), ".olam", "config.yaml")
26422
+ path48.join(os27.homedir(), ".olam", "config.yaml"),
26423
+ path48.join(process.cwd(), ".olam", "config.yaml")
26092
26424
  ];
26093
26425
  const paths = [];
26094
26426
  for (const configPath of configPaths) {
@@ -26110,7 +26442,7 @@ async function discoverMcpSources(repoPaths) {
26110
26442
  const sources = [];
26111
26443
  const sourceDefs = [
26112
26444
  {
26113
- path: path47.join(os27.homedir(), ".claude.json"),
26445
+ path: path48.join(os27.homedir(), ".claude.json"),
26114
26446
  label: "Claude Code (~/.claude.json)"
26115
26447
  },
26116
26448
  {
@@ -26118,19 +26450,19 @@ async function discoverMcpSources(repoPaths) {
26118
26450
  label: "Claude Desktop"
26119
26451
  },
26120
26452
  {
26121
- path: path47.join(os27.homedir(), ".cursor", "mcp.json"),
26453
+ path: path48.join(os27.homedir(), ".cursor", "mcp.json"),
26122
26454
  label: "Cursor (~/.cursor/mcp.json)"
26123
26455
  },
26124
26456
  {
26125
- path: path47.join(os27.homedir(), ".codeium", "windsurf", "mcp_config.json"),
26457
+ path: path48.join(os27.homedir(), ".codeium", "windsurf", "mcp_config.json"),
26126
26458
  label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
26127
26459
  }
26128
26460
  ];
26129
26461
  const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
26130
26462
  for (const repoPath of resolvedRepoPaths) {
26131
26463
  sourceDefs.push({
26132
- path: path47.join(repoPath, ".mcp.json"),
26133
- label: `.mcp.json (${path47.basename(repoPath)})`
26464
+ path: path48.join(repoPath, ".mcp.json"),
26465
+ label: `.mcp.json (${path48.basename(repoPath)})`
26134
26466
  });
26135
26467
  }
26136
26468
  const reads = await Promise.all(
@@ -26360,12 +26692,12 @@ function registerMcp(program2) {
26360
26692
  }
26361
26693
 
26362
26694
  // src/commands/kg-build.ts
26363
- import { spawnSync as spawnSync14 } from "node:child_process";
26695
+ import { spawnSync as spawnSync15 } from "node:child_process";
26364
26696
  import fs48 from "node:fs";
26365
- import path50 from "node:path";
26697
+ import path51 from "node:path";
26366
26698
 
26367
26699
  // ../core/dist/kg/storage-paths.js
26368
- import { homedir as homedir26 } from "node:os";
26700
+ import { homedir as homedir27 } from "node:os";
26369
26701
  import { join as join48, resolve as resolve10 } from "node:path";
26370
26702
 
26371
26703
  // ../core/dist/world/workspace-name.js
@@ -26387,7 +26719,7 @@ function validateWorkspaceName(name) {
26387
26719
 
26388
26720
  // ../core/dist/kg/storage-paths.js
26389
26721
  function olamHome3() {
26390
- return process.env.OLAM_HOME ?? join48(homedir26(), ".olam");
26722
+ return process.env.OLAM_HOME ?? join48(homedir27(), ".olam");
26391
26723
  }
26392
26724
  function kgRoot() {
26393
26725
  return join48(olamHome3(), "kg");
@@ -26395,17 +26727,17 @@ function kgRoot() {
26395
26727
  function worldsRoot() {
26396
26728
  return join48(olamHome3(), "worlds");
26397
26729
  }
26398
- function assertWithinPrefix(path52, prefix, label) {
26399
- if (!path52.startsWith(prefix + "/")) {
26400
- throw new Error(`${label} escape: ${path52} not under ${prefix}/`);
26730
+ function assertWithinPrefix(path53, prefix, label) {
26731
+ if (!path53.startsWith(prefix + "/")) {
26732
+ throw new Error(`${label} escape: ${path53} not under ${prefix}/`);
26401
26733
  }
26402
26734
  }
26403
26735
  function kgPristinePath(workspace) {
26404
26736
  validateWorkspaceName(workspace);
26405
26737
  const root = kgRoot();
26406
- const path52 = resolve10(join48(root, workspace));
26407
- assertWithinPrefix(path52, root, "kgPristinePath");
26408
- return path52;
26738
+ const path53 = resolve10(join48(root, workspace));
26739
+ assertWithinPrefix(path53, root, "kgPristinePath");
26740
+ return path53;
26409
26741
  }
26410
26742
  var KG_PATHS_INTERNALS = Object.freeze({
26411
26743
  olamHome: olamHome3,
@@ -26418,21 +26750,19 @@ init_output();
26418
26750
 
26419
26751
  // src/commands/kg-status.ts
26420
26752
  import fs46 from "node:fs";
26421
- import { homedir as homedir27 } from "node:os";
26422
- import path48 from "node:path";
26753
+ import { homedir as homedir28 } from "node:os";
26754
+ import path49 from "node:path";
26423
26755
  init_output();
26424
- var SOFT_CAP_BYTES = 15e8;
26425
- var HARD_CAP_BYTES = 5e9;
26426
26756
  function olamHome4() {
26427
- return process.env.OLAM_HOME ?? path48.join(homedir27(), ".olam");
26757
+ return process.env.OLAM_HOME ?? path49.join(homedir28(), ".olam");
26428
26758
  }
26429
26759
  function kgRoot2() {
26430
- return path48.join(olamHome4(), "kg");
26760
+ return path49.join(olamHome4(), "kg");
26431
26761
  }
26432
26762
  function worldsRoot2() {
26433
- return path48.join(olamHome4(), "worlds");
26763
+ return path49.join(olamHome4(), "worlds");
26434
26764
  }
26435
- function dirSizeBytes(dir) {
26765
+ function dirSizeBytes2(dir) {
26436
26766
  if (!fs46.existsSync(dir)) return 0;
26437
26767
  let total = 0;
26438
26768
  const stack = [dir];
@@ -26445,7 +26775,7 @@ function dirSizeBytes(dir) {
26445
26775
  continue;
26446
26776
  }
26447
26777
  for (const entry of entries) {
26448
- const full = path48.join(cur, entry.name);
26778
+ const full = path49.join(cur, entry.name);
26449
26779
  if (entry.isSymbolicLink()) continue;
26450
26780
  if (entry.isDirectory()) {
26451
26781
  stack.push(full);
@@ -26459,14 +26789,14 @@ function dirSizeBytes(dir) {
26459
26789
  }
26460
26790
  return total;
26461
26791
  }
26462
- function formatBytes4(n) {
26792
+ function formatBytes5(n) {
26463
26793
  if (n < 1024) return `${n} B`;
26464
26794
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
26465
26795
  if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
26466
26796
  return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
26467
26797
  }
26468
26798
  function readFreshness(workspace) {
26469
- const file = path48.join(kgPristinePath(workspace), "freshness.json");
26799
+ const file = path49.join(kgPristinePath(workspace), "freshness.json");
26470
26800
  if (!fs46.existsSync(file)) return null;
26471
26801
  try {
26472
26802
  const raw = JSON.parse(fs46.readFileSync(file, "utf-8"));
@@ -26477,7 +26807,7 @@ function readFreshness(workspace) {
26477
26807
  }
26478
26808
  }
26479
26809
  function readOverlayNodeCount(graphifyOutDir) {
26480
- const graphPath = path48.join(graphifyOutDir, "graph.json");
26810
+ const graphPath = path49.join(graphifyOutDir, "graph.json");
26481
26811
  if (!fs46.existsSync(graphPath)) return null;
26482
26812
  try {
26483
26813
  const raw = JSON.parse(fs46.readFileSync(graphPath, "utf-8"));
@@ -26503,7 +26833,7 @@ function listOverlays() {
26503
26833
  for (const worldEntry of worldDirs) {
26504
26834
  if (!worldEntry.isDirectory()) continue;
26505
26835
  const worldId = worldEntry.name;
26506
- const worldDir = path48.join(root, worldId);
26836
+ const worldDir = path49.join(root, worldId);
26507
26837
  let cloneDirs;
26508
26838
  try {
26509
26839
  cloneDirs = fs46.readdirSync(worldDir, { withFileTypes: true });
@@ -26512,13 +26842,13 @@ function listOverlays() {
26512
26842
  }
26513
26843
  for (const cloneEntry of cloneDirs) {
26514
26844
  if (!cloneEntry.isDirectory()) continue;
26515
- const graphifyOut = path48.join(worldDir, cloneEntry.name, "graphify-out");
26845
+ const graphifyOut = path49.join(worldDir, cloneEntry.name, "graphify-out");
26516
26846
  if (!fs46.existsSync(graphifyOut)) continue;
26517
26847
  records.push({
26518
26848
  world_id: worldId,
26519
26849
  clone_dir: cloneEntry.name,
26520
26850
  graphify_out_path: graphifyOut,
26521
- graphify_out_size_bytes: dirSizeBytes(graphifyOut),
26851
+ graphify_out_size_bytes: dirSizeBytes2(graphifyOut),
26522
26852
  node_count: readOverlayNodeCount(graphifyOut)
26523
26853
  });
26524
26854
  }
@@ -26544,8 +26874,8 @@ function listPristines(overlays) {
26544
26874
  continue;
26545
26875
  }
26546
26876
  const fresh = readFreshness(workspace);
26547
- const graphifyOut = path48.join(kgPristinePath(workspace), "graphify-out");
26548
- const size = dirSizeBytes(graphifyOut);
26877
+ const graphifyOut = path49.join(kgPristinePath(workspace), "graphify-out");
26878
+ const size = dirSizeBytes2(graphifyOut);
26549
26879
  const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
26550
26880
  records.push({
26551
26881
  workspace,
@@ -26577,7 +26907,7 @@ function buildReport(workspaceFilter) {
26577
26907
  cap_status: classifyCap(totalBytes)
26578
26908
  };
26579
26909
  }
26580
- function renderHuman(report, workspaceFilter) {
26910
+ function renderHuman2(report, workspaceFilter) {
26581
26911
  const lines = [];
26582
26912
  if (report.pristines.length === 0 && report.overlays.length === 0) {
26583
26913
  if (workspaceFilter) {
@@ -26605,7 +26935,7 @@ function renderHuman(report, workspaceFilter) {
26605
26935
  p.workspace.padEnd(24),
26606
26936
  (p.built_at ?? "\u2014").padEnd(22),
26607
26937
  String(p.node_count ?? "\u2014").padStart(8),
26608
- formatBytes4(p.graphify_out_size_bytes).padStart(10),
26938
+ formatBytes5(p.graphify_out_size_bytes).padStart(10),
26609
26939
  String(p.world_count).padStart(7)
26610
26940
  ].join(" ")
26611
26941
  );
@@ -26629,13 +26959,13 @@ function renderHuman(report, workspaceFilter) {
26629
26959
  o.world_id.padEnd(24),
26630
26960
  o.clone_dir.padEnd(20),
26631
26961
  String(o.node_count ?? "\u2014").padStart(8),
26632
- formatBytes4(o.graphify_out_size_bytes).padStart(10)
26962
+ formatBytes5(o.graphify_out_size_bytes).padStart(10)
26633
26963
  ].join(" ")
26634
26964
  );
26635
26965
  }
26636
26966
  lines.push("");
26637
26967
  }
26638
- lines.push(`Total: ${formatBytes4(report.total_bytes)} (cap: ${report.cap_status})`);
26968
+ lines.push(`Total: ${formatBytes5(report.total_bytes)} (cap: ${report.cap_status})`);
26639
26969
  return lines.join("\n");
26640
26970
  }
26641
26971
  async function runKgStatus(workspaceArg, opts) {
@@ -26652,15 +26982,15 @@ async function runKgStatus(workspaceArg, opts) {
26652
26982
  if (opts.json) {
26653
26983
  process.stdout.write(JSON.stringify(report, null, 2) + "\n");
26654
26984
  } else {
26655
- process.stdout.write(renderHuman(report, workspaceArg) + "\n");
26985
+ process.stdout.write(renderHuman2(report, workspaceArg) + "\n");
26656
26986
  }
26657
26987
  if (report.cap_status === "soft-warn") {
26658
26988
  printWarning(
26659
- `KG storage at ${formatBytes4(report.total_bytes)} \u2014 exceeds 1.5GB soft cap. Consider pruning stale pristines via \`rm -rf ~/.olam/kg/<workspace>\` after operator review.`
26989
+ `KG storage at ${formatBytes5(report.total_bytes)} \u2014 exceeds 1.5GB soft cap. Consider pruning stale pristines via \`rm -rf ~/.olam/kg/<workspace>\` after operator review.`
26660
26990
  );
26661
26991
  } else if (report.cap_status === "hard-critical") {
26662
26992
  printError(
26663
- `KG storage at ${formatBytes4(report.total_bytes)} \u2014 exceeds 5GB hard cap. Prune stale pristines or overlays before running \`olam kg build\` again.`
26993
+ `KG storage at ${formatBytes5(report.total_bytes)} \u2014 exceeds 5GB hard cap. Prune stale pristines or overlays before running \`olam kg build\` again.`
26664
26994
  );
26665
26995
  return { exitCode: 1, report };
26666
26996
  }
@@ -26678,10 +27008,10 @@ function registerKgStatusCommand(kg) {
26678
27008
  // src/commands/kg-watch.ts
26679
27009
  import { spawn as spawn7 } from "node:child_process";
26680
27010
  import fs47 from "node:fs";
26681
- import path49 from "node:path";
27011
+ import path50 from "node:path";
26682
27012
  init_output();
26683
27013
  function pidFilePath(workspace) {
26684
- return path49.join(kgPristinePath(workspace), ".watch.pid");
27014
+ return path50.join(kgPristinePath(workspace), ".watch.pid");
26685
27015
  }
26686
27016
  function isPidAlive3(pid) {
26687
27017
  if (!Number.isInteger(pid) || pid <= 0) return false;
@@ -26715,7 +27045,7 @@ function readAndClassifyPid(workspace) {
26715
27045
  }
26716
27046
  function writePidFile(workspace, pid) {
26717
27047
  const file = pidFilePath(workspace);
26718
- const dir = path49.dirname(file);
27048
+ const dir = path50.dirname(file);
26719
27049
  fs47.mkdirSync(dir, { recursive: true });
26720
27050
  fs47.writeFileSync(file, String(pid), { encoding: "utf-8" });
26721
27051
  }
@@ -26728,7 +27058,7 @@ function removePidFile(workspace) {
26728
27058
  }
26729
27059
  async function runKgWatch(workspaceArg, opts, deps = {}) {
26730
27060
  const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
26731
- const name = workspaceArg ?? path49.basename(cwd).toLowerCase();
27061
+ const name = workspaceArg ?? path50.basename(cwd).toLowerCase();
26732
27062
  try {
26733
27063
  validateWorkspaceName(name);
26734
27064
  } catch (err) {
@@ -26736,7 +27066,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
26736
27066
  return { exitCode: 1, pidWritten: false };
26737
27067
  }
26738
27068
  const pristinePath = kgPristinePath(name);
26739
- const graphPath = path49.join(pristinePath, "graphify-out", "graph.json");
27069
+ const graphPath = path50.join(pristinePath, "graphify-out", "graph.json");
26740
27070
  const pidState = readAndClassifyPid(name);
26741
27071
  if (pidState.status === "active") {
26742
27072
  printError(
@@ -26802,19 +27132,19 @@ function registerKgWatchCommand(kg) {
26802
27132
  var DEFAULT_DEVBOX_IMAGE2 = "olam-devbox:latest";
26803
27133
  function resolveWorkspace(arg) {
26804
27134
  const cwd = process.cwd();
26805
- const name = arg ?? path50.basename(cwd).toLowerCase();
27135
+ const name = arg ?? path51.basename(cwd).toLowerCase();
26806
27136
  validateWorkspaceName(name);
26807
27137
  return { name, sourcePath: cwd };
26808
27138
  }
26809
27139
  function copyWorkspaceToScratch(source, scratch) {
26810
27140
  if (process.platform === "darwin") {
26811
- const r2 = spawnSync14("cp", ["-c", "-r", source + "/.", scratch], {
27141
+ const r2 = spawnSync15("cp", ["-c", "-r", source + "/.", scratch], {
26812
27142
  stdio: ["ignore", "ignore", "pipe"],
26813
27143
  encoding: "utf-8"
26814
27144
  });
26815
27145
  if (r2.status === 0) return "cp-c-r-reflink";
26816
27146
  }
26817
- const r = spawnSync14("cp", ["-r", source + "/.", scratch], {
27147
+ const r = spawnSync15("cp", ["-r", source + "/.", scratch], {
26818
27148
  stdio: ["ignore", "ignore", "pipe"],
26819
27149
  encoding: "utf-8"
26820
27150
  });
@@ -26824,7 +27154,7 @@ function copyWorkspaceToScratch(source, scratch) {
26824
27154
  return "cp-r";
26825
27155
  }
26826
27156
  function parseNodeCount(graphifyOutDir) {
26827
- const graphPath = path50.join(graphifyOutDir, "graph.json");
27157
+ const graphPath = path51.join(graphifyOutDir, "graph.json");
26828
27158
  if (!fs48.existsSync(graphPath)) return null;
26829
27159
  try {
26830
27160
  const content = fs48.readFileSync(graphPath, "utf-8");
@@ -26835,7 +27165,7 @@ function parseNodeCount(graphifyOutDir) {
26835
27165
  }
26836
27166
  }
26837
27167
  function readGraphifyVersion(image) {
26838
- const r = spawnSync14(
27168
+ const r = spawnSync15(
26839
27169
  "docker",
26840
27170
  [
26841
27171
  "run",
@@ -26861,7 +27191,7 @@ async function runKgBuild(workspaceArg, options = {}) {
26861
27191
  return { exitCode: 2 };
26862
27192
  }
26863
27193
  const outDir = kgPristinePath(workspace.name);
26864
- const scratchDir = path50.join(outDir, "scratch");
27194
+ const scratchDir = path51.join(outDir, "scratch");
26865
27195
  fs48.mkdirSync(outDir, { recursive: true });
26866
27196
  if (fs48.existsSync(scratchDir)) fs48.rmSync(scratchDir, { recursive: true, force: true });
26867
27197
  fs48.mkdirSync(scratchDir);
@@ -26887,13 +27217,13 @@ async function runKgBuild(workspaceArg, options = {}) {
26887
27217
  "update",
26888
27218
  "."
26889
27219
  ];
26890
- const r = human ? spawnSync14("docker", dockerArgs, { stdio: "inherit" }) : spawnSync14("docker", dockerArgs, { stdio: ["ignore", "ignore", "pipe"] });
27220
+ const r = human ? spawnSync15("docker", dockerArgs, { stdio: "inherit" }) : spawnSync15("docker", dockerArgs, { stdio: ["ignore", "ignore", "pipe"] });
26891
27221
  if (r.status !== 0) {
26892
27222
  printError(`graphify update failed (exit ${r.status})`);
26893
27223
  return { exitCode: r.status ?? 1 };
26894
27224
  }
26895
- const scratchOut = path50.join(scratchDir, "graphify-out");
26896
- const finalOut = path50.join(outDir, "graphify-out");
27225
+ const scratchOut = path51.join(scratchDir, "graphify-out");
27226
+ const finalOut = path51.join(outDir, "graphify-out");
26897
27227
  if (!fs48.existsSync(scratchOut)) {
26898
27228
  printError(`graphify produced no graphify-out/ in scratch (${scratchOut})`);
26899
27229
  return { exitCode: 1 };
@@ -26912,7 +27242,7 @@ async function runKgBuild(workspaceArg, options = {}) {
26912
27242
  scratch_strategy: scratchStrategy
26913
27243
  };
26914
27244
  fs48.writeFileSync(
26915
- path50.join(outDir, "freshness.json"),
27245
+ path51.join(outDir, "freshness.json"),
26916
27246
  JSON.stringify(freshness, null, 2) + "\n",
26917
27247
  "utf-8"
26918
27248
  );
@@ -26945,12 +27275,12 @@ function registerKg(program2) {
26945
27275
 
26946
27276
  // src/pleri-config.ts
26947
27277
  import * as fs49 from "node:fs";
26948
- import * as path51 from "node:path";
27278
+ import * as path52 from "node:path";
26949
27279
  function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
26950
27280
  if (process.env.PLERI_BASE_URL) {
26951
27281
  return true;
26952
27282
  }
26953
- const configPath = path51.join(configDir, "config.yaml");
27283
+ const configPath = path52.join(configDir, "config.yaml");
26954
27284
  if (!fs49.existsSync(configPath)) {
26955
27285
  return false;
26956
27286
  }
@@ -26992,6 +27322,7 @@ registerWorldSnapshot(program);
26992
27322
  registerRefresh(program);
26993
27323
  registerBootstrap(program);
26994
27324
  registerDiagnose(program);
27325
+ registerDoctor(program);
26995
27326
  registerUpdate(program);
26996
27327
  registerBegin(program);
26997
27328
  registerStop(program);