@pleri/olam-cli 0.1.81 → 0.1.83

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: path48, errorMaps, issueData } = params;
491
- const fullPath = [...path48, ...issueData.path || []];
490
+ const { data, path: path49, errorMaps, issueData } = params;
491
+ const fullPath = [...path49, ...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, path48, key) {
799
+ constructor(parent, value, path49, key) {
800
800
  this._cachedPath = [];
801
801
  this.parent = parent;
802
802
  this.data = value;
803
- this._path = path48;
803
+ this._path = path49;
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, path48, ctx, rejectSource) {
4284
+ function refineForbiddenKeys(value, path49, 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, path48, ctx, rejectSource) {
4289
4289
  if (FORBIDDEN_KEYS.has(key)) {
4290
4290
  ctx.addIssue({
4291
4291
  code: external_exports.ZodIssueCode.custom,
4292
- path: [...path48, key],
4292
+ path: [...path49, key],
4293
4293
  message: `forbidden key "${key}" (prototype-pollution surface)`
4294
4294
  });
4295
4295
  continue;
4296
4296
  }
4297
- if (rejectSource && path48.length === 0 && key === "source") {
4297
+ if (rejectSource && path49.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, path48, ctx, rejectSource) {
4302
4302
  });
4303
4303
  continue;
4304
4304
  }
4305
- refineForbiddenKeys(value[key], [...path48, key], ctx, false);
4305
+ refineForbiddenKeys(value[key], [...path49, key], ctx, false);
4306
4306
  }
4307
4307
  }
4308
- function rejectForbiddenKeys(value, path48, rejectSource) {
4308
+ function rejectForbiddenKeys(value, path49, 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] ${path48}: forbidden key "${key}" (prototype-pollution surface)`);
4314
+ throw new Error(`[manifest] ${path49}: forbidden key "${key}" (prototype-pollution surface)`);
4315
4315
  }
4316
4316
  if (rejectSource && key === "source") {
4317
- throw new Error(`[manifest] ${path48}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
4317
+ throw new Error(`[manifest] ${path49}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
4318
4318
  }
4319
- rejectForbiddenKeys(value[key], `${path48}.${key}`, false);
4319
+ rejectForbiddenKeys(value[key], `${path49}.${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, path48, body, attempt = 0) {
5313
- const url = `${this.baseUrl}${path48}`;
5312
+ async request(method, path49, body, attempt = 0) {
5313
+ const url = `${this.baseUrl}${path49}`;
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, path48, body, attempt + 1);
5331
+ return this.request(method, path49, body, attempt + 1);
5332
5332
  }
5333
5333
  throw err;
5334
5334
  } finally {
@@ -6819,8 +6819,8 @@ var init_provider3 = __esm({
6819
6819
  // -----------------------------------------------------------------------
6820
6820
  // Internal fetch helper
6821
6821
  // -----------------------------------------------------------------------
6822
- async request(path48, method, body) {
6823
- const url = `${this.config.workerUrl}${path48}`;
6822
+ async request(path49, method, body) {
6823
+ const url = `${this.config.workerUrl}${path49}`;
6824
6824
  const bearer = await this.config.mintToken();
6825
6825
  const headers = {
6826
6826
  Authorization: `Bearer ${bearer}`
@@ -8112,8 +8112,8 @@ import { execFileSync as execFileSync3 } from "node:child_process";
8112
8112
  import * as fs14 from "node:fs";
8113
8113
  import * as os9 from "node:os";
8114
8114
  import * as path15 from "node:path";
8115
- function expandHome(p, homedir25) {
8116
- return p.replace(/^~(?=$|\/|\\)/, homedir25());
8115
+ function expandHome(p, homedir26) {
8116
+ return p.replace(/^~(?=$|\/|\\)/, homedir26());
8117
8117
  }
8118
8118
  function sanitizeRepoFilename(name) {
8119
8119
  const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -8136,7 +8136,7 @@ ${stderr}`;
8136
8136
  }
8137
8137
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
8138
8138
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
8139
- const homedir25 = deps.homedir ?? (() => os9.homedir());
8139
+ const homedir26 = deps.homedir ?? (() => os9.homedir());
8140
8140
  const baselineDir = path15.join(workspacePath, ".olam", "baseline");
8141
8141
  try {
8142
8142
  fs14.mkdirSync(baselineDir, { recursive: true });
@@ -8152,7 +8152,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
8152
8152
  continue;
8153
8153
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
8154
8154
  const outPath = path15.join(baselineDir, filename);
8155
- const repoPath = expandHome(repo.path, homedir25);
8155
+ const repoPath = expandHome(repo.path, homedir26);
8156
8156
  if (!fs14.existsSync(repoPath)) {
8157
8157
  writeBaselineFile(outPath, `# repo: ${repo.name}
8158
8158
  # (skipped: path ${repoPath} does not exist)
@@ -13674,10 +13674,10 @@ async function readHostCpToken2() {
13674
13674
  if (!fs25.existsSync(tp)) return null;
13675
13675
  return fs25.readFileSync(tp, "utf-8").trim();
13676
13676
  }
13677
- async function callHostCpProxy(method, worldId, path48, body) {
13677
+ async function callHostCpProxy(method, worldId, path49, body) {
13678
13678
  const token = await readHostCpToken2();
13679
13679
  if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
13680
- const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path48}`;
13680
+ const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path49}`;
13681
13681
  try {
13682
13682
  const headers = {
13683
13683
  Authorization: `Bearer ${token}`
@@ -14136,16 +14136,16 @@ __export(machine_schema_exports, {
14136
14136
  readMachineConfig: () => readMachineConfig,
14137
14137
  writeMachineConfig: () => writeMachineConfig
14138
14138
  });
14139
- import * as fs40 from "node:fs";
14140
- import * as path43 from "node:path";
14141
- import * as os23 from "node:os";
14139
+ import * as fs41 from "node:fs";
14140
+ import * as path44 from "node:path";
14141
+ import * as os24 from "node:os";
14142
14142
  import { parse as parseYaml5, stringify as stringifyYaml5 } from "yaml";
14143
14143
  function readMachineConfig(configPath) {
14144
14144
  const p = configPath ?? DEFAULT_CONFIG_PATH;
14145
- if (!fs40.existsSync(p))
14145
+ if (!fs41.existsSync(p))
14146
14146
  return null;
14147
14147
  try {
14148
- const raw = fs40.readFileSync(p, "utf-8");
14148
+ const raw = fs41.readFileSync(p, "utf-8");
14149
14149
  const parsed = parseYaml5(raw);
14150
14150
  return MachineConfigSchema.parse(parsed);
14151
14151
  } catch {
@@ -14154,8 +14154,8 @@ function readMachineConfig(configPath) {
14154
14154
  }
14155
14155
  function writeMachineConfig(config, configPath) {
14156
14156
  const p = configPath ?? DEFAULT_CONFIG_PATH;
14157
- fs40.mkdirSync(path43.dirname(p), { recursive: true });
14158
- fs40.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
14157
+ fs41.mkdirSync(path44.dirname(p), { recursive: true });
14158
+ fs41.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
14159
14159
  }
14160
14160
  function initMachineConfig(opts = {}) {
14161
14161
  const configPath = opts.configPath ?? DEFAULT_CONFIG_PATH;
@@ -14178,9 +14178,9 @@ var init_machine_schema = __esm({
14178
14178
  channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
14179
14179
  auto_update: external_exports.boolean().default(true),
14180
14180
  telemetry: external_exports.boolean().default(true),
14181
- worlds_dir: external_exports.string().default(() => path43.join(os23.homedir(), ".olam", "worlds"))
14181
+ worlds_dir: external_exports.string().default(() => path44.join(os24.homedir(), ".olam", "worlds"))
14182
14182
  });
14183
- DEFAULT_CONFIG_PATH = path43.join(os23.homedir(), ".olam", "config.yaml");
14183
+ DEFAULT_CONFIG_PATH = path44.join(os24.homedir(), ".olam", "config.yaml");
14184
14184
  }
14185
14185
  });
14186
14186
 
@@ -14562,9 +14562,9 @@ var UnknownArchetypeError = class extends Error {
14562
14562
  };
14563
14563
  var ArchetypeCycleError = class extends Error {
14564
14564
  path;
14565
- constructor(path48) {
14566
- super(`Archetype inheritance cycle detected: ${path48.join(" \u2192 ")} \u2192 ${path48[0] ?? "?"}`);
14567
- this.path = path48;
14565
+ constructor(path49) {
14566
+ super(`Archetype inheritance cycle detected: ${path49.join(" \u2192 ")} \u2192 ${path49[0] ?? "?"}`);
14567
+ this.path = path49;
14568
14568
  this.name = "ArchetypeCycleError";
14569
14569
  }
14570
14570
  };
@@ -15196,8 +15196,8 @@ function runStep(label, cmd, args, opts = {}) {
15196
15196
  }
15197
15197
  async function confirm(message) {
15198
15198
  if (!process.stdin.isTTY) return true;
15199
- const { createInterface: createInterface4 } = await import("node:readline");
15200
- const rl = createInterface4({ input: process.stdin, output: process.stdout });
15199
+ const { createInterface: createInterface5 } = await import("node:readline");
15200
+ const rl = createInterface5({ input: process.stdin, output: process.stdout });
15201
15201
  return new Promise((resolve10) => {
15202
15202
  rl.question(`${message} [y/N] `, (answer) => {
15203
15203
  rl.close();
@@ -15929,9 +15929,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
15929
15929
  "These source files have changed since the image was built; the",
15930
15930
  "changes will NOT take effect in fresh worlds until you rebuild:"
15931
15931
  ];
15932
- for (const { path: path48, mtimeMs } of result.newerSources) {
15932
+ for (const { path: path49, mtimeMs } of result.newerSources) {
15933
15933
  const when = new Date(mtimeMs).toISOString();
15934
- lines.push(` \u2022 ${path48} (modified ${when})`);
15934
+ lines.push(` \u2022 ${path49} (modified ${when})`);
15935
15935
  }
15936
15936
  lines.push("");
15937
15937
  lines.push("Rebuild with:");
@@ -16090,15 +16090,15 @@ init_host_cp();
16090
16090
  var HOST_CP_URL = "http://127.0.0.1:19000";
16091
16091
  async function readHostCpTokenForCreate() {
16092
16092
  try {
16093
- const { default: fs46 } = await import("node:fs");
16094
- const { default: os27 } = await import("node:os");
16095
- const { default: path48 } = await import("node:path");
16096
- const tp = path48.join(
16097
- process.env.OLAM_HOME ?? path48.join(os27.homedir(), ".olam"),
16093
+ const { default: fs47 } = await import("node:fs");
16094
+ const { default: os28 } = await import("node:os");
16095
+ const { default: path49 } = await import("node:path");
16096
+ const tp = path49.join(
16097
+ process.env.OLAM_HOME ?? path49.join(os28.homedir(), ".olam"),
16098
16098
  "host-cp.token"
16099
16099
  );
16100
- if (!fs46.existsSync(tp)) return null;
16101
- return fs46.readFileSync(tp, "utf-8").trim();
16100
+ if (!fs47.existsSync(tp)) return null;
16101
+ return fs47.readFileSync(tp, "utf-8").trim();
16102
16102
  } catch {
16103
16103
  return null;
16104
16104
  }
@@ -16461,12 +16461,12 @@ function defaultNameFromPrompt(prompt) {
16461
16461
  }
16462
16462
  async function readHostCpToken3() {
16463
16463
  try {
16464
- const { default: fs46 } = await import("node:fs");
16465
- const { default: os27 } = await import("node:os");
16466
- const { default: path48 } = await import("node:path");
16467
- const tp = path48.join(os27.homedir(), ".olam", "host-cp.token");
16468
- if (!fs46.existsSync(tp)) return null;
16469
- const raw = fs46.readFileSync(tp, "utf-8").trim();
16464
+ const { default: fs47 } = await import("node:fs");
16465
+ const { default: os28 } = await import("node:os");
16466
+ const { default: path49 } = await import("node:path");
16467
+ const tp = path49.join(os28.homedir(), ".olam", "host-cp.token");
16468
+ if (!fs47.existsSync(tp)) return null;
16469
+ const raw = fs47.readFileSync(tp, "utf-8").trim();
16470
16470
  return raw.length > 0 ? raw : null;
16471
16471
  } catch {
16472
16472
  return null;
@@ -17149,11 +17149,381 @@ async function confirmInteractive() {
17149
17149
  });
17150
17150
  }
17151
17151
 
17152
+ // src/commands/implode.ts
17153
+ init_output();
17154
+ import { execFileSync as execFileSync7 } from "node:child_process";
17155
+ import * as fs30 from "node:fs";
17156
+ import * as os18 from "node:os";
17157
+ import * as path32 from "node:path";
17158
+ import { createInterface as createInterface2 } from "node:readline/promises";
17159
+ import pc14 from "picocolors";
17160
+ var NPM_PACKAGE = "@pleri/olam-cli";
17161
+ var realExec = (cmd, args) => {
17162
+ try {
17163
+ const stdout = execFileSync7(cmd, [...args], {
17164
+ encoding: "utf-8",
17165
+ stdio: ["ignore", "pipe", "pipe"]
17166
+ });
17167
+ return { exitCode: 0, stdout, stderr: "" };
17168
+ } catch (err) {
17169
+ const e = err;
17170
+ return {
17171
+ exitCode: e.status ?? 1,
17172
+ stdout: typeof e.stdout === "string" ? e.stdout : e.stdout?.toString("utf-8") ?? "",
17173
+ stderr: typeof e.stderr === "string" ? e.stderr : e.stderr?.toString("utf-8") ?? ""
17174
+ };
17175
+ }
17176
+ };
17177
+ function surveyOlam(opts = {}) {
17178
+ const exec = opts.exec ?? realExec;
17179
+ const home = opts.olamHome ?? path32.join(os18.homedir(), ".olam");
17180
+ const containers = listDocker(exec, ["ps", "-a", "--format", "{{.Names}}"]).filter(
17181
+ (n) => n.startsWith("olam-")
17182
+ );
17183
+ const images = listDocker(exec, ["images", "--format", "{{.Repository}}:{{.Tag}}"]).filter(
17184
+ (ref) => ref.startsWith("olam-") || ref.startsWith("ghcr.io/pleri/olam-") || ref.startsWith("ghcr.io/pleri/olam")
17185
+ );
17186
+ const volumes = listDocker(exec, ["volume", "ls", "--format", "{{.Name}}"]).filter(
17187
+ (n) => n.startsWith("olam-")
17188
+ );
17189
+ const networks = listDocker(exec, ["network", "ls", "--format", "{{.Name}}"]).filter(
17190
+ (n) => n.startsWith("olam-") && n !== "olam-host-cp-internal-default"
17191
+ );
17192
+ const worlds = [];
17193
+ const worldsDir = path32.join(home, "worlds");
17194
+ if (fs30.existsSync(worldsDir)) {
17195
+ for (const entry of fs30.readdirSync(worldsDir, { withFileTypes: true })) {
17196
+ if (!entry.isDirectory()) continue;
17197
+ const wPath = path32.join(worldsDir, entry.name);
17198
+ const bytes = dirSize(wPath);
17199
+ const { dirty, note } = inspectWorldGitState(wPath);
17200
+ worlds.push({ id: entry.name, bytes, dirty, note, path: wPath });
17201
+ }
17202
+ }
17203
+ const homeBytesNonWorld = fs30.existsSync(home) ? Math.max(0, dirSize(home) - worlds.reduce((acc, w) => acc + w.bytes, 0)) : 0;
17204
+ const npmRoot = exec("npm", ["root", "-g"]);
17205
+ const npmGlobalRoot = npmRoot.exitCode === 0 ? npmRoot.stdout.trim() : null;
17206
+ const npmInstalled = npmGlobalRoot !== null && fs30.existsSync(path32.join(npmGlobalRoot, NPM_PACKAGE));
17207
+ return {
17208
+ containers,
17209
+ images,
17210
+ volumes,
17211
+ networks,
17212
+ worlds,
17213
+ homeBytesNonWorld,
17214
+ npmInstalled,
17215
+ npmGlobalRoot
17216
+ };
17217
+ }
17218
+ function listDocker(exec, args) {
17219
+ const r = exec("docker", args);
17220
+ if (r.exitCode !== 0) return [];
17221
+ return r.stdout.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
17222
+ }
17223
+ function dirSize(p) {
17224
+ let total = 0;
17225
+ try {
17226
+ const stack = [p];
17227
+ while (stack.length > 0) {
17228
+ const cur = stack.pop();
17229
+ let entries;
17230
+ try {
17231
+ entries = fs30.readdirSync(cur, { withFileTypes: true });
17232
+ } catch {
17233
+ continue;
17234
+ }
17235
+ for (const e of entries) {
17236
+ const full = path32.join(cur, e.name);
17237
+ try {
17238
+ if (e.isDirectory()) stack.push(full);
17239
+ else if (e.isFile()) total += fs30.statSync(full).size;
17240
+ } catch {
17241
+ }
17242
+ }
17243
+ }
17244
+ } catch {
17245
+ }
17246
+ return total;
17247
+ }
17248
+ function inspectWorldGitState(worldPath) {
17249
+ const repoNotes = [];
17250
+ let dirty = false;
17251
+ try {
17252
+ for (const entry of fs30.readdirSync(worldPath, { withFileTypes: true })) {
17253
+ if (!entry.isDirectory()) continue;
17254
+ const repo = path32.join(worldPath, entry.name);
17255
+ const gitDir = path32.join(repo, ".git");
17256
+ if (!fs30.existsSync(gitDir)) continue;
17257
+ try {
17258
+ const status = execFileSync7("git", ["status", "--porcelain"], {
17259
+ cwd: repo,
17260
+ encoding: "utf-8",
17261
+ stdio: ["ignore", "pipe", "ignore"]
17262
+ }).trim();
17263
+ if (status.length > 0) {
17264
+ dirty = true;
17265
+ repoNotes.push(`${entry.name}: uncommitted`);
17266
+ continue;
17267
+ }
17268
+ } catch {
17269
+ continue;
17270
+ }
17271
+ try {
17272
+ const ahead = execFileSync7(
17273
+ "git",
17274
+ ["rev-list", "--count", "@{upstream}..HEAD"],
17275
+ { cwd: repo, encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
17276
+ ).trim();
17277
+ if (ahead && ahead !== "0") {
17278
+ dirty = true;
17279
+ repoNotes.push(`${entry.name}: ${ahead} unpushed`);
17280
+ }
17281
+ } catch {
17282
+ dirty = true;
17283
+ repoNotes.push(`${entry.name}: no-upstream`);
17284
+ }
17285
+ }
17286
+ } catch {
17287
+ }
17288
+ return { dirty, note: repoNotes.join("; ") };
17289
+ }
17290
+ function renderSurvey(survey, opts) {
17291
+ if (opts.json) {
17292
+ return JSON.stringify(
17293
+ {
17294
+ containers: survey.containers,
17295
+ images: survey.images,
17296
+ volumes: survey.volumes,
17297
+ networks: survey.networks,
17298
+ worlds: survey.worlds.map((w) => ({
17299
+ id: w.id,
17300
+ bytes: w.bytes,
17301
+ dirty: w.dirty,
17302
+ note: w.note
17303
+ })),
17304
+ homeBytesNonWorld: survey.homeBytesNonWorld,
17305
+ npmInstalled: survey.npmInstalled,
17306
+ npmGlobalRoot: survey.npmGlobalRoot
17307
+ },
17308
+ null,
17309
+ 2
17310
+ );
17311
+ }
17312
+ const lines = [];
17313
+ const dirtyWorlds = survey.worlds.filter((w) => w.dirty);
17314
+ const cleanWorlds = survey.worlds.filter((w) => !w.dirty);
17315
+ const worldBytes = survey.worlds.reduce((acc, w) => acc + w.bytes, 0);
17316
+ lines.push(pc14.bold(pc14.red("\u2014 olam implode survey \u2014")));
17317
+ lines.push("");
17318
+ lines.push(` containers (olam-*): ${survey.containers.length}`);
17319
+ lines.push(` images: ${survey.images.length}`);
17320
+ lines.push(` volumes: ${survey.volumes.length}`);
17321
+ lines.push(` networks: ${survey.networks.length}`);
17322
+ lines.push(
17323
+ ` worlds: ${survey.worlds.length} (${dirtyWorlds.length} dirty, ${cleanWorlds.length} clean)`
17324
+ );
17325
+ lines.push(` ~/.olam/* (non-world): ${formatBytes2(survey.homeBytesNonWorld)}`);
17326
+ lines.push(` worlds total: ${formatBytes2(worldBytes)}`);
17327
+ lines.push(
17328
+ ` npm package installed: ${survey.npmInstalled ? `yes (at ${survey.npmGlobalRoot}/${NPM_PACKAGE})` : "no"}`
17329
+ );
17330
+ if (dirtyWorlds.length > 0) {
17331
+ lines.push("");
17332
+ lines.push(pc14.yellow(` \u26A0 dirty worlds (${dirtyWorlds.length}) \u2014 pass --include-dirty to destroy:`));
17333
+ for (const w of dirtyWorlds) {
17334
+ lines.push(` - ${w.id} ${formatBytes2(w.bytes)} (${w.note})`);
17335
+ }
17336
+ }
17337
+ lines.push("");
17338
+ lines.push(pc14.dim(" Run with --yes to actually destroy. Default is dry-run."));
17339
+ return lines.join("\n");
17340
+ }
17341
+ function formatBytes2(n) {
17342
+ if (n < 1024) return `${n} B`;
17343
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
17344
+ if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
17345
+ return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
17346
+ }
17347
+ async function executeImplode(survey, opts) {
17348
+ const exec = opts.exec ?? realExec;
17349
+ const home = opts.olamHome ?? path32.join(os18.homedir(), ".olam");
17350
+ const removed = [];
17351
+ const skipped = [];
17352
+ const errors = [];
17353
+ if (!opts.keepWorlds) {
17354
+ const sortedContainers = [...survey.containers].sort((a, b) => {
17355
+ const aWorld = isWorldContainer(a);
17356
+ const bWorld = isWorldContainer(b);
17357
+ if (aWorld && !bWorld) return -1;
17358
+ if (!aWorld && bWorld) return 1;
17359
+ return 0;
17360
+ });
17361
+ for (const name of sortedContainers) {
17362
+ const r = exec("docker", ["rm", "-f", name]);
17363
+ if (r.exitCode === 0) removed.push(`container:${name}`);
17364
+ else errors.push(`container:${name}: ${r.stderr.trim()}`);
17365
+ }
17366
+ } else {
17367
+ for (const c of survey.containers) skipped.push(`container:${c}`);
17368
+ }
17369
+ if (!opts.keepImages) {
17370
+ for (const ref of survey.images) {
17371
+ const r = exec("docker", ["rmi", "-f", ref]);
17372
+ if (r.exitCode === 0) removed.push(`image:${ref}`);
17373
+ else errors.push(`image:${ref}: ${r.stderr.trim()}`);
17374
+ }
17375
+ } else {
17376
+ for (const i of survey.images) skipped.push(`image:${i}`);
17377
+ }
17378
+ if (!opts.keepVolumes && !opts.keepVault) {
17379
+ for (const v of survey.volumes) {
17380
+ const r = exec("docker", ["volume", "rm", "-f", v]);
17381
+ if (r.exitCode === 0) removed.push(`volume:${v}`);
17382
+ else errors.push(`volume:${v}: ${r.stderr.trim()}`);
17383
+ }
17384
+ } else if (opts.keepVault) {
17385
+ for (const v of survey.volumes) {
17386
+ if (v === "olam-auth-data" || v === "olam-mcp-auth-data") {
17387
+ skipped.push(`volume:${v} (--keep-vault)`);
17388
+ continue;
17389
+ }
17390
+ const r = exec("docker", ["volume", "rm", "-f", v]);
17391
+ if (r.exitCode === 0) removed.push(`volume:${v}`);
17392
+ else errors.push(`volume:${v}: ${r.stderr.trim()}`);
17393
+ }
17394
+ } else {
17395
+ for (const v of survey.volumes) skipped.push(`volume:${v}`);
17396
+ }
17397
+ if (!opts.keepNetworks) {
17398
+ for (const n of survey.networks) {
17399
+ const r = exec("docker", ["network", "rm", n]);
17400
+ if (r.exitCode === 0) removed.push(`network:${n}`);
17401
+ else errors.push(`network:${n}: ${r.stderr.trim()}`);
17402
+ }
17403
+ } else {
17404
+ for (const n of survey.networks) skipped.push(`network:${n}`);
17405
+ }
17406
+ if (fs30.existsSync(home)) {
17407
+ if (opts.keepVault) {
17408
+ for (const entry of fs30.readdirSync(home, { withFileTypes: true })) {
17409
+ if (entry.name === "auth-data") {
17410
+ skipped.push(`fs:~/.olam/auth-data (--keep-vault)`);
17411
+ continue;
17412
+ }
17413
+ const target = path32.join(home, entry.name);
17414
+ try {
17415
+ fs30.rmSync(target, { recursive: true, force: true });
17416
+ removed.push(`fs:${target}`);
17417
+ } catch (err) {
17418
+ errors.push(`fs:${target}: ${err.message}`);
17419
+ }
17420
+ }
17421
+ } else {
17422
+ try {
17423
+ fs30.rmSync(home, { recursive: true, force: true });
17424
+ removed.push(`fs:${home}`);
17425
+ } catch (err) {
17426
+ errors.push(`fs:${home}: ${err.message}`);
17427
+ }
17428
+ }
17429
+ }
17430
+ if (!opts.keepNpm && survey.npmInstalled) {
17431
+ const r = exec("npm", ["uninstall", "-g", NPM_PACKAGE]);
17432
+ if (r.exitCode === 0) removed.push(`npm:${NPM_PACKAGE}`);
17433
+ else errors.push(`npm:${NPM_PACKAGE}: ${r.stderr.trim()}`);
17434
+ } else if (opts.keepNpm) {
17435
+ skipped.push(`npm:${NPM_PACKAGE}`);
17436
+ }
17437
+ return { removed, skipped, errors };
17438
+ }
17439
+ function isWorldContainer(name) {
17440
+ const stack = /* @__PURE__ */ new Set(["olam-host-cp", "olam-auth", "olam-mcp-auth", "olam-docker-socket-proxy"]);
17441
+ return !stack.has(name);
17442
+ }
17443
+ async function readConfirmation() {
17444
+ const rl = createInterface2({ input: process.stdin, output: process.stdout });
17445
+ const answer = await rl.question('Type "implode" to proceed: ');
17446
+ rl.close();
17447
+ return answer.trim();
17448
+ }
17449
+ function registerImplode(program2) {
17450
+ program2.command("implode").description(
17451
+ "Destroy ALL local olam install + configs (containers, images, volumes, ~/.olam/, npm package). Default is dry-run."
17452
+ ).option("-y, --yes", "Actually destroy (default is dry-run)", false).option(
17453
+ "--include-dirty",
17454
+ "Also destroy worlds with uncommitted/unpushed work",
17455
+ false
17456
+ ).option("--keep-worlds", "Skip world container destruction", false).option("--keep-images", "Skip docker image removal", false).option("--keep-vault", "Preserve auth-service credentials (~/.olam/auth-data + olam-*-data volumes)", false).option("--keep-npm", "Skip global npm package uninstall", false).option("--keep-volumes", "Skip docker volume removal", false).option("--keep-networks", "Skip docker network removal", false).option("--json", "Emit machine-readable JSON survey", false).action(async (raw) => {
17457
+ const opts = {
17458
+ yes: raw.yes === true,
17459
+ includeDirty: raw.includeDirty === true,
17460
+ keepWorlds: raw.keepWorlds === true,
17461
+ keepImages: raw.keepImages === true,
17462
+ keepVault: raw.keepVault === true,
17463
+ keepNpm: raw.keepNpm === true,
17464
+ keepVolumes: raw.keepVolumes === true,
17465
+ keepNetworks: raw.keepNetworks === true,
17466
+ json: raw.json === true
17467
+ };
17468
+ const exitCode = await runImplode(opts);
17469
+ process.exitCode = exitCode;
17470
+ });
17471
+ }
17472
+ async function runImplode(opts) {
17473
+ const survey = surveyOlam({ exec: opts.exec, olamHome: opts.olamHome });
17474
+ if (opts.json && !opts.yes) {
17475
+ process.stdout.write(renderSurvey(survey, opts) + "\n");
17476
+ return 0;
17477
+ }
17478
+ if (!opts.yes) {
17479
+ process.stdout.write(renderSurvey(survey, opts) + "\n");
17480
+ return 0;
17481
+ }
17482
+ const dirty = survey.worlds.filter((w) => w.dirty);
17483
+ if (dirty.length > 0 && !opts.includeDirty && !opts.keepWorlds) {
17484
+ printError(
17485
+ `Refusing to destroy ${dirty.length} world(s) with uncommitted/unpushed work. Pass --include-dirty to override or --keep-worlds to skip world destruction.`
17486
+ );
17487
+ for (const w of dirty) {
17488
+ process.stderr.write(` - ${w.id} (${w.note})
17489
+ `);
17490
+ }
17491
+ return 2;
17492
+ }
17493
+ process.stdout.write(renderSurvey(survey, opts) + "\n");
17494
+ printWarning("This will permanently destroy the resources listed above.");
17495
+ printInfo("Project files", "~/Projects/* and ~/.claude/ are NOT touched.");
17496
+ const answer = opts.confirmAnswer ?? await readConfirmation();
17497
+ if (answer !== "implode") {
17498
+ printError(`Confirmation failed (got "${answer}", expected "implode"). Aborting.`);
17499
+ return 3;
17500
+ }
17501
+ printHeader("Imploding olam");
17502
+ const result = await executeImplode(survey, opts);
17503
+ for (const r of result.removed) printSuccess(`removed ${r}`);
17504
+ for (const s of result.skipped) printInfo("skipped", s);
17505
+ for (const e of result.errors) printError(e);
17506
+ printHeader("Implode complete");
17507
+ printInfo("Removed", String(result.removed.length));
17508
+ printInfo("Skipped", String(result.skipped.length));
17509
+ printInfo("Errors", String(result.errors.length));
17510
+ process.stdout.write("\n");
17511
+ process.stdout.write(`To reinstall a fresh copy:
17512
+ `);
17513
+ process.stdout.write(` ${pc14.cyan(`npm install -g ${NPM_PACKAGE}`)}
17514
+ `);
17515
+ process.stdout.write(` ${pc14.cyan("olam init")}
17516
+ `);
17517
+ process.stdout.write(` ${pc14.cyan("olam auth login")}
17518
+ `);
17519
+ return result.errors.length > 0 ? 1 : 0;
17520
+ }
17521
+
17152
17522
  // src/commands/enter.ts
17153
17523
  init_context();
17154
17524
  init_output();
17155
17525
  import { execSync as execSync8 } from "node:child_process";
17156
- import pc14 from "picocolors";
17526
+ import pc15 from "picocolors";
17157
17527
  var SAFE_IDENT3 = /^[a-z0-9][a-z0-9-]{0,63}$/;
17158
17528
  function buildStartClaudeCommands(containerName, sessionName, task) {
17159
17529
  if (!SAFE_IDENT3.test(containerName)) {
@@ -17260,7 +17630,7 @@ function registerEnter(program2) {
17260
17630
  }
17261
17631
  console.log("Run these commands in order to enter the world:\n");
17262
17632
  for (const step of steps) {
17263
- console.log(` ${pc14.dim(`# ${step.description}`)}`);
17633
+ console.log(` ${pc15.dim(`# ${step.description}`)}`);
17264
17634
  if (step.stdin !== void 0) {
17265
17635
  const escaped = step.stdin.replace(/'/g, "'\\''");
17266
17636
  console.log(` printf '%s' '${escaped}' | ${step.command}`);
@@ -17294,11 +17664,11 @@ function registerEnter(program2) {
17294
17664
  return;
17295
17665
  }
17296
17666
  console.log("Run this command to enter the world:\n");
17297
- console.log(` ${pc14.bold(result.command)}`);
17667
+ console.log(` ${pc15.bold(result.command)}`);
17298
17668
  const containerName = `olam-${worldId}-devbox`;
17299
17669
  console.log(
17300
17670
  `
17301
- ${pc14.dim(`Observe dispatch: docker exec -it ${containerName} tmux attach -t olam-dispatch -r`)}`
17671
+ ${pc15.dim(`Observe dispatch: docker exec -it ${containerName} tmux attach -t olam-dispatch -r`)}`
17302
17672
  );
17303
17673
  });
17304
17674
  }
@@ -17308,7 +17678,7 @@ init_context();
17308
17678
  init_output();
17309
17679
  init_exit_codes();
17310
17680
  init_world_paths();
17311
- import * as fs30 from "node:fs";
17681
+ import * as fs31 from "node:fs";
17312
17682
  import "node:path";
17313
17683
  import ora6 from "ora";
17314
17684
  function registerCrystallize(program2, options = {}) {
@@ -17340,7 +17710,7 @@ function registerCrystallize(program2, options = {}) {
17340
17710
  return;
17341
17711
  }
17342
17712
  const thoughtDbPath = getWorldDbPath(world.workspacePath);
17343
- if (!fs30.existsSync(thoughtDbPath)) {
17713
+ if (!fs31.existsSync(thoughtDbPath)) {
17344
17714
  printError(`No thoughts captured yet for "${worldId}". Run a dispatch first.`);
17345
17715
  process.exitCode = EXIT_GENERIC_ERROR;
17346
17716
  return;
@@ -17410,7 +17780,7 @@ function registerCrystallize(program2, options = {}) {
17410
17780
 
17411
17781
  // src/commands/pr.ts
17412
17782
  init_registry();
17413
- import pc15 from "picocolors";
17783
+ import pc16 from "picocolors";
17414
17784
 
17415
17785
  // ../core/dist/pr-gate/client.js
17416
17786
  var HOST_CONTROL_PLANE_BASE2 = 19080;
@@ -17491,26 +17861,26 @@ async function findGate(id) {
17491
17861
  return null;
17492
17862
  }
17493
17863
  function formatStateBadge(state) {
17494
- if (state === "approve") return pc15.green("approve");
17495
- if (state === "block") return pc15.red("block");
17496
- if (state === "denied") return pc15.gray("denied");
17497
- return pc15.yellow("pending");
17864
+ if (state === "approve") return pc16.green("approve");
17865
+ if (state === "block") return pc16.red("block");
17866
+ if (state === "denied") return pc16.gray("denied");
17867
+ return pc16.yellow("pending");
17498
17868
  }
17499
17869
  function registerPr(program2) {
17500
17870
  const pr = program2.command("pr").description("Review and decide PR-gate requests from running worlds");
17501
17871
  pr.command("list").description("List all PR-gate requests across every running world").action(async () => {
17502
17872
  const all = await fanoutList();
17503
17873
  if (all.length === 0) {
17504
- console.log(pc15.dim("No gates open."));
17874
+ console.log(pc16.dim("No gates open."));
17505
17875
  return;
17506
17876
  }
17507
17877
  printHeader(`${all.length} gate(s)`);
17508
17878
  for (const { world, gate } of all) {
17509
17879
  const badge = formatStateBadge(gate.state);
17510
17880
  console.log(
17511
- ` ${pc15.bold(gate.id.slice(0, 8))} ${badge.padEnd(20)} ${pc15.dim(world.name)} ${pc15.dim(gate.branch)}`
17881
+ ` ${pc16.bold(gate.id.slice(0, 8))} ${badge.padEnd(20)} ${pc16.dim(world.name)} ${pc16.dim(gate.branch)}`
17512
17882
  );
17513
- console.log(` ${pc15.dim(gate.command.slice(0, 100))}`);
17883
+ console.log(` ${pc16.dim(gate.command.slice(0, 100))}`);
17514
17884
  }
17515
17885
  });
17516
17886
  pr.command("show").description("Show full gate detail (diff, command, commits)").argument("<id>", "Gate id (prefix match ok)").action(async (id) => {
@@ -17533,9 +17903,9 @@ function registerPr(program2) {
17533
17903
  if (gate.reason) printInfo("Reason", gate.reason);
17534
17904
  }
17535
17905
  printHeader("Commits");
17536
- console.log(gate.commitLog || pc15.dim(" (empty)"));
17906
+ console.log(gate.commitLog || pc16.dim(" (empty)"));
17537
17907
  printHeader("Diff stat");
17538
- console.log(gate.diffStat || pc15.dim(" (empty)"));
17908
+ console.log(gate.diffStat || pc16.dim(" (empty)"));
17539
17909
  });
17540
17910
  function decideCommand(verb, decision) {
17541
17911
  pr.command(verb).description(`${verb[0].toUpperCase()}${verb.slice(1)} a pending gate`).argument("<id>", "Gate id").option("--reason <reason>", "Short free-text reason").option("--by <name>", "Deciding identity (defaults to $USER)", process.env["USER"] ?? "human").action(async (id, opts) => {
@@ -17660,7 +18030,7 @@ function registerLanes(program2) {
17660
18030
  // src/commands/policy-check.ts
17661
18031
  init_loader2();
17662
18032
  import { execSync as execSync9 } from "node:child_process";
17663
- import pc16 from "picocolors";
18033
+ import pc17 from "picocolors";
17664
18034
 
17665
18035
  // ../../node_modules/balanced-match/dist/esm/index.js
17666
18036
  var balanced = (a, b, str) => {
@@ -18714,11 +19084,11 @@ var qmarksTestNoExtDot = ([$0]) => {
18714
19084
  return (f) => f.length === len && f !== "." && f !== "..";
18715
19085
  };
18716
19086
  var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
18717
- var path33 = {
19087
+ var path34 = {
18718
19088
  win32: { sep: "\\" },
18719
19089
  posix: { sep: "/" }
18720
19090
  };
18721
- var sep = defaultPlatform === "win32" ? path33.win32.sep : path33.posix.sep;
19091
+ var sep = defaultPlatform === "win32" ? path34.win32.sep : path34.posix.sep;
18722
19092
  minimatch.sep = sep;
18723
19093
  var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
18724
19094
  minimatch.GLOBSTAR = GLOBSTAR;
@@ -19520,7 +19890,7 @@ function registerPolicyCheck(program2) {
19520
19890
  const workspaceRoot = opts.workspace ?? process.cwd();
19521
19891
  const policies = loadPolicies(workspaceRoot);
19522
19892
  if (policies.length === 0) {
19523
- console.log(pc16.dim("policy-check: no policies found in .olam/policies/ \u2014 nothing to enforce"));
19893
+ console.log(pc17.dim("policy-check: no policies found in .olam/policies/ \u2014 nothing to enforce"));
19524
19894
  return;
19525
19895
  }
19526
19896
  const diff = getDiff(opts.base, workspaceRoot);
@@ -19529,11 +19899,11 @@ function registerPolicyCheck(program2) {
19529
19899
  for (const result of results) {
19530
19900
  if (result.passed) continue;
19531
19901
  if (result.severity === "error") {
19532
- console.error(`${pc16.red("policy error")} [${result.policyId}]`);
19902
+ console.error(`${pc17.red("policy error")} [${result.policyId}]`);
19533
19903
  console.error(result.message);
19534
19904
  hasErrorFailure = true;
19535
19905
  } else {
19536
- console.warn(`${pc16.yellow("policy warn")} [${result.policyId}]`);
19906
+ console.warn(`${pc17.yellow("policy warn")} [${result.policyId}]`);
19537
19907
  console.warn(result.message);
19538
19908
  }
19539
19909
  }
@@ -19544,7 +19914,7 @@ function registerPolicyCheck(program2) {
19544
19914
  }
19545
19915
 
19546
19916
  // src/commands/worldspec/compile.ts
19547
- import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "node:fs";
19917
+ import { existsSync as existsSync32, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "node:fs";
19548
19918
  import { resolve as resolvePath } from "node:path";
19549
19919
  import YAML5 from "yaml";
19550
19920
 
@@ -19827,11 +20197,11 @@ function zodIssueToError(issue, doc, lineCounter) {
19827
20197
  suggestion: deriveSuggestion(issue)
19828
20198
  };
19829
20199
  }
19830
- function formatJsonPath(path48) {
19831
- if (path48.length === 0)
20200
+ function formatJsonPath(path49) {
20201
+ if (path49.length === 0)
19832
20202
  return "<root>";
19833
20203
  let out = "";
19834
- for (const seg of path48) {
20204
+ for (const seg of path49) {
19835
20205
  if (typeof seg === "number") {
19836
20206
  out += `[${seg}]`;
19837
20207
  } else {
@@ -19840,11 +20210,11 @@ function formatJsonPath(path48) {
19840
20210
  }
19841
20211
  return out;
19842
20212
  }
19843
- function resolveYamlLocation(path48, doc, lineCounter) {
20213
+ function resolveYamlLocation(path49, doc, lineCounter) {
19844
20214
  let bestLine = 0;
19845
20215
  let bestColumn = 0;
19846
- for (let depth = path48.length; depth >= 0; depth -= 1) {
19847
- const segment = path48.slice(0, depth);
20216
+ for (let depth = path49.length; depth >= 0; depth -= 1) {
20217
+ const segment = path49.slice(0, depth);
19848
20218
  try {
19849
20219
  const node = doc.getIn(segment, true);
19850
20220
  if (node && typeof node === "object" && "range" in node) {
@@ -20062,11 +20432,11 @@ function topoSort(nodes) {
20062
20432
  }
20063
20433
  function traceCycle(start, byId) {
20064
20434
  const seen = /* @__PURE__ */ new Set();
20065
- const path48 = [];
20435
+ const path49 = [];
20066
20436
  let current = start;
20067
20437
  while (current && !seen.has(current)) {
20068
20438
  seen.add(current);
20069
- path48.push(current);
20439
+ path49.push(current);
20070
20440
  const node = byId.get(current);
20071
20441
  const next = node?.dependsOn[0];
20072
20442
  if (next === void 0)
@@ -20074,10 +20444,10 @@ function traceCycle(start, byId) {
20074
20444
  current = next;
20075
20445
  }
20076
20446
  if (current && seen.has(current)) {
20077
- const idx = path48.indexOf(current);
20078
- return [...path48.slice(idx), current];
20447
+ const idx = path49.indexOf(current);
20448
+ return [...path49.slice(idx), current];
20079
20449
  }
20080
- return path48;
20450
+ return path49;
20081
20451
  }
20082
20452
 
20083
20453
  // ../core/dist/executor/types.js
@@ -20301,11 +20671,11 @@ async function resolveDigests(lockfile, resolver) {
20301
20671
  }
20302
20672
 
20303
20673
  // ../core/dist/worldspec/image-digest.js
20304
- import { execFileSync as execFileSync7 } from "node:child_process";
20674
+ import { execFileSync as execFileSync8 } from "node:child_process";
20305
20675
  var DOCKER_SUBPROCESS_TIMEOUT_MS = 3e4;
20306
20676
  var dockerDigestResolver = async (image, source) => {
20307
20677
  if (source === "local") {
20308
- const out = execFileSync7("docker", ["inspect", image, "--format", "{{.Id}}"], {
20678
+ const out = execFileSync8("docker", ["inspect", image, "--format", "{{.Id}}"], {
20309
20679
  encoding: "utf8",
20310
20680
  stdio: ["ignore", "pipe", "pipe"],
20311
20681
  timeout: DOCKER_SUBPROCESS_TIMEOUT_MS,
@@ -20316,7 +20686,7 @@ var dockerDigestResolver = async (image, source) => {
20316
20686
  }
20317
20687
  return out;
20318
20688
  }
20319
- const raw = execFileSync7("docker", ["buildx", "imagetools", "inspect", image], {
20689
+ const raw = execFileSync8("docker", ["buildx", "imagetools", "inspect", image], {
20320
20690
  encoding: "utf8",
20321
20691
  stdio: ["ignore", "pipe", "pipe"],
20322
20692
  timeout: DOCKER_SUBPROCESS_TIMEOUT_MS,
@@ -20347,7 +20717,7 @@ function registerWorldspecCompile(parent) {
20347
20717
  const sourcePolicies = [];
20348
20718
  for (const p of paths) {
20349
20719
  const abs = resolvePath(process.cwd(), p);
20350
- if (!existsSync31(abs)) {
20720
+ if (!existsSync32(abs)) {
20351
20721
  printError(`worldspec not found at ${abs}`);
20352
20722
  process.exit(EXIT_WORLDSPEC_FILE_NOT_FOUND);
20353
20723
  }
@@ -20438,7 +20808,7 @@ function getPkgVersion() {
20438
20808
  // src/commands/worldspec/init.ts
20439
20809
  init_exit_codes();
20440
20810
  init_output();
20441
- import { existsSync as existsSync32, mkdirSync as mkdirSync19, readFileSync as readFileSync22, writeFileSync as writeFileSync15 } from "node:fs";
20811
+ import { existsSync as existsSync33, mkdirSync as mkdirSync19, readFileSync as readFileSync22, writeFileSync as writeFileSync15 } from "node:fs";
20442
20812
  import { execSync as execSync10 } from "node:child_process";
20443
20813
  import { basename as basename3, resolve as resolvePath2 } from "node:path";
20444
20814
  function registerWorldspecInit(parent) {
@@ -20456,7 +20826,7 @@ function registerWorldspecInit(parent) {
20456
20826
  const cwd = process.cwd();
20457
20827
  const targetDir = resolvePath2(cwd, ".olam/worldspecs");
20458
20828
  const targetFile = resolvePath2(targetDir, "default.yaml");
20459
- if (existsSync32(targetFile) && !opts.force) {
20829
+ if (existsSync33(targetFile) && !opts.force) {
20460
20830
  printError(
20461
20831
  `${targetFile} already exists; pass --force to overwrite`
20462
20832
  );
@@ -20490,12 +20860,12 @@ function registerWorldspecInit(parent) {
20490
20860
  });
20491
20861
  }
20492
20862
  function detectProjectShape(root, useAdbYaml) {
20493
- const hasGemfile = existsSync32(resolvePath2(root, "Gemfile"));
20494
- const hasNodePackageJson = existsSync32(resolvePath2(root, "package.json"));
20495
- const hasAdbYaml = existsSync32(resolvePath2(root, ".adb.yaml"));
20863
+ const hasGemfile = existsSync33(resolvePath2(root, "Gemfile"));
20864
+ const hasNodePackageJson = existsSync33(resolvePath2(root, "package.json"));
20865
+ const hasAdbYaml = existsSync33(resolvePath2(root, ".adb.yaml"));
20496
20866
  let rubyVersion = null;
20497
20867
  const rubyVersionPath = resolvePath2(root, ".ruby-version");
20498
- if (existsSync32(rubyVersionPath)) {
20868
+ if (existsSync33(rubyVersionPath)) {
20499
20869
  try {
20500
20870
  const raw = readFileSync22(rubyVersionPath, "utf8").trim();
20501
20871
  const match2 = raw.match(/(\d+\.\d+\.\d+)/);
@@ -21900,7 +22270,7 @@ function registerWorldspecSchema(parent) {
21900
22270
  }
21901
22271
 
21902
22272
  // src/commands/worldspec/validate.ts
21903
- import { existsSync as existsSync33, readFileSync as readFileSync23 } from "node:fs";
22273
+ import { existsSync as existsSync34, readFileSync as readFileSync23 } from "node:fs";
21904
22274
  import { resolve as resolvePath4 } from "node:path";
21905
22275
  init_exit_codes();
21906
22276
  init_output();
@@ -21917,7 +22287,7 @@ function registerWorldspecValidate(parent) {
21917
22287
  "human"
21918
22288
  ).action(async (pathArg, opts) => {
21919
22289
  const absPath = resolvePath4(process.cwd(), pathArg);
21920
- if (!existsSync33(absPath)) {
22290
+ if (!existsSync34(absPath)) {
21921
22291
  printError(`worldspec not found at ${absPath}`);
21922
22292
  process.exit(EXIT_WORLDSPEC_FILE_NOT_FOUND);
21923
22293
  }
@@ -21969,23 +22339,23 @@ function registerWorldspec(program2) {
21969
22339
  // src/commands/upgrade.ts
21970
22340
  init_output();
21971
22341
  init_host_cp();
21972
- import * as fs33 from "node:fs";
21973
- import * as path36 from "node:path";
22342
+ import * as fs34 from "node:fs";
22343
+ import * as path37 from "node:path";
21974
22344
  import { spawnSync as spawnSync11 } from "node:child_process";
21975
22345
  import ora7 from "ora";
21976
- import pc17 from "picocolors";
22346
+ import pc18 from "picocolors";
21977
22347
 
21978
22348
  // src/commands/upgrade-lock.ts
21979
- import * as fs31 from "node:fs";
21980
- import * as os18 from "node:os";
21981
- import * as path34 from "node:path";
22349
+ import * as fs32 from "node:fs";
22350
+ import * as os19 from "node:os";
22351
+ import * as path35 from "node:path";
21982
22352
  import { spawnSync as spawnSync10 } from "node:child_process";
21983
- var LOCK_FILE_PATH = path34.join(os18.homedir(), ".olam", ".upgrade.lock");
22353
+ var LOCK_FILE_PATH = path35.join(os19.homedir(), ".olam", ".upgrade.lock");
21984
22354
  var STALE_LOCK_TIMEOUT_MS = 5 * 60 * 1e3;
21985
22355
  function readLockFile(lockPath) {
21986
22356
  try {
21987
- if (!fs31.existsSync(lockPath)) return null;
21988
- const raw = fs31.readFileSync(lockPath, "utf-8").trim();
22357
+ if (!fs32.existsSync(lockPath)) return null;
22358
+ const raw = fs32.readFileSync(lockPath, "utf-8").trim();
21989
22359
  if (raw.length === 0) return null;
21990
22360
  const parsed = JSON.parse(raw);
21991
22361
  if (typeof parsed.pid !== "number" || typeof parsed.startTs !== "number") return null;
@@ -22030,16 +22400,16 @@ function isStaleLock(content, nowMs = Date.now()) {
22030
22400
  return false;
22031
22401
  }
22032
22402
  function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
22033
- const dir = path34.dirname(lockPath);
22034
- fs31.mkdirSync(dir, { recursive: true });
22403
+ const dir = path35.dirname(lockPath);
22404
+ fs32.mkdirSync(dir, { recursive: true });
22035
22405
  for (let attempt = 0; attempt < 2; attempt++) {
22036
22406
  try {
22037
- const fd = fs31.openSync(lockPath, "wx", 420);
22407
+ const fd = fs32.openSync(lockPath, "wx", 420);
22038
22408
  try {
22039
22409
  const content = { pid: process.pid, startTs: nowMs };
22040
- fs31.writeSync(fd, JSON.stringify(content));
22410
+ fs32.writeSync(fd, JSON.stringify(content));
22041
22411
  } finally {
22042
- fs31.closeSync(fd);
22412
+ fs32.closeSync(fd);
22043
22413
  }
22044
22414
  return { acquired: true, lockPath };
22045
22415
  } catch (err) {
@@ -22048,7 +22418,7 @@ function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
22048
22418
  const existing2 = readLockFile(lockPath);
22049
22419
  if (isStaleLock(existing2, nowMs)) {
22050
22420
  try {
22051
- fs31.unlinkSync(lockPath);
22421
+ fs32.unlinkSync(lockPath);
22052
22422
  } catch (unlinkErr) {
22053
22423
  const ucode = unlinkErr.code;
22054
22424
  if (ucode !== "ENOENT") throw unlinkErr;
@@ -22073,7 +22443,7 @@ function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
22073
22443
  }
22074
22444
  function releaseLock(lockPath = LOCK_FILE_PATH) {
22075
22445
  try {
22076
- fs31.unlinkSync(lockPath);
22446
+ fs32.unlinkSync(lockPath);
22077
22447
  } catch (err) {
22078
22448
  const code = err.code;
22079
22449
  if (code !== "ENOENT") throw err;
@@ -22091,19 +22461,19 @@ function formatRefusalMessage(result, lockPath = LOCK_FILE_PATH) {
22091
22461
  }
22092
22462
 
22093
22463
  // src/commands/upgrade-log.ts
22094
- import * as fs32 from "node:fs";
22095
- import * as os19 from "node:os";
22096
- import * as path35 from "node:path";
22464
+ import * as fs33 from "node:fs";
22465
+ import * as os20 from "node:os";
22466
+ import * as path36 from "node:path";
22097
22467
  function getUpgradeLogPath() {
22098
- const home = process.env["HOME"] ?? os19.homedir();
22099
- return path35.join(home, ".olam", "upgrade.log");
22468
+ const home = process.env["HOME"] ?? os20.homedir();
22469
+ return path36.join(home, ".olam", "upgrade.log");
22100
22470
  }
22101
22471
  var UPGRADE_LOG_PATH = getUpgradeLogPath();
22102
22472
  function appendUpgradeLog(row, logPath = getUpgradeLogPath()) {
22103
22473
  try {
22104
- fs32.mkdirSync(path35.dirname(logPath), { recursive: true });
22474
+ fs33.mkdirSync(path36.dirname(logPath), { recursive: true });
22105
22475
  const line = JSON.stringify(row) + "\n";
22106
- fs32.appendFileSync(logPath, line, { mode: 420 });
22476
+ fs33.appendFileSync(logPath, line, { mode: 420 });
22107
22477
  } catch (err) {
22108
22478
  process.stderr.write(
22109
22479
  `[upgrade-log] failed to append: ${err instanceof Error ? err.message : String(err)}
@@ -22112,10 +22482,10 @@ function appendUpgradeLog(row, logPath = getUpgradeLogPath()) {
22112
22482
  }
22113
22483
  }
22114
22484
  function readUpgradeLog(limit = 10, logPath = getUpgradeLogPath()) {
22115
- if (!fs32.existsSync(logPath)) return [];
22485
+ if (!fs33.existsSync(logPath)) return [];
22116
22486
  let raw;
22117
22487
  try {
22118
- raw = fs32.readFileSync(logPath, "utf-8");
22488
+ raw = fs33.readFileSync(logPath, "utf-8");
22119
22489
  } catch (err) {
22120
22490
  process.stderr.write(
22121
22491
  `[upgrade-log] failed to read: ${err instanceof Error ? err.message : String(err)}
@@ -22208,12 +22578,12 @@ init_protocol_version();
22208
22578
  init_install_root();
22209
22579
  var AUTH_HEALTH_URL2 = "http://127.0.0.1:9999/health";
22210
22580
  function isNodeModulesInSync(cwd) {
22211
- const lockPath = path36.join(cwd, "package-lock.json");
22212
- const markerPath = path36.join(cwd, "node_modules", ".package-lock.json");
22213
- if (!fs33.existsSync(lockPath) || !fs33.existsSync(markerPath)) return false;
22581
+ const lockPath = path37.join(cwd, "package-lock.json");
22582
+ const markerPath = path37.join(cwd, "node_modules", ".package-lock.json");
22583
+ if (!fs34.existsSync(lockPath) || !fs34.existsSync(markerPath)) return false;
22214
22584
  try {
22215
- const lockStat = fs33.statSync(lockPath);
22216
- const markerStat = fs33.statSync(markerPath);
22585
+ const lockStat = fs34.statSync(lockPath);
22586
+ const markerStat = fs34.statSync(markerPath);
22217
22587
  return markerStat.mtimeMs >= lockStat.mtimeMs;
22218
22588
  } catch {
22219
22589
  return false;
@@ -22229,8 +22599,8 @@ function shouldSkipInstall(opts, cwd) {
22229
22599
  return { skip: false };
22230
22600
  }
22231
22601
  function validateRepoRoot(cwd) {
22232
- const marker = path36.join(cwd, "packages/host-cp/compose.yaml");
22233
- if (!fs33.existsSync(marker)) {
22602
+ const marker = path37.join(cwd, "packages/host-cp/compose.yaml");
22603
+ if (!fs34.existsSync(marker)) {
22234
22604
  return {
22235
22605
  ok: false,
22236
22606
  error: `Not an olam repo root (expected ${marker}).
@@ -22262,7 +22632,7 @@ function extractBundleHash(indexHtml) {
22262
22632
  }
22263
22633
  function runStep2(label, cmd, args, opts = {}) {
22264
22634
  const start = Date.now();
22265
- process.stdout.write(` ${pc17.dim(label.padEnd(34))}`);
22635
+ process.stdout.write(` ${pc18.dim(label.padEnd(34))}`);
22266
22636
  const result = spawnSync11(cmd, [...args], {
22267
22637
  encoding: "utf-8",
22268
22638
  stdio: ["ignore", "pipe", "pipe"],
@@ -22272,7 +22642,7 @@ function runStep2(label, cmd, args, opts = {}) {
22272
22642
  const durationMs = Date.now() - start;
22273
22643
  const ok = result.status === 0 && result.error === void 0;
22274
22644
  const dur = `${(durationMs / 1e3).toFixed(1)}s`;
22275
- process.stdout.write(`${ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${dur}
22645
+ process.stdout.write(`${ok ? pc18.green("\u2713") : pc18.red("\u2717")} ${dur}
22276
22646
  `);
22277
22647
  return {
22278
22648
  ok,
@@ -22484,8 +22854,8 @@ function performRollbackSwap(plan) {
22484
22854
  }
22485
22855
  async function confirm2(message) {
22486
22856
  if (!process.stdin.isTTY) return true;
22487
- const { createInterface: createInterface4 } = await import("node:readline");
22488
- const rl = createInterface4({ input: process.stdin, output: process.stdout });
22857
+ const { createInterface: createInterface5 } = await import("node:readline");
22858
+ const rl = createInterface5({ input: process.stdin, output: process.stdout });
22489
22859
  return new Promise((resolve10) => {
22490
22860
  rl.question(`${message} [y/N] `, (answer) => {
22491
22861
  rl.close();
@@ -22586,9 +22956,9 @@ async function recreateAuthService() {
22586
22956
  }
22587
22957
  }
22588
22958
  function readBundleHash(cwd) {
22589
- const indexPath = path36.join(cwd, "packages/control-plane/public/index.html");
22590
- if (!fs33.existsSync(indexPath)) return null;
22591
- return extractBundleHash(fs33.readFileSync(indexPath, "utf-8"));
22959
+ const indexPath = path37.join(cwd, "packages/control-plane/public/index.html");
22960
+ if (!fs34.existsSync(indexPath)) return null;
22961
+ return extractBundleHash(fs34.readFileSync(indexPath, "utf-8"));
22592
22962
  }
22593
22963
  async function runUpgradePullByDigest(deps = {}) {
22594
22964
  const docker2 = deps.docker ?? realDocker;
@@ -22600,7 +22970,7 @@ async function runUpgradePullByDigest(deps = {}) {
22600
22970
  if (info.exitCode !== 0) {
22601
22971
  infoSpinner.fail("docker daemon not reachable");
22602
22972
  process.stderr.write(
22603
- `${pc17.red("error")} docker info exited with ${info.exitCode}.
22973
+ `${pc18.red("error")} docker info exited with ${info.exitCode}.
22604
22974
  Ensure Docker Desktop / Colima / Rancher is running, then retry.
22605
22975
  `
22606
22976
  );
@@ -22635,7 +23005,7 @@ async function runUpgradePullByDigest(deps = {}) {
22635
23005
  pullSpinner.fail(`Pull failed for ${failed.map((r) => r.name).join(", ")}`);
22636
23006
  for (const f of failed) {
22637
23007
  process.stderr.write(
22638
- ` ${pc17.red(f.name)} (${f.ref}):
23008
+ ` ${pc18.red(f.name)} (${f.ref}):
22639
23009
  exit=${f.result.exitCode}
22640
23010
  stderr: ${f.result.stderr.split("\n")[0] ?? "(empty)"}
22641
23011
  `
@@ -22656,7 +23026,7 @@ async function runUpgradePullByDigest(deps = {}) {
22656
23026
  if (inspect.exitCode !== 0) {
22657
23027
  handshakeSpinner.fail(`Could not inspect ${name}`);
22658
23028
  process.stderr.write(
22659
- `${pc17.red("error")} docker inspect ${ref} failed: ${inspect.stderr}
23029
+ `${pc18.red("error")} docker inspect ${ref} failed: ${inspect.stderr}
22660
23030
  `
22661
23031
  );
22662
23032
  return { exitCode: EXIT_GENERIC_ERROR, summary: `inspect failed: ${name}` };
@@ -22668,7 +23038,7 @@ async function runUpgradePullByDigest(deps = {}) {
22668
23038
  const decision = checkProtocolOverlap(versions);
22669
23039
  if (!decision.compatible) {
22670
23040
  handshakeSpinner.fail(`Protocol mismatch on ${name}`);
22671
- process.stderr.write(`${pc17.red("error")} ${decision.remedy}
23041
+ process.stderr.write(`${pc18.red("error")} ${decision.remedy}
22672
23042
  `);
22673
23043
  return {
22674
23044
  exitCode: EXIT_PROTOCOL_MISMATCH,
@@ -22698,7 +23068,7 @@ async function runUpgradePullByDigest(deps = {}) {
22698
23068
  const r = tagger(t.from, t.to);
22699
23069
  if (!r.ok) {
22700
23070
  tagSpinner.fail(`docker tag failed for ${t.name}`);
22701
- process.stderr.write(`${pc17.red("error")} ${r.error ?? "docker tag failed"}
23071
+ process.stderr.write(`${pc18.red("error")} ${r.error ?? "docker tag failed"}
22702
23072
  `);
22703
23073
  return { exitCode: EXIT_GENERIC_ERROR, summary: `tag failed: ${t.name}` };
22704
23074
  }
@@ -22716,7 +23086,7 @@ async function runUpgradePullByDigest(deps = {}) {
22716
23086
  if (!composeResult.ok) {
22717
23087
  composeSpinner.fail("compose recreate failed");
22718
23088
  process.stderr.write(
22719
- `${pc17.red("error")} docker compose up --force-recreate host-cp failed:
23089
+ `${pc18.red("error")} docker compose up --force-recreate host-cp failed:
22720
23090
  ${composeResult.stderr.split("\n").slice(0, 3).join("\n ")}
22721
23091
  `
22722
23092
  );
@@ -22729,7 +23099,7 @@ async function runUpgradePullByDigest(deps = {}) {
22729
23099
  if (!authResult.ok) {
22730
23100
  authSpinner.fail("auth-service recreate failed");
22731
23101
  process.stderr.write(
22732
- `${pc17.red("error")} ${authResult.error ?? "unknown failure"}
23102
+ `${pc18.red("error")} ${authResult.error ?? "unknown failure"}
22733
23103
  `
22734
23104
  );
22735
23105
  return { exitCode: EXIT_GENERIC_ERROR, summary: "auth recreate failed" };
@@ -22742,7 +23112,7 @@ async function runUpgradePullByDigest(deps = {}) {
22742
23112
  if (!mcpResult.ok) {
22743
23113
  mcpSpinner.fail("mcp-auth-service recreate failed");
22744
23114
  process.stderr.write(
22745
- `${pc17.red("error")} ${mcpResult.error ?? "unknown failure"}
23115
+ `${pc18.red("error")} ${mcpResult.error ?? "unknown failure"}
22746
23116
  `
22747
23117
  );
22748
23118
  return { exitCode: EXIT_GENERIC_ERROR, summary: "mcp-auth recreate failed" };
@@ -22935,11 +23305,11 @@ manually inspect images with \`docker images olam-*:olam-rollback\`.`
22935
23305
  process.once("SIGINT", releaseOnSignal);
22936
23306
  process.once("SIGTERM", releaseOnSignal);
22937
23307
  try {
22938
- process.stdout.write(` ${pc17.dim("rollback retag (3 ops)".padEnd(34))}`);
23308
+ process.stdout.write(` ${pc18.dim("rollback retag (3 ops)".padEnd(34))}`);
22939
23309
  const swapStart = Date.now();
22940
23310
  const swapResult = performRollbackSwap(PRODUCTION_SWAP_PLAN);
22941
23311
  const swapDur = `${((Date.now() - swapStart) / 1e3).toFixed(1)}s`;
22942
- process.stdout.write(`${swapResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${swapDur}
23312
+ process.stdout.write(`${swapResult.ok ? pc18.green("\u2713") : pc18.red("\u2717")} ${swapDur}
22943
23313
  `);
22944
23314
  if (!swapResult.ok) {
22945
23315
  printError(`Rollback retag failed: ${swapResult.summary}`);
@@ -22949,11 +23319,11 @@ manually inspect images with \`docker images olam-*:olam-rollback\`.`
22949
23319
  printInfo("Rollback", swapResult.summary);
22950
23320
  const composeFile = findComposeFile();
22951
23321
  const authSecret = readAuthSecret2();
22952
- process.stdout.write(` ${pc17.dim("docker compose recreate host-cp".padEnd(34))}`);
23322
+ process.stdout.write(` ${pc18.dim("docker compose recreate host-cp".padEnd(34))}`);
22953
23323
  const composeStart = Date.now();
22954
23324
  const composeResult = runCompose(["up", "-d", "--force-recreate", "--no-deps", "host-cp"], composeFile, buildComposeEnv(authSecret, captureGhToken()));
22955
23325
  const composeDur = `${((Date.now() - composeStart) / 1e3).toFixed(1)}s`;
22956
- process.stdout.write(`${composeResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${composeDur}
23326
+ process.stdout.write(`${composeResult.ok ? pc18.green("\u2713") : pc18.red("\u2717")} ${composeDur}
22957
23327
  `);
22958
23328
  if (!composeResult.ok) {
22959
23329
  printError(
@@ -22964,10 +23334,10 @@ Canonical tags are at :olam-rollback (good); container restart pending. Manually
22964
23334
  process.exitCode = 1;
22965
23335
  return;
22966
23336
  }
22967
- process.stdout.write(` ${pc17.dim("recreate auth-service".padEnd(34))}`);
23337
+ process.stdout.write(` ${pc18.dim("recreate auth-service".padEnd(34))}`);
22968
23338
  const authResult = await recreateAuthService();
22969
23339
  const authDur = `${(authResult.durationMs / 1e3).toFixed(1)}s`;
22970
- process.stdout.write(`${authResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${authDur}
23340
+ process.stdout.write(`${authResult.ok ? pc18.green("\u2713") : pc18.red("\u2717")} ${authDur}
22971
23341
  `);
22972
23342
  if (!authResult.ok) {
22973
23343
  printError(`Auth-service recreate failed: ${authResult.error ?? "unknown"}`);
@@ -23088,7 +23458,7 @@ ${buildResult.stderr}`);
23088
23458
  return;
23089
23459
  }
23090
23460
  const authSecret = readAuthSecret2();
23091
- const spaDir = path36.join(cwd, "packages/control-plane/app");
23461
+ const spaDir = path37.join(cwd, "packages/control-plane/app");
23092
23462
  const spaResult = runStep2(
23093
23463
  "vite build (SPA)",
23094
23464
  "npx",
@@ -23133,7 +23503,7 @@ ${spaResult.stderr}`);
23133
23503
  throw err;
23134
23504
  }
23135
23505
  if (step.tee) {
23136
- process.stdout.write(` ${pc17.dim(step.label.padEnd(34))}
23506
+ process.stdout.write(` ${pc18.dim(step.label.padEnd(34))}
23137
23507
  `);
23138
23508
  const start = Date.now();
23139
23509
  const result = spawnSync11("bash", [scriptPath], {
@@ -23144,7 +23514,7 @@ ${spaResult.stderr}`);
23144
23514
  const durationMs = Date.now() - start;
23145
23515
  const ok = result.status === 0 && result.error === void 0;
23146
23516
  const dur = `${(durationMs / 1e3).toFixed(1)}s`;
23147
- process.stdout.write(` ${pc17.dim(step.label.padEnd(34))}${ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${dur}
23517
+ process.stdout.write(` ${pc18.dim(step.label.padEnd(34))}${ok ? pc18.green("\u2713") : pc18.red("\u2717")} ${dur}
23148
23518
  `);
23149
23519
  timings.push({ label: step.label, durationMs });
23150
23520
  if (!ok) {
@@ -23170,7 +23540,7 @@ ${result.stderr.split("\n").slice(-3).join("\n")}`);
23170
23540
  }
23171
23541
  for (const t of timings) logRow.durations_ms[t.label] = t.durationMs;
23172
23542
  const smokeStart = Date.now();
23173
- process.stdout.write(` ${pc17.dim("smoke (docker create + inspect)".padEnd(34))}`);
23543
+ process.stdout.write(` ${pc18.dim("smoke (docker create + inspect)".padEnd(34))}`);
23174
23544
  const smokeImages = [
23175
23545
  "olam-auth:olam-next",
23176
23546
  "olam-devbox:olam-next",
@@ -23180,7 +23550,7 @@ ${result.stderr.split("\n").slice(-3).join("\n")}`);
23180
23550
  const smokeFailures = smokeResults.filter((r) => !r.ok);
23181
23551
  const smokeDurationMs = Date.now() - smokeStart;
23182
23552
  const smokeDur = `${(smokeDurationMs / 1e3).toFixed(1)}s`;
23183
- process.stdout.write(`${smokeFailures.length === 0 ? pc17.green("\u2713") : pc17.red("\u2717")} ${smokeDur}
23553
+ process.stdout.write(`${smokeFailures.length === 0 ? pc18.green("\u2713") : pc18.red("\u2717")} ${smokeDur}
23184
23554
  `);
23185
23555
  timings.push({ label: "smoke", durationMs: smokeDurationMs });
23186
23556
  if (smokeFailures.length > 0) {
@@ -23207,12 +23577,12 @@ Recovery options:
23207
23577
  process.exitCode = 1;
23208
23578
  return;
23209
23579
  }
23210
- process.stdout.write(` ${pc17.dim("atomic 6-tag swap".padEnd(34))}`);
23580
+ process.stdout.write(` ${pc18.dim("atomic 6-tag swap".padEnd(34))}`);
23211
23581
  const swapStart = Date.now();
23212
23582
  const swapResult = performAtomicSwap(PRODUCTION_SWAP_PLAN);
23213
23583
  const swapDurationMs = Date.now() - swapStart;
23214
23584
  const swapDur = `${(swapDurationMs / 1e3).toFixed(1)}s`;
23215
- process.stdout.write(`${swapResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${swapDur}
23585
+ process.stdout.write(`${swapResult.ok ? pc18.green("\u2713") : pc18.red("\u2717")} ${swapDur}
23216
23586
  `);
23217
23587
  timings.push({ label: "atomic swap", durationMs: swapDurationMs });
23218
23588
  if (!swapResult.ok) {
@@ -23222,7 +23592,7 @@ Recovery options:
23222
23592
  }
23223
23593
  printInfo("Swap", swapResult.summary);
23224
23594
  const composeFile = findComposeFile();
23225
- process.stdout.write(` ${pc17.dim("docker compose recreate".padEnd(34))}`);
23595
+ process.stdout.write(` ${pc18.dim("docker compose recreate".padEnd(34))}`);
23226
23596
  const composeStart = Date.now();
23227
23597
  const composeResult = runCompose(
23228
23598
  ["up", "-d", "--force-recreate"],
@@ -23232,7 +23602,7 @@ Recovery options:
23232
23602
  const composeDurationMs = Date.now() - composeStart;
23233
23603
  const composeOk = composeResult.ok;
23234
23604
  const composeDur = `${(composeDurationMs / 1e3).toFixed(1)}s`;
23235
- process.stdout.write(`${composeOk ? pc17.green("\u2713") : pc17.red("\u2717")} ${composeDur}
23605
+ process.stdout.write(`${composeOk ? pc18.green("\u2713") : pc18.red("\u2717")} ${composeDur}
23236
23606
  `);
23237
23607
  timings.push({ label: "container recreate", durationMs: composeDurationMs });
23238
23608
  if (!composeOk) {
@@ -23248,10 +23618,10 @@ Recovery options:
23248
23618
  process.exitCode = 1;
23249
23619
  return;
23250
23620
  }
23251
- process.stdout.write(` ${pc17.dim("recreate auth-service".padEnd(34))}`);
23621
+ process.stdout.write(` ${pc18.dim("recreate auth-service".padEnd(34))}`);
23252
23622
  const authResult = await recreateAuthService();
23253
23623
  const authDur = `${(authResult.durationMs / 1e3).toFixed(1)}s`;
23254
- process.stdout.write(`${authResult.ok ? pc17.green("\u2713") : pc17.red("\u2717")} ${authDur}
23624
+ process.stdout.write(`${authResult.ok ? pc18.green("\u2713") : pc18.red("\u2717")} ${authDur}
23255
23625
  `);
23256
23626
  timings.push({ label: "auth recreate", durationMs: authResult.durationMs });
23257
23627
  if (!authResult.ok) {
@@ -23266,12 +23636,12 @@ Recovery options:
23266
23636
  process.exitCode = 1;
23267
23637
  return;
23268
23638
  }
23269
- process.stdout.write(` ${pc17.dim("waiting for /health".padEnd(34))}`);
23639
+ process.stdout.write(` ${pc18.dim("waiting for /health".padEnd(34))}`);
23270
23640
  const healthStart = Date.now();
23271
23641
  const healthy = await waitForHealth(1e4);
23272
23642
  const healthDurationMs = Date.now() - healthStart;
23273
23643
  const healthDur = `${(healthDurationMs / 1e3).toFixed(1)}s`;
23274
- process.stdout.write(`${healthy ? pc17.green("\u2713") : pc17.yellow("?")} ${healthDur}
23644
+ process.stdout.write(`${healthy ? pc18.green("\u2713") : pc18.yellow("?")} ${healthDur}
23275
23645
  `);
23276
23646
  timings.push({ label: "/health", durationMs: healthDurationMs });
23277
23647
  if (!healthy) {
@@ -23279,12 +23649,12 @@ Recovery options:
23279
23649
  "Host CP started but /health did not respond within 10s.\n \u2022 Check: docker logs olam-host-cp\n \u2022 If the new SHA is broken: `olam upgrade --rollback` restores the prior set in <30s."
23280
23650
  );
23281
23651
  }
23282
- process.stdout.write(` ${pc17.dim("verify /version/status round-trip".padEnd(34))}`);
23652
+ process.stdout.write(` ${pc18.dim("verify /version/status round-trip".padEnd(34))}`);
23283
23653
  const versionStart = Date.now();
23284
23654
  const versionMatch = await waitForVersionMatch(_targetSha, 9e4);
23285
23655
  const versionDurationMs = Date.now() - versionStart;
23286
23656
  const versionDur = `${(versionDurationMs / 1e3).toFixed(1)}s`;
23287
- process.stdout.write(`${versionMatch.matched ? pc17.green("\u2713") : pc17.yellow("?")} ${versionDur}
23657
+ process.stdout.write(`${versionMatch.matched ? pc18.green("\u2713") : pc18.yellow("?")} ${versionDur}
23288
23658
  `);
23289
23659
  timings.push({ label: "/version/status round-trip", durationMs: versionDurationMs });
23290
23660
  if (!versionMatch.matched) {
@@ -23358,16 +23728,16 @@ init_host_cp();
23358
23728
  init_context();
23359
23729
  init_output();
23360
23730
  import * as http3 from "node:http";
23361
- import pc18 from "picocolors";
23731
+ import pc19 from "picocolors";
23362
23732
  var HOST_CP_PORT3 = 19e3;
23363
23733
  function colorLine(line) {
23364
- if (/\bERROR\b/.test(line)) return pc18.red(line);
23365
- if (/\bWARN\b/.test(line)) return pc18.yellow(line);
23366
- if (/\bINFO\b/.test(line)) return pc18.dim(line);
23734
+ if (/\bERROR\b/.test(line)) return pc19.red(line);
23735
+ if (/\bWARN\b/.test(line)) return pc19.yellow(line);
23736
+ if (/\bINFO\b/.test(line)) return pc19.dim(line);
23367
23737
  return line;
23368
23738
  }
23369
23739
  function formatLine(line, service, showService) {
23370
- const prefix = showService && service ? `${pc18.cyan(`[${service}]`)} ` : "";
23740
+ const prefix = showService && service ? `${pc19.cyan(`[${service}]`)} ` : "";
23371
23741
  return prefix + colorLine(line);
23372
23742
  }
23373
23743
  function parseSseEvent(raw) {
@@ -23484,7 +23854,7 @@ function registerLogs(program2) {
23484
23854
  // src/commands/ps.ts
23485
23855
  init_context();
23486
23856
  init_output();
23487
- import pc19 from "picocolors";
23857
+ import pc20 from "picocolors";
23488
23858
  import { spawnSync as spawnSync12 } from "node:child_process";
23489
23859
  var SAFE_IDENT4 = /^[a-z0-9][a-z0-9-]{0,63}$/;
23490
23860
  function parseDockerTop(stdout) {
@@ -23545,18 +23915,18 @@ function printTable2(rows) {
23545
23915
  const fixedWidth = 5 + 1 + 8 + 1 + 6 + 1 + 6 + 1 + 10 + 1 + 6 + 1;
23546
23916
  const cmdWidth = Math.max(20, cols - fixedWidth);
23547
23917
  const header = [
23548
- pc19.bold(pc19.dim("PID".padEnd(5))),
23549
- pc19.bold(pc19.dim("USER".padEnd(8))),
23550
- pc19.bold(pc19.dim("%CPU".padEnd(6))),
23551
- pc19.bold(pc19.dim("%MEM".padEnd(6))),
23552
- pc19.bold(pc19.dim("STARTED".padEnd(10))),
23553
- pc19.bold(pc19.dim("STATE".padEnd(6))),
23554
- pc19.bold(pc19.dim("COMMAND"))
23918
+ pc20.bold(pc20.dim("PID".padEnd(5))),
23919
+ pc20.bold(pc20.dim("USER".padEnd(8))),
23920
+ pc20.bold(pc20.dim("%CPU".padEnd(6))),
23921
+ pc20.bold(pc20.dim("%MEM".padEnd(6))),
23922
+ pc20.bold(pc20.dim("STARTED".padEnd(10))),
23923
+ pc20.bold(pc20.dim("STATE".padEnd(6))),
23924
+ pc20.bold(pc20.dim("COMMAND"))
23555
23925
  ].join(" ");
23556
23926
  console.log(header);
23557
23927
  for (const row of rows) {
23558
23928
  const cmd = row.command.length > cmdWidth ? row.command.slice(0, cmdWidth - 1) + "\u2026" : row.command;
23559
- const stateFn = row.state.startsWith("R") ? pc19.green : row.state.startsWith("Z") ? pc19.red : pc19.dim;
23929
+ const stateFn = row.state.startsWith("R") ? pc20.green : row.state.startsWith("Z") ? pc20.red : pc20.dim;
23560
23930
  console.log([
23561
23931
  row.pid.padEnd(5),
23562
23932
  row.user.slice(0, 8).padEnd(8),
@@ -23605,7 +23975,7 @@ function registerPs(program2) {
23605
23975
  printTable2(rows);
23606
23976
  if (opts.watch) {
23607
23977
  process.stdout.write(`
23608
- ${pc19.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
23978
+ ${pc20.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
23609
23979
  `);
23610
23980
  }
23611
23981
  }
@@ -23622,20 +23992,20 @@ ${pc19.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
23622
23992
 
23623
23993
  // src/commands/keys.ts
23624
23994
  init_output();
23625
- import * as fs34 from "node:fs";
23626
- import * as os20 from "node:os";
23627
- import * as path37 from "node:path";
23995
+ import * as fs35 from "node:fs";
23996
+ import * as os21 from "node:os";
23997
+ import * as path38 from "node:path";
23628
23998
  import YAML6 from "yaml";
23629
23999
  function olamHome2() {
23630
- return process.env.OLAM_HOME ?? path37.join(os20.homedir(), ".olam");
24000
+ return process.env.OLAM_HOME ?? path38.join(os21.homedir(), ".olam");
23631
24001
  }
23632
24002
  function keysFilePath() {
23633
- return path37.join(olamHome2(), "keys.yaml");
24003
+ return path38.join(olamHome2(), "keys.yaml");
23634
24004
  }
23635
24005
  function readKeysFile() {
23636
24006
  const filePath = keysFilePath();
23637
- if (!fs34.existsSync(filePath)) return null;
23638
- const raw = fs34.readFileSync(filePath, "utf-8").trim();
24007
+ if (!fs35.existsSync(filePath)) return null;
24008
+ const raw = fs35.readFileSync(filePath, "utf-8").trim();
23639
24009
  if (raw.length === 0) return null;
23640
24010
  try {
23641
24011
  const parsed = YAML6.parse(raw);
@@ -23651,13 +24021,13 @@ function readKeysFile() {
23651
24021
  }
23652
24022
  function writeKeysFile(keys) {
23653
24023
  const dir = olamHome2();
23654
- if (!fs34.existsSync(dir)) {
23655
- fs34.mkdirSync(dir, { recursive: true });
24024
+ if (!fs35.existsSync(dir)) {
24025
+ fs35.mkdirSync(dir, { recursive: true });
23656
24026
  }
23657
24027
  const filePath = keysFilePath();
23658
24028
  const content = YAML6.stringify(keys);
23659
- fs34.writeFileSync(filePath, content, { encoding: "utf-8", mode: 384 });
23660
- fs34.chmodSync(filePath, 384);
24029
+ fs35.writeFileSync(filePath, content, { encoding: "utf-8", mode: 384 });
24030
+ fs35.chmodSync(filePath, 384);
23661
24031
  }
23662
24032
  function redact(value) {
23663
24033
  if (value.length <= 8) return value + "...";
@@ -23700,7 +24070,7 @@ function registerKeys(program2) {
23700
24070
  }
23701
24071
  const { [key]: _removed, ...rest } = existing;
23702
24072
  if (Object.keys(rest).length === 0) {
23703
- fs34.unlinkSync(keysFilePath());
24073
+ fs35.unlinkSync(keysFilePath());
23704
24074
  } else {
23705
24075
  writeKeysFile(rest);
23706
24076
  }
@@ -23725,10 +24095,10 @@ function registerKeys(program2) {
23725
24095
  // src/commands/world-snapshot.ts
23726
24096
  init_snapshot();
23727
24097
  init_output();
23728
- import * as fs35 from "node:fs";
23729
- import * as path38 from "node:path";
24098
+ import * as fs36 from "node:fs";
24099
+ import * as path39 from "node:path";
23730
24100
  import { execSync as execSync11 } from "node:child_process";
23731
- import pc20 from "picocolors";
24101
+ import pc21 from "picocolors";
23732
24102
 
23733
24103
  // src/commands/world.ts
23734
24104
  function getOrCreateWorldCommand(program2) {
@@ -23749,16 +24119,16 @@ function emitDeprecationWarning(subcommand) {
23749
24119
  }
23750
24120
  function bumpDeprecationCounter() {
23751
24121
  if (process.env[INTERNAL_SENTINEL_ENV] === "1") return;
23752
- const counterPath = path38.join(snapshotsDir(), ".deprecation-counter");
24122
+ const counterPath = path39.join(snapshotsDir(), ".deprecation-counter");
23753
24123
  try {
23754
- fs35.mkdirSync(path38.dirname(counterPath), { recursive: true });
24124
+ fs36.mkdirSync(path39.dirname(counterPath), { recursive: true });
23755
24125
  let current = 0;
23756
- if (fs35.existsSync(counterPath)) {
23757
- const raw = fs35.readFileSync(counterPath, "utf-8").trim();
24126
+ if (fs36.existsSync(counterPath)) {
24127
+ const raw = fs36.readFileSync(counterPath, "utf-8").trim();
23758
24128
  const parsed = parseInt(raw, 10);
23759
24129
  if (Number.isInteger(parsed) && parsed >= 0) current = parsed;
23760
24130
  }
23761
- fs35.writeFileSync(counterPath, String(current + 1), { mode: 384 });
24131
+ fs36.writeFileSync(counterPath, String(current + 1), { mode: 384 });
23762
24132
  } catch {
23763
24133
  }
23764
24134
  }
@@ -23820,7 +24190,7 @@ async function handleCreate2(worldId, kindArg) {
23820
24190
  const label = r.repo ? `${r.kind}/${r.repo}` : r.kind;
23821
24191
  if (r.ok) {
23822
24192
  printSuccess(`${label}`);
23823
- console.log(` ${pc20.dim(r.tarPath)}`);
24193
+ console.log(` ${pc21.dim(r.tarPath)}`);
23824
24194
  } else {
23825
24195
  printWarning(`${label}: ${r.msg ?? "skipped"}`);
23826
24196
  }
@@ -23834,17 +24204,17 @@ function resolveKinds(arg) {
23834
24204
  return [];
23835
24205
  }
23836
24206
  async function captureGems(worldId, workspacePath, repo) {
23837
- const repoDir = path38.join(workspacePath, repo);
24207
+ const repoDir = path39.join(workspacePath, repo);
23838
24208
  const fingerprint = computeGemsFingerprint(repoDir);
23839
24209
  if (!fingerprint) {
23840
24210
  return { ok: false, tarPath: "", msg: "no Gemfile.lock \u2014 layer does not apply" };
23841
24211
  }
23842
24212
  const tarPath = snapshotTarPath(worldId, "gems", repo, fingerprint);
23843
- const vendorBundle = path38.join(repoDir, "vendor", "bundle");
23844
- if (fs35.existsSync(vendorBundle)) {
24213
+ const vendorBundle = path39.join(repoDir, "vendor", "bundle");
24214
+ if (fs36.existsSync(vendorBundle)) {
23845
24215
  try {
23846
24216
  packTarball(vendorBundle, tarPath);
23847
- const stat = fs35.statSync(tarPath);
24217
+ const stat = fs36.statSync(tarPath);
23848
24218
  const manifest = {
23849
24219
  kind: "gems",
23850
24220
  worldId,
@@ -23877,10 +24247,10 @@ async function captureGems(worldId, workspacePath, repo) {
23877
24247
  `docker exec ${containerName} sh -c 'mkdir -p "$(dirname ${tmpTar})" && tar -czf ${tmpTar}.tmp -C ${bundlePath} . && mv ${tmpTar}.tmp ${tmpTar}'`,
23878
24248
  { stdio: "pipe", timeout: 12e4 }
23879
24249
  );
23880
- fs35.mkdirSync(path38.dirname(tarPath), { recursive: true });
24250
+ fs36.mkdirSync(path39.dirname(tarPath), { recursive: true });
23881
24251
  execSync11(`docker cp ${containerName}:${tmpTar} "${tarPath}"`, { stdio: "pipe", timeout: 12e4 });
23882
24252
  execSync11(`docker exec ${containerName} rm -f ${tmpTar}`, { stdio: "pipe" });
23883
- const stat = fs35.statSync(tarPath);
24253
+ const stat = fs36.statSync(tarPath);
23884
24254
  const manifest = {
23885
24255
  kind: "gems",
23886
24256
  worldId,
@@ -23897,19 +24267,19 @@ async function captureGems(worldId, workspacePath, repo) {
23897
24267
  }
23898
24268
  }
23899
24269
  async function captureNode(worldId, workspacePath, repo) {
23900
- const repoDir = path38.join(workspacePath, repo);
24270
+ const repoDir = path39.join(workspacePath, repo);
23901
24271
  const fingerprint = computeNodeFingerprint(repoDir);
23902
24272
  if (!fingerprint) {
23903
24273
  return { ok: false, tarPath: "", msg: "no lockfile \u2014 layer does not apply" };
23904
24274
  }
23905
- const nodeModules = path38.join(repoDir, "node_modules");
23906
- if (!fs35.existsSync(nodeModules)) {
24275
+ const nodeModules = path39.join(repoDir, "node_modules");
24276
+ if (!fs36.existsSync(nodeModules)) {
23907
24277
  return { ok: false, tarPath: "", msg: "node_modules not installed yet" };
23908
24278
  }
23909
24279
  const tarPath = snapshotTarPath(worldId, "node", repo, fingerprint);
23910
24280
  try {
23911
24281
  packTarball(nodeModules, tarPath);
23912
- const stat = fs35.statSync(tarPath);
24282
+ const stat = fs36.statSync(tarPath);
23913
24283
  const manifest = {
23914
24284
  kind: "node",
23915
24285
  worldId,
@@ -23926,7 +24296,7 @@ async function captureNode(worldId, workspacePath, repo) {
23926
24296
  }
23927
24297
  }
23928
24298
  async function capturePg(worldId, workspacePath, repoNames) {
23929
- const repoDirs = repoNames.map((r) => path38.join(workspacePath, r));
24299
+ const repoDirs = repoNames.map((r) => path39.join(workspacePath, r));
23930
24300
  const fingerprint = computePgFingerprint(repoDirs);
23931
24301
  if (!fingerprint) {
23932
24302
  return { ok: false, tarPath: "", msg: "no Gemfile.lock / schema.rb \u2014 layer does not apply" };
@@ -23941,13 +24311,13 @@ async function capturePg(worldId, workspacePath, repoNames) {
23941
24311
  }
23942
24312
  try {
23943
24313
  execSync11(`docker stop ${containerName}`, { stdio: "pipe", timeout: 3e4 });
23944
- fs35.mkdirSync(path38.dirname(tarPath), { recursive: true });
24314
+ fs36.mkdirSync(path39.dirname(tarPath), { recursive: true });
23945
24315
  execSync11(
23946
- `docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${path38.dirname(tarPath)}:/dest" alpine sh -c 'tar -czf /dest/${path38.basename(tarPath)}.tmp -C /pgdata . && mv /dest/${path38.basename(tarPath)}.tmp /dest/${path38.basename(tarPath)}'`,
24316
+ `docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${path39.dirname(tarPath)}:/dest" alpine sh -c 'tar -czf /dest/${path39.basename(tarPath)}.tmp -C /pgdata . && mv /dest/${path39.basename(tarPath)}.tmp /dest/${path39.basename(tarPath)}'`,
23947
24317
  { stdio: "pipe", timeout: 18e4 }
23948
24318
  );
23949
24319
  execSync11(`docker start ${containerName}`, { stdio: "pipe", timeout: 3e4 });
23950
- const stat = fs35.statSync(tarPath);
24320
+ const stat = fs36.statSync(tarPath);
23951
24321
  const manifest = {
23952
24322
  kind: "pg",
23953
24323
  worldId,
@@ -23971,18 +24341,18 @@ async function handleEvict(opts) {
23971
24341
  const maxBytes = Number.isInteger(cap) && cap > 0 ? cap : 5 * 1024 * 1024 * 1024;
23972
24342
  if (opts.dryRun) {
23973
24343
  const root = snapshotsDir();
23974
- if (!fs35.existsSync(root)) {
23975
- console.log(pc20.dim("No snapshot dir; nothing to evict."));
24344
+ if (!fs36.existsSync(root)) {
24345
+ console.log(pc21.dim("No snapshot dir; nothing to evict."));
23976
24346
  return;
23977
24347
  }
23978
24348
  const allTars = [];
23979
24349
  const walk2 = (d) => {
23980
- for (const entry of fs35.readdirSync(d, { withFileTypes: true })) {
23981
- const full = path38.join(d, entry.name);
24350
+ for (const entry of fs36.readdirSync(d, { withFileTypes: true })) {
24351
+ const full = path39.join(d, entry.name);
23982
24352
  if (entry.isDirectory()) {
23983
24353
  walk2(full);
23984
24354
  } else if (entry.name.endsWith(".tar.gz")) {
23985
- const stat = fs35.statSync(full);
24355
+ const stat = fs36.statSync(full);
23986
24356
  allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
23987
24357
  }
23988
24358
  }
@@ -23990,7 +24360,7 @@ async function handleEvict(opts) {
23990
24360
  walk2(root);
23991
24361
  const total = allTars.reduce((a, t) => a + t.size, 0);
23992
24362
  if (total <= maxBytes) {
23993
- console.log(`${formatBytes2(total)} total \u2264 ${formatBytes2(maxBytes)} cap; nothing to evict.`);
24363
+ console.log(`${formatBytes3(total)} total \u2264 ${formatBytes3(maxBytes)} cap; nothing to evict.`);
23994
24364
  return;
23995
24365
  }
23996
24366
  allTars.sort((a, b) => a.mtime - b.mtime);
@@ -24001,21 +24371,21 @@ async function handleEvict(opts) {
24001
24371
  toEvict.push(t);
24002
24372
  remaining -= t.size;
24003
24373
  }
24004
- printHeader(`Would evict ${toEvict.length} snapshot(s) (${formatBytes2(total - remaining)})`);
24374
+ printHeader(`Would evict ${toEvict.length} snapshot(s) (${formatBytes3(total - remaining)})`);
24005
24375
  console.log();
24006
24376
  for (const t of toEvict) {
24007
24377
  const age = formatAge2(Date.now() - t.mtime);
24008
- console.log(` ${pc20.dim(formatBytes2(t.size).padStart(8))} ${age.padStart(10)} ${t.path}`);
24378
+ console.log(` ${pc21.dim(formatBytes3(t.size).padStart(8))} ${age.padStart(10)} ${t.path}`);
24009
24379
  }
24010
24380
  console.log();
24011
- console.log(pc20.dim(`Total after eviction: ${formatBytes2(remaining)} (cap: ${formatBytes2(maxBytes)})`));
24381
+ console.log(pc21.dim(`Total after eviction: ${formatBytes3(remaining)} (cap: ${formatBytes3(maxBytes)})`));
24012
24382
  return;
24013
24383
  }
24014
24384
  const freed = evictOldSnapshotsWithFlock(maxBytes);
24015
24385
  if (freed > 0) {
24016
- printSuccess(`Evicted ${formatBytes2(freed)} (cap: ${formatBytes2(maxBytes)})`);
24386
+ printSuccess(`Evicted ${formatBytes3(freed)} (cap: ${formatBytes3(maxBytes)})`);
24017
24387
  } else {
24018
- console.log(pc20.dim("No eviction needed (or another process held the lock)."));
24388
+ console.log(pc21.dim("No eviction needed (or another process held the lock)."));
24019
24389
  }
24020
24390
  }
24021
24391
  function handleList2(worldIdFilter) {
@@ -24023,7 +24393,7 @@ function handleList2(worldIdFilter) {
24023
24393
  const entries = listSnapshots(worldIdFilter);
24024
24394
  if (entries.length === 0) {
24025
24395
  const where = worldIdFilter ? ` for world "${worldIdFilter}"` : "";
24026
- console.log(pc20.dim(`No snapshots found${where}. Run \`olam world snapshot create <worldId>\` first.`));
24396
+ console.log(pc21.dim(`No snapshots found${where}. Run \`olam world snapshot create <worldId>\` first.`));
24027
24397
  return;
24028
24398
  }
24029
24399
  printHeader(`${entries.length} snapshot(s)`);
@@ -24032,15 +24402,15 @@ function handleList2(worldIdFilter) {
24032
24402
  for (const entry of entries) {
24033
24403
  const { manifest } = entry;
24034
24404
  if (manifest.worldId !== lastWorldId) {
24035
- console.log(pc20.bold(manifest.worldId));
24405
+ console.log(pc21.bold(manifest.worldId));
24036
24406
  lastWorldId = manifest.worldId;
24037
24407
  }
24038
24408
  const repo = manifest.repo ?? "(all repos)";
24039
- const size = formatBytes2(manifest.sizeBytes);
24409
+ const size = formatBytes3(manifest.sizeBytes);
24040
24410
  const age = formatAge2(entry.ageMs);
24041
- const kindColor = manifest.kind === "gems" ? pc20.magenta(manifest.kind) : manifest.kind === "node" ? pc20.cyan(manifest.kind) : pc20.yellow(manifest.kind);
24411
+ const kindColor = manifest.kind === "gems" ? pc21.magenta(manifest.kind) : manifest.kind === "node" ? pc21.cyan(manifest.kind) : pc21.yellow(manifest.kind);
24042
24412
  console.log(
24043
- ` ${kindColor.padEnd(6)} ${pc20.dim(repo.padEnd(24))} ${manifest.fingerprint} ${size.padStart(8)} ${age}`
24413
+ ` ${kindColor.padEnd(6)} ${pc21.dim(repo.padEnd(24))} ${manifest.fingerprint} ${size.padStart(8)} ${age}`
24044
24414
  );
24045
24415
  }
24046
24416
  console.log();
@@ -24057,7 +24427,7 @@ async function loadWorldMeta(worldId) {
24057
24427
  }
24058
24428
  return { workspacePath: world.workspacePath, repoNames: [...world.repos] };
24059
24429
  }
24060
- function formatBytes2(bytes) {
24430
+ function formatBytes3(bytes) {
24061
24431
  if (bytes < 1024) return `${bytes}B`;
24062
24432
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
24063
24433
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
@@ -24075,35 +24445,35 @@ function formatAge2(ms) {
24075
24445
  // src/commands/refresh.ts
24076
24446
  init_context();
24077
24447
  init_output();
24078
- import * as fs37 from "node:fs";
24079
- import * as os21 from "node:os";
24080
- import * as path40 from "node:path";
24448
+ import * as fs38 from "node:fs";
24449
+ import * as os22 from "node:os";
24450
+ import * as path41 from "node:path";
24081
24451
  import { spawnSync as spawnSync13 } from "node:child_process";
24082
24452
  import ora8 from "ora";
24083
24453
 
24084
24454
  // src/commands/refresh-helpers.ts
24085
- import * as fs36 from "node:fs";
24086
- import * as path39 from "node:path";
24455
+ import * as fs37 from "node:fs";
24456
+ import * as path40 from "node:path";
24087
24457
  function collectCpSourceFiles(standaloneDir) {
24088
- if (!fs36.existsSync(standaloneDir)) {
24458
+ if (!fs37.existsSync(standaloneDir)) {
24089
24459
  throw new Error(`CP standalone dir not found: ${standaloneDir}`);
24090
24460
  }
24091
24461
  const entries = [];
24092
- const topLevel = fs36.readdirSync(standaloneDir).filter((f) => {
24093
- const stat = fs36.statSync(path39.join(standaloneDir, f));
24462
+ const topLevel = fs37.readdirSync(standaloneDir).filter((f) => {
24463
+ const stat = fs37.statSync(path40.join(standaloneDir, f));
24094
24464
  return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
24095
24465
  }).sort();
24096
24466
  for (const f of topLevel) {
24097
- entries.push({ srcPath: path39.join(standaloneDir, f), destRelPath: f });
24467
+ entries.push({ srcPath: path40.join(standaloneDir, f), destRelPath: f });
24098
24468
  }
24099
- const libDir = path39.join(standaloneDir, "lib");
24100
- if (fs36.existsSync(libDir) && fs36.statSync(libDir).isDirectory()) {
24101
- const libFiles = fs36.readdirSync(libDir).filter((f) => {
24102
- const stat = fs36.statSync(path39.join(libDir, f));
24469
+ const libDir = path40.join(standaloneDir, "lib");
24470
+ if (fs37.existsSync(libDir) && fs37.statSync(libDir).isDirectory()) {
24471
+ const libFiles = fs37.readdirSync(libDir).filter((f) => {
24472
+ const stat = fs37.statSync(path40.join(libDir, f));
24103
24473
  return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
24104
24474
  }).sort();
24105
24475
  for (const f of libFiles) {
24106
- entries.push({ srcPath: path39.join(libDir, f), destRelPath: `lib/${f}` });
24476
+ entries.push({ srcPath: path40.join(libDir, f), destRelPath: `lib/${f}` });
24107
24477
  }
24108
24478
  }
24109
24479
  return entries;
@@ -24161,16 +24531,16 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
24161
24531
  error: err instanceof Error ? err.message : String(err)
24162
24532
  };
24163
24533
  }
24164
- const stagingDir = fs37.mkdtempSync(
24165
- path40.join(os21.tmpdir(), `olam-refresh-${worldId}-`)
24534
+ const stagingDir = fs38.mkdtempSync(
24535
+ path41.join(os22.tmpdir(), `olam-refresh-${worldId}-`)
24166
24536
  );
24167
24537
  try {
24168
24538
  const hasLib = entries.some((e) => e.destRelPath.startsWith("lib/"));
24169
24539
  if (hasLib) {
24170
- fs37.mkdirSync(path40.join(stagingDir, "lib"), { recursive: true });
24540
+ fs38.mkdirSync(path41.join(stagingDir, "lib"), { recursive: true });
24171
24541
  }
24172
24542
  for (const { srcPath, destRelPath } of entries) {
24173
- fs37.copyFileSync(srcPath, path40.join(stagingDir, destRelPath));
24543
+ fs38.copyFileSync(srcPath, path41.join(stagingDir, destRelPath));
24174
24544
  }
24175
24545
  const cpResult = docker([
24176
24546
  "cp",
@@ -24185,7 +24555,7 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
24185
24555
  };
24186
24556
  }
24187
24557
  } finally {
24188
- fs37.rmSync(stagingDir, { recursive: true, force: true });
24558
+ fs38.rmSync(stagingDir, { recursive: true, force: true });
24189
24559
  }
24190
24560
  if (opts.restart) {
24191
24561
  const restartResult = docker([
@@ -24222,11 +24592,11 @@ function registerRefresh(program2) {
24222
24592
  process.exitCode = 1;
24223
24593
  return;
24224
24594
  }
24225
- const standaloneDir = path40.join(
24595
+ const standaloneDir = path41.join(
24226
24596
  process.cwd(),
24227
24597
  "packages/control-plane/standalone"
24228
24598
  );
24229
- if (!fs37.existsSync(standaloneDir)) {
24599
+ if (!fs38.existsSync(standaloneDir)) {
24230
24600
  printError(
24231
24601
  `CP standalone source not found at ${standaloneDir}.
24232
24602
  Run \`olam refresh\` from the olam repo root.`
@@ -24305,11 +24675,11 @@ Run \`olam refresh\` from the olam repo root.`
24305
24675
  }
24306
24676
 
24307
24677
  // src/commands/diagnose.ts
24308
- import * as fs38 from "node:fs";
24309
- import * as os22 from "node:os";
24310
- import * as path41 from "node:path";
24311
- import { execFileSync as execFileSync8, execSync as execSync12 } from "node:child_process";
24312
- import pc21 from "picocolors";
24678
+ import * as fs39 from "node:fs";
24679
+ import * as os23 from "node:os";
24680
+ import * as path42 from "node:path";
24681
+ import { execFileSync as execFileSync9, execSync as execSync12 } from "node:child_process";
24682
+ import pc22 from "picocolors";
24313
24683
 
24314
24684
  // ../core/dist/diagnose/secret-stripper.js
24315
24685
  var SECRET_PATTERNS = [
@@ -24342,9 +24712,9 @@ function stripSecrets(input) {
24342
24712
  }
24343
24713
 
24344
24714
  // src/commands/diagnose.ts
24345
- var DIAGNOSTICS_DIR = path41.join(os22.homedir(), ".olam", "diagnostics");
24346
- var LOG_DIR = path41.join(os22.homedir(), ".olam", "log");
24347
- var CACHE_DIR = path41.join(os22.homedir(), ".olam", "cache");
24715
+ var DIAGNOSTICS_DIR = path42.join(os23.homedir(), ".olam", "diagnostics");
24716
+ var LOG_DIR = path42.join(os23.homedir(), ".olam", "log");
24717
+ var CACHE_DIR = path42.join(os23.homedir(), ".olam", "cache");
24348
24718
  var LOG_TAIL_LINES = 200;
24349
24719
  function safeExec(cmd) {
24350
24720
  try {
@@ -24354,14 +24724,14 @@ function safeExec(cmd) {
24354
24724
  }
24355
24725
  }
24356
24726
  function defaultZip(zipPath, files) {
24357
- execFileSync8("zip", ["-j", zipPath, ...files]);
24727
+ execFileSync9("zip", ["-j", zipPath, ...files]);
24358
24728
  }
24359
24729
  async function buildDiagnosticsZip(_exec = (cmd) => safeExec(cmd), _outDir = DIAGNOSTICS_DIR, _logDir = LOG_DIR, _zip = defaultZip) {
24360
24730
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 23);
24361
- const zipPath = path41.join(_outDir, `olam-diag-${ts}.zip`);
24362
- const tmpDir = fs38.mkdtempSync(path41.join(os22.tmpdir(), "olam-diag-"));
24731
+ const zipPath = path42.join(_outDir, `olam-diag-${ts}.zip`);
24732
+ const tmpDir = fs39.mkdtempSync(path42.join(os23.tmpdir(), "olam-diag-"));
24363
24733
  try {
24364
- fs38.mkdirSync(_outDir, { recursive: true });
24734
+ fs39.mkdirSync(_outDir, { recursive: true });
24365
24735
  const entries = [];
24366
24736
  const version = process.env["OLAM_CLI_VERSION"] ?? "unknown";
24367
24737
  const nodeVersion = process.version;
@@ -24372,19 +24742,19 @@ platform: ${platform}
24372
24742
  `;
24373
24743
  _writeEntry(tmpDir, "version.txt", stripSecrets(versionContent), entries);
24374
24744
  const osContent = [
24375
- `os: ${os22.type()} ${os22.release()}`,
24376
- `arch: ${os22.arch()}`,
24377
- `uptime: ${os22.uptime()}s`
24745
+ `os: ${os23.type()} ${os23.release()}`,
24746
+ `arch: ${os23.arch()}`,
24747
+ `uptime: ${os23.uptime()}s`
24378
24748
  ].join("\n") + "\n";
24379
24749
  _writeEntry(tmpDir, "os-info.txt", stripSecrets(osContent), entries);
24380
- const depsFile = path41.join(CACHE_DIR, "deps.json");
24381
- if (fs38.existsSync(depsFile)) {
24382
- const deps = fs38.readFileSync(depsFile, "utf-8");
24750
+ const depsFile = path42.join(CACHE_DIR, "deps.json");
24751
+ if (fs39.existsSync(depsFile)) {
24752
+ const deps = fs39.readFileSync(depsFile, "utf-8");
24383
24753
  _writeEntry(tmpDir, "deps.json", stripSecrets(deps), entries);
24384
24754
  }
24385
24755
  const latestLog = _latestLog(_logDir);
24386
24756
  if (latestLog) {
24387
- const lines = fs38.readFileSync(latestLog, "utf-8").split("\n");
24757
+ const lines = fs39.readFileSync(latestLog, "utf-8").split("\n");
24388
24758
  const tail = lines.slice(-LOG_TAIL_LINES).join("\n");
24389
24759
  _writeEntry(tmpDir, "log-tail.txt", stripSecrets(tail), entries);
24390
24760
  }
@@ -24396,38 +24766,38 @@ platform: ${platform}
24396
24766
  if (authAudit) {
24397
24767
  _writeEntry(tmpDir, "audit-auth-callers.txt", stripSecrets(authAudit), entries);
24398
24768
  }
24399
- const fileArgs = entries.map((e) => path41.join(tmpDir, e));
24769
+ const fileArgs = entries.map((e) => path42.join(tmpDir, e));
24400
24770
  try {
24401
24771
  _zip(zipPath, fileArgs);
24402
24772
  } catch (err) {
24403
24773
  throw new Error(`zip command produced no output file. zip stderr: ${err.message}`);
24404
24774
  }
24405
- if (!fs38.existsSync(zipPath)) {
24775
+ if (!fs39.existsSync(zipPath)) {
24406
24776
  throw new Error("zip command produced no output file.");
24407
24777
  }
24408
24778
  return { zipPath, entries };
24409
24779
  } finally {
24410
24780
  try {
24411
- fs38.rmSync(tmpDir, { recursive: true, force: true });
24781
+ fs39.rmSync(tmpDir, { recursive: true, force: true });
24412
24782
  } catch {
24413
24783
  }
24414
24784
  }
24415
24785
  }
24416
24786
  function _writeEntry(dir, name, content, entries) {
24417
- fs38.writeFileSync(path41.join(dir, name), content, { mode: 420 });
24787
+ fs39.writeFileSync(path42.join(dir, name), content, { mode: 420 });
24418
24788
  entries.push(name);
24419
24789
  }
24420
24790
  function _latestLog(logDir) {
24421
- if (!fs38.existsSync(logDir)) return null;
24422
- const files = fs38.readdirSync(logDir).filter((f) => f.startsWith("host-")).sort().reverse();
24423
- return files.length > 0 ? path41.join(logDir, files[0]) : null;
24791
+ if (!fs39.existsSync(logDir)) return null;
24792
+ const files = fs39.readdirSync(logDir).filter((f) => f.startsWith("host-")).sort().reverse();
24793
+ return files.length > 0 ? path42.join(logDir, files[0]) : null;
24424
24794
  }
24425
24795
  async function buildTelemetryPayload() {
24426
24796
  const channel = "stable";
24427
- const manifestFile = path41.join(CACHE_DIR, "manifest.json");
24797
+ const manifestFile = path42.join(CACHE_DIR, "manifest.json");
24428
24798
  let manifestAgeHours = null;
24429
- if (fs38.existsSync(manifestFile)) {
24430
- const mtime = fs38.statSync(manifestFile).mtime.getTime();
24799
+ if (fs39.existsSync(manifestFile)) {
24800
+ const mtime = fs39.statSync(manifestFile).mtime.getTime();
24431
24801
  manifestAgeHours = Math.round((Date.now() - mtime) / 36e5);
24432
24802
  }
24433
24803
  return {
@@ -24447,47 +24817,47 @@ function registerDiagnose(program2) {
24447
24817
  return;
24448
24818
  }
24449
24819
  if (!opts.quiet) {
24450
- console.log(pc21.cyan("Building diagnostics zip\u2026"));
24820
+ console.log(pc22.cyan("Building diagnostics zip\u2026"));
24451
24821
  }
24452
24822
  try {
24453
24823
  const { zipPath, entries } = await buildDiagnosticsZip();
24454
24824
  if (!opts.quiet) {
24455
- console.log(pc21.green(`Done: ${zipPath}`));
24456
- console.log(pc21.dim(`Contents: ${entries.join(", ")}`));
24825
+ console.log(pc22.green(`Done: ${zipPath}`));
24826
+ console.log(pc22.dim(`Contents: ${entries.join(", ")}`));
24457
24827
  }
24458
24828
  if (opts.upload) {
24459
- console.log(pc21.yellow(
24829
+ console.log(pc22.yellow(
24460
24830
  `Telemetry endpoint not yet provisioned. Share the zip manually:
24461
24831
  File: ${zipPath}
24462
24832
  See docs/runbooks/share-diagnostics.md for instructions.`
24463
24833
  ));
24464
24834
  }
24465
24835
  } catch (err) {
24466
- console.error(pc21.red(`Diagnose failed: ${err.message}`));
24836
+ console.error(pc22.red(`Diagnose failed: ${err.message}`));
24467
24837
  process.exitCode = 1;
24468
24838
  }
24469
24839
  });
24470
24840
  }
24471
24841
 
24472
24842
  // src/commands/update.ts
24473
- import * as fs41 from "node:fs";
24474
- import * as os24 from "node:os";
24475
- import * as path44 from "node:path";
24843
+ import * as fs42 from "node:fs";
24844
+ import * as os25 from "node:os";
24845
+ import * as path45 from "node:path";
24476
24846
  import { execSync as execSync13 } from "node:child_process";
24477
- import pc22 from "picocolors";
24847
+ import pc23 from "picocolors";
24478
24848
 
24479
24849
  // src/lib/symlink-reconcile.ts
24480
- import * as fs39 from "node:fs";
24481
- import * as path42 from "node:path";
24850
+ import * as fs40 from "node:fs";
24851
+ import * as path43 from "node:path";
24482
24852
  var realFs = {
24483
- readdirSync: (p) => fs39.readdirSync(p),
24484
- existsSync: (p) => fs39.existsSync(p),
24485
- lstatSync: (p) => fs39.lstatSync(p),
24486
- readlinkSync: (p) => fs39.readlinkSync(p),
24487
- symlinkSync: (t, l) => fs39.symlinkSync(t, l),
24488
- unlinkSync: (p) => fs39.unlinkSync(p),
24853
+ readdirSync: (p) => fs40.readdirSync(p),
24854
+ existsSync: (p) => fs40.existsSync(p),
24855
+ lstatSync: (p) => fs40.lstatSync(p),
24856
+ readlinkSync: (p) => fs40.readlinkSync(p),
24857
+ symlinkSync: (t, l) => fs40.symlinkSync(t, l),
24858
+ unlinkSync: (p) => fs40.unlinkSync(p),
24489
24859
  mkdirSync: (p, o) => {
24490
- fs39.mkdirSync(p, o);
24860
+ fs40.mkdirSync(p, o);
24491
24861
  }
24492
24862
  };
24493
24863
  function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
@@ -24497,8 +24867,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
24497
24867
  _fs.mkdirSync(claudeSkillsDir, { recursive: true });
24498
24868
  const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
24499
24869
  for (const skill of sourceSkills) {
24500
- const linkPath = path42.join(claudeSkillsDir, skill);
24501
- const target = path42.join(npmSkillsDir, skill);
24870
+ const linkPath = path43.join(claudeSkillsDir, skill);
24871
+ const target = path43.join(npmSkillsDir, skill);
24502
24872
  if (!_fs.existsSync(linkPath)) {
24503
24873
  try {
24504
24874
  _fs.symlinkSync(target, linkPath);
@@ -24511,7 +24881,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
24511
24881
  }
24512
24882
  const deployedEntries = _fs.existsSync(claudeSkillsDir) ? _fs.readdirSync(claudeSkillsDir).filter((d) => d.startsWith("olam-")) : [];
24513
24883
  for (const entry of deployedEntries) {
24514
- const linkPath = path42.join(claudeSkillsDir, entry);
24884
+ const linkPath = path43.join(claudeSkillsDir, entry);
24515
24885
  let isSymlink = false;
24516
24886
  try {
24517
24887
  isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
@@ -24536,9 +24906,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
24536
24906
 
24537
24907
  // src/commands/update.ts
24538
24908
  var PACKAGE_NAME = "@pleri/olam-cli";
24539
- var CACHE_DIR2 = path44.join(os24.homedir(), ".olam", "cache");
24540
- var LOG_DIR2 = path44.join(os24.homedir(), ".olam", "log");
24541
- var LAST_STABLE_FILE = path44.join(CACHE_DIR2, "last-stable.txt");
24909
+ var CACHE_DIR2 = path45.join(os25.homedir(), ".olam", "cache");
24910
+ var LOG_DIR2 = path45.join(os25.homedir(), ".olam", "log");
24911
+ var LAST_STABLE_FILE = path45.join(CACHE_DIR2, "last-stable.txt");
24542
24912
  function defaultExec(cmd) {
24543
24913
  try {
24544
24914
  const stdout = execSync13(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
@@ -24560,22 +24930,22 @@ function getCurrentVersion(_exec = defaultExec) {
24560
24930
  }
24561
24931
  function readLastStable(file = LAST_STABLE_FILE) {
24562
24932
  try {
24563
- const v = fs41.readFileSync(file, "utf-8").trim();
24933
+ const v = fs42.readFileSync(file, "utf-8").trim();
24564
24934
  return v || null;
24565
24935
  } catch {
24566
24936
  return null;
24567
24937
  }
24568
24938
  }
24569
24939
  function writeLastStable(version, file = LAST_STABLE_FILE) {
24570
- fs41.mkdirSync(path44.dirname(file), { recursive: true });
24571
- fs41.writeFileSync(file, version, { mode: 420 });
24940
+ fs42.mkdirSync(path45.dirname(file), { recursive: true });
24941
+ fs42.writeFileSync(file, version, { mode: 420 });
24572
24942
  }
24573
24943
  function logUpdateFailure(stderr) {
24574
24944
  const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
24575
- const logFile = path44.join(LOG_DIR2, `update-${ts}.log`);
24945
+ const logFile = path45.join(LOG_DIR2, `update-${ts}.log`);
24576
24946
  try {
24577
- fs41.mkdirSync(LOG_DIR2, { recursive: true });
24578
- fs41.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
24947
+ fs42.mkdirSync(LOG_DIR2, { recursive: true });
24948
+ fs42.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
24579
24949
  ${stderr}
24580
24950
  `, "utf-8");
24581
24951
  } catch {
@@ -24626,52 +24996,52 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
24626
24996
  writeLastStable(prevVersion);
24627
24997
  }
24628
24998
  if (!quiet) {
24629
- console.log(pc22.cyan(`Installing ${PACKAGE_NAME}@${channel}\u2026`));
24999
+ console.log(pc23.cyan(`Installing ${PACKAGE_NAME}@${channel}\u2026`));
24630
25000
  }
24631
25001
  const installResult = _exec(`npm install -g ${PACKAGE_NAME}@${channel}`);
24632
25002
  if (installResult.exitCode !== 0) {
24633
25003
  logUpdateFailure(installResult.stderr);
24634
25004
  if (!quiet) {
24635
- console.error(pc22.red("Update failed."));
25005
+ console.error(pc23.red("Update failed."));
24636
25006
  }
24637
25007
  const prev = readLastStable();
24638
25008
  if (prev) {
24639
25009
  if (!quiet) {
24640
- console.log(pc22.yellow(`Restoring to ${prev}\u2026`));
25010
+ console.log(pc23.yellow(`Restoring to ${prev}\u2026`));
24641
25011
  }
24642
25012
  const restoreResult = _exec(`npm install -g ${PACKAGE_NAME}@${prev}`);
24643
25013
  if (restoreResult.exitCode !== 0) {
24644
25014
  if (!quiet) {
24645
- console.error(pc22.red(
25015
+ console.error(pc23.red(
24646
25016
  `Restore also failed. Run: npm install -g ${PACKAGE_NAME}@${prev} manually.`
24647
25017
  ));
24648
25018
  }
24649
25019
  } else if (!quiet) {
24650
- console.log(pc22.yellow(`Restored to ${prev}.`));
25020
+ console.log(pc23.yellow(`Restored to ${prev}.`));
24651
25021
  }
24652
25022
  } else if (!quiet) {
24653
- console.error(pc22.red("No previous version cached; cannot auto-restore."));
25023
+ console.error(pc23.red("No previous version cached; cannot auto-restore."));
24654
25024
  }
24655
25025
  return { action: "restored", prevVersion: prev ?? void 0, exitCode: 11 };
24656
25026
  }
24657
25027
  const newVersion = getCurrentVersion(_exec) ?? void 0;
24658
25028
  if (!quiet && newVersion) {
24659
- console.log(pc22.green(`Updated to ${newVersion}.`));
25029
+ console.log(pc23.green(`Updated to ${newVersion}.`));
24660
25030
  }
24661
25031
  const npmRootResult = _getNpmRoot("npm root -g");
24662
25032
  let symlinkResult = { added: [], removed: [] };
24663
25033
  if (npmRootResult.exitCode === 0) {
24664
25034
  const npmRoot = npmRootResult.stdout.trim();
24665
- const npmSkillsDir = path44.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
24666
- const claudeSkillsDir = path44.join(os24.homedir(), ".claude", "skills");
25035
+ const npmSkillsDir = path45.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
25036
+ const claudeSkillsDir = path45.join(os25.homedir(), ".claude", "skills");
24667
25037
  const rec = _reconcile(npmSkillsDir, claudeSkillsDir);
24668
25038
  symlinkResult = { added: rec.added, removed: rec.removed };
24669
25039
  if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
24670
25040
  if (rec.added.length > 0) {
24671
- console.log(pc22.dim(`Skills added: ${rec.added.join(", ")}`));
25041
+ console.log(pc23.dim(`Skills added: ${rec.added.join(", ")}`));
24672
25042
  }
24673
25043
  if (rec.removed.length > 0) {
24674
- console.log(pc22.dim(`Skills removed (dangling): ${rec.removed.join(", ")}`));
25044
+ console.log(pc23.dim(`Skills removed (dangling): ${rec.removed.join(", ")}`));
24675
25045
  }
24676
25046
  }
24677
25047
  }
@@ -24709,8 +25079,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
24709
25079
  if (npmRootResult.exitCode === 0) {
24710
25080
  const npmRoot = npmRootResult.stdout.trim();
24711
25081
  _reconcile(
24712
- path44.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
24713
- path44.join(os24.homedir(), ".claude", "skills")
25082
+ path45.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
25083
+ path45.join(os25.homedir(), ".claude", "skills")
24714
25084
  );
24715
25085
  }
24716
25086
  return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
@@ -24765,7 +25135,7 @@ function registerUpdate(program2) {
24765
25135
  // src/commands/begin.ts
24766
25136
  init_host_cp();
24767
25137
  init_open_url();
24768
- import pc23 from "picocolors";
25138
+ import pc24 from "picocolors";
24769
25139
  async function doBegin(opts, _startFn = startHostCp, _openFn = openUrl) {
24770
25140
  const prevExitCode = process.exitCode;
24771
25141
  await _startFn({ showToken: opts.showToken });
@@ -24775,7 +25145,7 @@ async function doBegin(opts, _startFn = startHostCp, _openFn = openUrl) {
24775
25145
  const token = readToken();
24776
25146
  if (token) {
24777
25147
  const base = `http://127.0.0.1:${HOST_CP_PORT}/`;
24778
- console.log(pc23.dim(`Opening ${base}`));
25148
+ console.log(pc24.dim(`Opening ${base}`));
24779
25149
  _openFn(`${base}?token=${token}`);
24780
25150
  }
24781
25151
  }
@@ -24791,7 +25161,7 @@ function registerBegin(program2) {
24791
25161
  }
24792
25162
 
24793
25163
  // src/commands/config.ts
24794
- import * as fs43 from "node:fs";
25164
+ import * as fs44 from "node:fs";
24795
25165
  import { createRequire as createRequire4 } from "node:module";
24796
25166
 
24797
25167
  // ../core/dist/global-config/index.js
@@ -24800,12 +25170,12 @@ init_store2();
24800
25170
 
24801
25171
  // ../core/dist/global-config/repos.js
24802
25172
  init_store2();
24803
- import * as fs42 from "node:fs";
24804
- import * as os25 from "node:os";
24805
- import * as path45 from "node:path";
25173
+ import * as fs43 from "node:fs";
25174
+ import * as os26 from "node:os";
25175
+ import * as path46 from "node:path";
24806
25176
  function expandPath(p) {
24807
25177
  if (p === "~" || p.startsWith("~/")) {
24808
- return path45.join(os25.homedir(), p.slice(1));
25178
+ return path46.join(os26.homedir(), p.slice(1));
24809
25179
  }
24810
25180
  return p;
24811
25181
  }
@@ -24818,7 +25188,7 @@ function addRepo(entry) {
24818
25188
  throw new Error(`repo "${entry.name}" already registered. Use "olam repos update" to change its path.`);
24819
25189
  }
24820
25190
  const resolvedPath = expandPath(entry.path);
24821
- if (!fs42.existsSync(resolvedPath)) {
25191
+ if (!fs43.existsSync(resolvedPath)) {
24822
25192
  throw new Error(`path "${entry.path}" does not exist. Verify the path is correct.`);
24823
25193
  }
24824
25194
  const now = Date.now();
@@ -24847,7 +25217,7 @@ function updateRepo(name, updates) {
24847
25217
  throw new Error(`repo "${name}" is not registered. Run "olam repos list" to see registered repos.`);
24848
25218
  }
24849
25219
  const resolvedUpdatePath = updates.path !== void 0 ? expandPath(updates.path) : void 0;
24850
- if (resolvedUpdatePath !== void 0 && !fs42.existsSync(resolvedUpdatePath)) {
25220
+ if (resolvedUpdatePath !== void 0 && !fs43.existsSync(resolvedUpdatePath)) {
24851
25221
  throw new Error(`path "${updates.path}" does not exist. Verify the path is correct.`);
24852
25222
  }
24853
25223
  const existing = config.repos[idx];
@@ -24877,14 +25247,14 @@ function registerConfig(program2) {
24877
25247
  const config = program2.command("config").description("Manage global olam configuration");
24878
25248
  config.command("validate [path]").description("Validate ~/.olam/config.json (or a custom path) against the schema").action((filePath) => {
24879
25249
  const resolvedPath = filePath ?? globalConfigPath();
24880
- if (!fs43.existsSync(resolvedPath)) {
25250
+ if (!fs44.existsSync(resolvedPath)) {
24881
25251
  process.stderr.write(`config file not found: ${resolvedPath}
24882
25252
  `);
24883
25253
  process.exit(1);
24884
25254
  }
24885
25255
  let raw;
24886
25256
  try {
24887
- raw = fs43.readFileSync(resolvedPath, "utf-8");
25257
+ raw = fs44.readFileSync(resolvedPath, "utf-8");
24888
25258
  } catch (err) {
24889
25259
  const msg = err instanceof Error ? err.message : String(err);
24890
25260
  process.stderr.write(`cannot read ${resolvedPath}: ${msg}
@@ -24920,7 +25290,7 @@ function registerConfig(program2) {
24920
25290
  }
24921
25291
 
24922
25292
  // src/commands/repos.ts
24923
- import pc24 from "picocolors";
25293
+ import pc25 from "picocolors";
24924
25294
  init_output();
24925
25295
  function asMessage(err) {
24926
25296
  return err instanceof Error ? err.message : String(err);
@@ -24930,14 +25300,14 @@ function registerRepos(program2) {
24930
25300
  repos.command("list").description("List all registered repos").action(() => {
24931
25301
  const all = listRepos();
24932
25302
  if (all.length === 0) {
24933
- console.log(pc24.dim("0 repo(s) registered. Add one with: olam repos add --name <n> --path <p>"));
25303
+ console.log(pc25.dim("0 repo(s) registered. Add one with: olam repos add --name <n> --path <p>"));
24934
25304
  return;
24935
25305
  }
24936
25306
  printHeader(`${all.length} repo(s)`);
24937
25307
  for (const r of all) {
24938
25308
  const when = new Date(r.addedAt).toISOString().slice(0, 10);
24939
25309
  console.log(
24940
- ` ${pc24.bold(r.name.padEnd(24))} ${r.path.padEnd(48)} ${pc24.dim(when)}`
25310
+ ` ${pc25.bold(r.name.padEnd(24))} ${r.path.padEnd(48)} ${pc25.dim(when)}`
24941
25311
  );
24942
25312
  }
24943
25313
  });
@@ -24980,7 +25350,7 @@ function registerRepos(program2) {
24980
25350
  }
24981
25351
 
24982
25352
  // src/commands/runbooks.ts
24983
- import pc25 from "picocolors";
25353
+ import pc26 from "picocolors";
24984
25354
  init_output();
24985
25355
  function asMessage2(err) {
24986
25356
  return err instanceof Error ? err.message : String(err);
@@ -25011,14 +25381,14 @@ function parsePortFlags(ports) {
25011
25381
  }
25012
25382
  function formatConflict(c) {
25013
25383
  const occupantStr = c.occupant.type === "olam-world" ? `in use by world "${c.occupant.worldId}" (olam)` : `in use by PID ${c.occupant.pid ?? "unknown"} (non-olam process)`;
25014
- return ` ${pc25.red("\u2717")} ${c.repoName}.${c.serviceName}:${c.port} \u2014 ${occupantStr}`;
25384
+ return ` ${pc26.red("\u2717")} ${c.repoName}.${c.serviceName}:${c.port} \u2014 ${occupantStr}`;
25015
25385
  }
25016
25386
  function registerRunbooks(program2) {
25017
25387
  const runbooks = program2.command("runbooks").description("Manage runbooks in the global config");
25018
25388
  runbooks.command("list").description("List all runbooks").action(() => {
25019
25389
  const all = listRunbooks();
25020
25390
  if (all.length === 0) {
25021
- console.log(pc25.dim("0 runbook(s). Add one with: olam runbooks add <name> --repos <repo>"));
25391
+ console.log(pc26.dim("0 runbook(s). Add one with: olam runbooks add <name> --repos <repo>"));
25022
25392
  return;
25023
25393
  }
25024
25394
  printHeader(`${all.length} runbook(s)`);
@@ -25026,7 +25396,7 @@ function registerRunbooks(program2) {
25026
25396
  const when = new Date(rb.updatedAt).toISOString().slice(0, 10);
25027
25397
  const repoList = rb.repos.join(", ");
25028
25398
  console.log(
25029
- ` ${pc25.bold(rb.name.padEnd(24))} ${repoList.padEnd(40)} ${pc25.dim(when)}`
25399
+ ` ${pc26.bold(rb.name.padEnd(24))} ${repoList.padEnd(40)} ${pc26.dim(when)}`
25030
25400
  );
25031
25401
  }
25032
25402
  });
@@ -25082,17 +25452,17 @@ ${conflicts.length} port conflict(s). Stop the conflicting processes or update p
25082
25452
  return;
25083
25453
  }
25084
25454
  console.log(
25085
- pc25.dim(
25455
+ pc26.dim(
25086
25456
  `olam runbooks apply: port validation passed for "${name}" (repos: ${rb.repos.join(", ")}).`
25087
25457
  )
25088
25458
  );
25089
25459
  console.log(
25090
- pc25.dim(
25460
+ pc26.dim(
25091
25461
  `Hint: use "olam create --repos ${rb.repos.join(" ")}${opts.task ? ` --task "${opts.task}"` : ""}${opts.name ? ` --name ${opts.name}` : ""}" to create the world.`
25092
25462
  )
25093
25463
  );
25094
25464
  console.log(
25095
- pc25.yellow('Phase D will wire --runbook directly. For now, use "olam create --repos ..." above.')
25465
+ pc26.yellow('Phase D will wire --runbook directly. For now, use "olam create --repos ..." above.')
25096
25466
  );
25097
25467
  } catch (err) {
25098
25468
  printError(asMessage2(err));
@@ -25104,7 +25474,7 @@ ${conflicts.length} port conflict(s). Stop the conflicting processes or update p
25104
25474
  const rb = getRunbook(name);
25105
25475
  const { conflicts } = validateRunbookPorts(rb);
25106
25476
  if (!rb.portMap || Object.keys(rb.portMap).length === 0) {
25107
- console.log(pc25.dim(`runbook "${name}" declares no ports.`));
25477
+ console.log(pc26.dim(`runbook "${name}" declares no ports.`));
25108
25478
  return;
25109
25479
  }
25110
25480
  for (const [repoName, svcMap] of Object.entries(rb.portMap ?? {})) {
@@ -25113,7 +25483,7 @@ ${conflicts.length} port conflict(s). Stop the conflicting processes or update p
25113
25483
  if (conflict) {
25114
25484
  console.log(formatConflict(conflict));
25115
25485
  } else {
25116
- console.log(` ${pc25.green("\u2713")} ${repoName}.${svcName}:${port} \u2014 free`);
25486
+ console.log(` ${pc26.green("\u2713")} ${repoName}.${svcName}:${port} \u2014 free`);
25117
25487
  }
25118
25488
  }
25119
25489
  }
@@ -25124,7 +25494,7 @@ ${conflicts.length} port conflict(s). Stop the conflicting processes or update p
25124
25494
  );
25125
25495
  process.exitCode = 1;
25126
25496
  } else {
25127
- console.log(pc25.green("\n\u2713 all ports free"));
25497
+ console.log(pc26.green("\n\u2713 all ports free"));
25128
25498
  }
25129
25499
  } catch (err) {
25130
25500
  printError(asMessage2(err));
@@ -25214,8 +25584,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
25214
25584
  function authHeaders() {
25215
25585
  return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
25216
25586
  }
25217
- async function apiFetch(path48, init = {}) {
25218
- const res = await fetch(`${BASE_URL}${path48}`, {
25587
+ async function apiFetch(path49, init = {}) {
25588
+ const res = await fetch(`${BASE_URL}${path49}`, {
25219
25589
  ...init,
25220
25590
  headers: {
25221
25591
  "Content-Type": "application/json",
@@ -25367,7 +25737,7 @@ function registerMcpAdd(cmd) {
25367
25737
 
25368
25738
  // src/commands/mcp/list.ts
25369
25739
  init_output();
25370
- import pc26 from "picocolors";
25740
+ import pc27 from "picocolors";
25371
25741
  function registerMcpList(cmd) {
25372
25742
  cmd.command("list").description("List all registered MCP credentials").action(async () => {
25373
25743
  const client = getMcpAuthClient();
@@ -25382,8 +25752,8 @@ function registerMcpList(cmd) {
25382
25752
  }
25383
25753
  const mcps = data.mcps ?? [];
25384
25754
  if (mcps.length === 0) {
25385
- console.log(pc26.dim("No MCP credentials registered."));
25386
- console.log(pc26.dim("Add one with: olam mcp add <service>"));
25755
+ console.log(pc27.dim("No MCP credentials registered."));
25756
+ console.log(pc27.dim("Add one with: olam mcp add <service>"));
25387
25757
  return;
25388
25758
  }
25389
25759
  const [c0, c1, c2, c3] = [16, 20, 10, 24];
@@ -25394,12 +25764,12 @@ function registerMcpList(cmd) {
25394
25764
  "ENV VAR".padEnd(c3),
25395
25765
  "STATUS"
25396
25766
  ].join(" ");
25397
- console.log(pc26.dim(header));
25398
- console.log(pc26.dim("\u2500".repeat(header.length)));
25767
+ console.log(pc27.dim(header));
25768
+ console.log(pc27.dim("\u2500".repeat(header.length)));
25399
25769
  for (const m of mcps) {
25400
- const status = !m.validated ? pc26.yellow("unvalidated") : m.expired ? pc26.red("expired") : pc26.green("active");
25770
+ const status = !m.validated ? pc27.yellow("unvalidated") : m.expired ? pc27.red("expired") : pc27.green("active");
25401
25771
  const row = [
25402
- pc26.cyan(m.service.padEnd(c0)),
25772
+ pc27.cyan(m.service.padEnd(c0)),
25403
25773
  m.label.padEnd(c1).slice(0, c1),
25404
25774
  m.type.padEnd(c2),
25405
25775
  (m.envName ?? "\u2014").padEnd(c3).slice(0, c3),
@@ -25427,13 +25797,13 @@ function registerMcpRemove(cmd) {
25427
25797
 
25428
25798
  // src/commands/mcp/status.ts
25429
25799
  init_output();
25430
- import pc27 from "picocolors";
25800
+ import pc28 from "picocolors";
25431
25801
  function formatExpiry(expiresAt) {
25432
25802
  if (!expiresAt) return "\u2014";
25433
25803
  const ms = expiresAt - Date.now();
25434
- if (ms <= 0) return pc27.red("expired");
25804
+ if (ms <= 0) return pc28.red("expired");
25435
25805
  const hours = ms / (1e3 * 60 * 60);
25436
- if (hours < 1) return pc27.yellow(`${Math.ceil(ms / 6e4)}m`);
25806
+ if (hours < 1) return pc28.yellow(`${Math.ceil(ms / 6e4)}m`);
25437
25807
  return `${hours.toFixed(1)}h`;
25438
25808
  }
25439
25809
  function registerMcpStatus(cmd) {
@@ -25450,14 +25820,14 @@ function registerMcpStatus(cmd) {
25450
25820
  const mcps = data.mcps ?? [];
25451
25821
  printHeader(`MCP Credentials (${mcps.length})`);
25452
25822
  if (mcps.length === 0) {
25453
- console.log(pc27.dim("No credentials registered."));
25823
+ console.log(pc28.dim("No credentials registered."));
25454
25824
  return;
25455
25825
  }
25456
25826
  for (const m of mcps) {
25457
- const stateColor = !m.validated ? pc27.yellow : m.expired ? pc27.red : pc27.green;
25827
+ const stateColor = !m.validated ? pc28.yellow : m.expired ? pc28.red : pc28.green;
25458
25828
  const stateLabel = !m.validated ? "unvalidated" : m.expired ? "expired" : "active";
25459
25829
  console.log(`
25460
- ${pc27.cyan(m.service)} ${stateColor(`[${stateLabel}]`)}`);
25830
+ ${pc28.cyan(m.service)} ${stateColor(`[${stateLabel}]`)}`);
25461
25831
  console.log(` label: ${m.label}`);
25462
25832
  console.log(` type: ${m.type}`);
25463
25833
  if (m.envName) console.log(` env var: ${m.envName}`);
@@ -25472,15 +25842,15 @@ function registerMcpStatus(cmd) {
25472
25842
  // src/commands/mcp/import.ts
25473
25843
  init_output();
25474
25844
  import * as readline3 from "node:readline";
25475
- import pc28 from "picocolors";
25845
+ import pc29 from "picocolors";
25476
25846
 
25477
25847
  // src/commands/mcp/import-discovery.ts
25478
- import * as fs44 from "node:fs";
25479
- import * as os26 from "node:os";
25480
- import * as path46 from "node:path";
25848
+ import * as fs45 from "node:fs";
25849
+ import * as os27 from "node:os";
25850
+ import * as path47 from "node:path";
25481
25851
  function readJsonFile(filePath) {
25482
25852
  try {
25483
- const raw = fs44.readFileSync(filePath, "utf-8");
25853
+ const raw = fs45.readFileSync(filePath, "utf-8");
25484
25854
  return JSON.parse(raw);
25485
25855
  } catch {
25486
25856
  return null;
@@ -25509,24 +25879,24 @@ function extractMcpServers(obj, source, sourceLabel) {
25509
25879
  }
25510
25880
  function getClaudeDesktopPath() {
25511
25881
  if (process.platform === "darwin") {
25512
- return path46.join(os26.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
25882
+ return path47.join(os27.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
25513
25883
  }
25514
25884
  if (process.platform === "win32") {
25515
- const appData = process.env["APPDATA"] ?? path46.join(os26.homedir(), "AppData", "Roaming");
25516
- return path46.join(appData, "Claude", "claude_desktop_config.json");
25885
+ const appData = process.env["APPDATA"] ?? path47.join(os27.homedir(), "AppData", "Roaming");
25886
+ return path47.join(appData, "Claude", "claude_desktop_config.json");
25517
25887
  }
25518
- return path46.join(os26.homedir(), ".config", "Claude", "claude_desktop_config.json");
25888
+ return path47.join(os27.homedir(), ".config", "Claude", "claude_desktop_config.json");
25519
25889
  }
25520
25890
  function getOlamRepoPaths() {
25521
25891
  const configPaths = [
25522
- path46.join(os26.homedir(), ".olam", "config.yaml"),
25523
- path46.join(process.cwd(), ".olam", "config.yaml")
25892
+ path47.join(os27.homedir(), ".olam", "config.yaml"),
25893
+ path47.join(process.cwd(), ".olam", "config.yaml")
25524
25894
  ];
25525
25895
  const paths = [];
25526
25896
  for (const configPath of configPaths) {
25527
- if (!fs44.existsSync(configPath)) continue;
25897
+ if (!fs45.existsSync(configPath)) continue;
25528
25898
  try {
25529
- const raw = fs44.readFileSync(configPath, "utf-8");
25899
+ const raw = fs45.readFileSync(configPath, "utf-8");
25530
25900
  const repoMatches = [...raw.matchAll(/path:\s*["']?([^\s"'\n]+)/g)];
25531
25901
  for (const m of repoMatches) {
25532
25902
  if (m[1]) paths.push(m[1]);
@@ -25542,7 +25912,7 @@ async function discoverMcpSources(repoPaths) {
25542
25912
  const sources = [];
25543
25913
  const sourceDefs = [
25544
25914
  {
25545
- path: path46.join(os26.homedir(), ".claude.json"),
25915
+ path: path47.join(os27.homedir(), ".claude.json"),
25546
25916
  label: "Claude Code (~/.claude.json)"
25547
25917
  },
25548
25918
  {
@@ -25550,19 +25920,19 @@ async function discoverMcpSources(repoPaths) {
25550
25920
  label: "Claude Desktop"
25551
25921
  },
25552
25922
  {
25553
- path: path46.join(os26.homedir(), ".cursor", "mcp.json"),
25923
+ path: path47.join(os27.homedir(), ".cursor", "mcp.json"),
25554
25924
  label: "Cursor (~/.cursor/mcp.json)"
25555
25925
  },
25556
25926
  {
25557
- path: path46.join(os26.homedir(), ".codeium", "windsurf", "mcp_config.json"),
25927
+ path: path47.join(os27.homedir(), ".codeium", "windsurf", "mcp_config.json"),
25558
25928
  label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
25559
25929
  }
25560
25930
  ];
25561
25931
  const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
25562
25932
  for (const repoPath of resolvedRepoPaths) {
25563
25933
  sourceDefs.push({
25564
- path: path46.join(repoPath, ".mcp.json"),
25565
- label: `.mcp.json (${path46.basename(repoPath)})`
25934
+ path: path47.join(repoPath, ".mcp.json"),
25935
+ label: `.mcp.json (${path47.basename(repoPath)})`
25566
25936
  });
25567
25937
  }
25568
25938
  const reads = await Promise.all(
@@ -25642,13 +26012,13 @@ async function validateMcpEntry(entry) {
25642
26012
  // src/commands/mcp/import.ts
25643
26013
  async function multiSelectPicker(entries) {
25644
26014
  if (entries.length === 0) return [];
25645
- console.log("\n" + pc28.bold("Discovered MCP servers:"));
26015
+ console.log("\n" + pc29.bold("Discovered MCP servers:"));
25646
26016
  entries.forEach((e, i) => {
25647
26017
  console.log(
25648
- ` ${pc28.dim(`[${i + 1}]`)} ${pc28.cyan(e.name.padEnd(20))} ${pc28.dim(e.sourceLabel)}`
26018
+ ` ${pc29.dim(`[${i + 1}]`)} ${pc29.cyan(e.name.padEnd(20))} ${pc29.dim(e.sourceLabel)}`
25649
26019
  );
25650
26020
  });
25651
- console.log("\n" + pc28.dim('Enter numbers to import (e.g. 1,2,3 or "all" or Enter to skip):'));
26021
+ console.log("\n" + pc29.dim('Enter numbers to import (e.g. 1,2,3 or "all" or Enter to skip):'));
25652
26022
  const answer = await new Promise((resolve10) => {
25653
26023
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
25654
26024
  rl.question("> ", (ans) => {
@@ -25675,7 +26045,7 @@ function registerMcpImport(cmd) {
25675
26045
  const repoPaths = opts.repoPaths ? opts.repoPaths.split(",").map((s) => s.trim()) : void 0;
25676
26046
  const { entries, sources, durationMs } = await discoverMcpSources(repoPaths);
25677
26047
  if (entries.length === 0) {
25678
- console.log(pc28.dim("No MCP servers found in any source path."));
26048
+ console.log(pc29.dim("No MCP servers found in any source path."));
25679
26049
  return;
25680
26050
  }
25681
26051
  printInfo("Sources", sources.length > 0 ? sources.join(", ") : "none");
@@ -25688,15 +26058,15 @@ function registerMcpImport(cmd) {
25688
26058
  candidates = filtered;
25689
26059
  }
25690
26060
  if (skippedCount > 0) {
25691
- console.log(pc28.dim(`skipped: ${skippedCount} already registered`));
26061
+ console.log(pc29.dim(`skipped: ${skippedCount} already registered`));
25692
26062
  }
25693
26063
  if (candidates.length === 0) {
25694
- console.log(pc28.dim("Nothing new to import. Use --reimport to force."));
26064
+ console.log(pc29.dim("Nothing new to import. Use --reimport to force."));
25695
26065
  return;
25696
26066
  }
25697
26067
  const selected = await multiSelectPicker(candidates);
25698
26068
  if (selected.length === 0) {
25699
- console.log(pc28.dim("No servers selected."));
26069
+ console.log(pc29.dim("No servers selected."));
25700
26070
  return;
25701
26071
  }
25702
26072
  console.log(`
@@ -25707,16 +26077,16 @@ Importing ${selected.length} server(s)\u2026`);
25707
26077
  let validated = false;
25708
26078
  let validationReason = "skipped";
25709
26079
  if (opts.validate !== false) {
25710
- process.stdout.write(` ${pc28.dim("\u2192")} ${entry.name} validating\u2026 `);
26080
+ process.stdout.write(` ${pc29.dim("\u2192")} ${entry.name} validating\u2026 `);
25711
26081
  const vr = await validateMcpEntry(entry);
25712
26082
  validated = vr.validated;
25713
26083
  validationReason = vr.reason;
25714
26084
  process.stdout.write(
25715
- validated ? pc28.green("ok\n") : pc28.yellow(`unvalidated (${vr.reason})
26085
+ validated ? pc29.green("ok\n") : pc29.yellow(`unvalidated (${vr.reason})
25716
26086
  `)
25717
26087
  );
25718
26088
  } else {
25719
- console.log(` ${pc28.dim("\u2192")} ${entry.name} ${pc28.dim("(validation skipped)")}`);
26089
+ console.log(` ${pc29.dim("\u2192")} ${entry.name} ${pc29.dim("(validation skipped)")}`);
25720
26090
  }
25721
26091
  if (validated) validatedCount++;
25722
26092
  const result = await client.staticAdd({
@@ -25731,21 +26101,21 @@ Importing ${selected.length} server(s)\u2026`);
25731
26101
  }
25732
26102
  }
25733
26103
  console.log("");
25734
- console.log(pc28.green(`\u2713 Imported ${importedCount}/${selected.length}`));
26104
+ console.log(pc29.green(`\u2713 Imported ${importedCount}/${selected.length}`));
25735
26105
  if (validatedCount > 0) {
25736
- console.log(pc28.dim(` ${validatedCount} validated, ${importedCount - validatedCount} unvalidated`));
26106
+ console.log(pc29.dim(` ${validatedCount} validated, ${importedCount - validatedCount} unvalidated`));
25737
26107
  }
25738
26108
  });
25739
26109
  }
25740
26110
 
25741
26111
  // src/commands/mcp/revoke.ts
25742
26112
  init_output();
25743
- import pc29 from "picocolors";
26113
+ import pc30 from "picocolors";
25744
26114
  function registerMcpRevoke(cmd) {
25745
26115
  cmd.command("revoke <user> <world> <service>").description("Revoke a user's MCP service entitlement (multi-tenant mode only)").action(async (user, world, service) => {
25746
26116
  const multiTenant = (process.env["OLAM_MCP_MULTI_TENANT"] ?? "").toLowerCase() === "true";
25747
26117
  if (!multiTenant) {
25748
- console.warn(pc29.yellow("\u26A0 revocation only meaningful in multi_tenant mode \u2014 no-op"));
26118
+ console.warn(pc30.yellow("\u26A0 revocation only meaningful in multi_tenant mode \u2014 no-op"));
25749
26119
  return;
25750
26120
  }
25751
26121
  const baseUrl = process.env["OLAM_MCP_AUTH_SERVICE_URL"] ?? "http://127.0.0.1:9998";
@@ -25774,8 +26144,8 @@ function registerMcpRevoke(cmd) {
25774
26144
  process.exitCode = 1;
25775
26145
  return;
25776
26146
  }
25777
- console.log(pc29.green(`\u2713 Revoked: ${user} / ${world} / ${service}`));
25778
- console.log(pc29.dim(" Next fetch-creds call returns 403; token cleared on next merge."));
26147
+ console.log(pc30.green(`\u2713 Revoked: ${user} / ${world} / ${service}`));
26148
+ console.log(pc30.dim(" Next fetch-creds call returns 403; token cleared on next merge."));
25779
26149
  });
25780
26150
  }
25781
26151
 
@@ -25792,18 +26162,18 @@ function registerMcp(program2) {
25792
26162
  }
25793
26163
 
25794
26164
  // src/pleri-config.ts
25795
- import * as fs45 from "node:fs";
25796
- import * as path47 from "node:path";
26165
+ import * as fs46 from "node:fs";
26166
+ import * as path48 from "node:path";
25797
26167
  function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
25798
26168
  if (process.env.PLERI_BASE_URL) {
25799
26169
  return true;
25800
26170
  }
25801
- const configPath = path47.join(configDir, "config.yaml");
25802
- if (!fs45.existsSync(configPath)) {
26171
+ const configPath = path48.join(configDir, "config.yaml");
26172
+ if (!fs46.existsSync(configPath)) {
25803
26173
  return false;
25804
26174
  }
25805
26175
  try {
25806
- const contents = fs45.readFileSync(configPath, "utf8");
26176
+ const contents = fs46.readFileSync(configPath, "utf8");
25807
26177
  return /^[^#\n]*\bpleri:/m.test(contents);
25808
26178
  } catch {
25809
26179
  return false;
@@ -25823,6 +26193,7 @@ registerList(program);
25823
26193
  registerStatus(program);
25824
26194
  registerDestroy(program);
25825
26195
  registerClean(program);
26196
+ registerImplode(program);
25826
26197
  registerEnter(program);
25827
26198
  registerCrystallize(program, { hidden: !isPleriConfigured() });
25828
26199
  registerPr(program);