@pleri/olam-cli 0.1.40 → 0.1.41

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.
@@ -21213,7 +21213,7 @@ __export(auth_exports, {
21213
21213
  register: () => register2
21214
21214
  });
21215
21215
 
21216
- // ../core/src/auth/secret.ts
21216
+ // ../core/dist/auth/secret.js
21217
21217
  import * as crypto from "node:crypto";
21218
21218
  import * as fs2 from "node:fs";
21219
21219
  import * as os from "node:os";
@@ -21226,11 +21226,13 @@ function getSecretFilePath() {
21226
21226
  }
21227
21227
  function getOrCreateSecret() {
21228
21228
  const fromEnv = process.env[SECRET_ENV_VAR];
21229
- if (fromEnv && fromEnv.length > 0) return fromEnv;
21229
+ if (fromEnv && fromEnv.length > 0)
21230
+ return fromEnv;
21230
21231
  const file = getSecretFilePath();
21231
21232
  if (fs2.existsSync(file)) {
21232
21233
  const value = fs2.readFileSync(file, "utf-8").trim();
21233
- if (value.length > 0) return value;
21234
+ if (value.length > 0)
21235
+ return value;
21234
21236
  }
21235
21237
  const generated = crypto.randomBytes(SECRET_BYTES).toString("base64url");
21236
21238
  fs2.mkdirSync(path2.dirname(file), { recursive: true });
@@ -21243,14 +21245,16 @@ function getOrCreateSecret() {
21243
21245
  }
21244
21246
  function readSecretIfExists() {
21245
21247
  const fromEnv = process.env[SECRET_ENV_VAR];
21246
- if (fromEnv && fromEnv.length > 0) return fromEnv;
21248
+ if (fromEnv && fromEnv.length > 0)
21249
+ return fromEnv;
21247
21250
  const file = getSecretFilePath();
21248
- if (!fs2.existsSync(file)) return null;
21251
+ if (!fs2.existsSync(file))
21252
+ return null;
21249
21253
  const value = fs2.readFileSync(file, "utf-8").trim();
21250
21254
  return value.length > 0 ? value : null;
21251
21255
  }
21252
21256
 
21253
- // ../core/src/auth/client.ts
21257
+ // ../core/dist/auth/client.js
21254
21258
  var DEFAULT_BASE_URL = "http://127.0.0.1:9999";
21255
21259
  var DEFAULT_TIMEOUT_MS = 3e3;
21256
21260
  var RETRY_COUNT = 2;
@@ -21295,7 +21299,8 @@ var AuthClient = class {
21295
21299
  params.set("account", options.account);
21296
21300
  }
21297
21301
  const res = await this.request("GET", `/credentials?${params.toString()}`);
21298
- if (res.status === 404) return null;
21302
+ if (res.status === 404)
21303
+ return null;
21299
21304
  if (!res.ok) {
21300
21305
  throw new Error(`auth service returned ${res.status} fetching credentials`);
21301
21306
  }
@@ -21332,19 +21337,13 @@ var AuthClient = class {
21332
21337
  }
21333
21338
  }
21334
21339
  async disableAccount(accountId) {
21335
- const res = await this.request(
21336
- "POST",
21337
- `/credentials/${encodeURIComponent(accountId)}/disable`
21338
- );
21340
+ const res = await this.request("POST", `/credentials/${encodeURIComponent(accountId)}/disable`);
21339
21341
  if (!res.ok) {
21340
21342
  throw new Error(`failed to disable account ${accountId} (HTTP ${res.status})`);
21341
21343
  }
21342
21344
  }
21343
21345
  async enableAccount(accountId) {
21344
- const res = await this.request(
21345
- "POST",
21346
- `/credentials/${encodeURIComponent(accountId)}/enable`
21347
- );
21346
+ const res = await this.request("POST", `/credentials/${encodeURIComponent(accountId)}/enable`);
21348
21347
  if (!res.ok) {
21349
21348
  throw new Error(`failed to enable account ${accountId} (HTTP ${res.status})`);
21350
21349
  }
@@ -21355,11 +21354,7 @@ var AuthClient = class {
21355
21354
  * `anthropic-ratelimit-reset` (epoch seconds) — the server normalizes.
21356
21355
  */
21357
21356
  async reportRateLimit(accountId, info) {
21358
- const res = await this.request(
21359
- "POST",
21360
- `/credentials/${encodeURIComponent(accountId)}/rate-limited`,
21361
- info
21362
- );
21357
+ const res = await this.request("POST", `/credentials/${encodeURIComponent(accountId)}/rate-limited`, info);
21363
21358
  if (!res.ok) {
21364
21359
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
21365
21360
  }
@@ -21369,8 +21364,10 @@ var AuthClient = class {
21369
21364
  const controller = new AbortController();
21370
21365
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
21371
21366
  const headers = {};
21372
- if (body) headers["Content-Type"] = "application/json";
21373
- if (this.secret) headers["X-Olam-Secret"] = this.secret;
21367
+ if (body)
21368
+ headers["Content-Type"] = "application/json";
21369
+ if (this.secret)
21370
+ headers["X-Olam-Secret"] = this.secret;
21374
21371
  try {
21375
21372
  return await fetch(url, {
21376
21373
  method,
@@ -21390,12 +21387,14 @@ var AuthClient = class {
21390
21387
  }
21391
21388
  };
21392
21389
  function isTransient(err) {
21393
- if (!(err instanceof Error)) return false;
21390
+ if (!(err instanceof Error))
21391
+ return false;
21394
21392
  const message = err.message.toLowerCase();
21395
21393
  return message.includes("econnrefused") || message.includes("econnreset") || message.includes("fetch failed");
21396
21394
  }
21397
21395
  function describeError(err) {
21398
- if (err instanceof Error) return err.message;
21396
+ if (err instanceof Error)
21397
+ return err.message;
21399
21398
  return "unknown error";
21400
21399
  }
21401
21400
  async function safeText(res) {
@@ -21409,7 +21408,7 @@ function sleep(ms) {
21409
21408
  return new Promise((resolve6) => setTimeout(resolve6, ms));
21410
21409
  }
21411
21410
 
21412
- // ../core/src/auth/container.ts
21411
+ // ../core/dist/auth/container.js
21413
21412
  import { execFileSync, spawnSync } from "node:child_process";
21414
21413
  import { existsSync as existsSync3 } from "node:fs";
21415
21414
  import * as path3 from "node:path";
@@ -21433,11 +21432,7 @@ var AuthContainerController = class {
21433
21432
  this.imageTag = options.imageTag ?? DEFAULT_IMAGE;
21434
21433
  }
21435
21434
  status() {
21436
- const inspect = spawnSync(
21437
- "docker",
21438
- ["inspect", "--format", "{{.State.Status}}|{{.Id}}", this.containerName],
21439
- { encoding: "utf-8" }
21440
- );
21435
+ const inspect = spawnSync("docker", ["inspect", "--format", "{{.State.Status}}|{{.Id}}", this.containerName], { encoding: "utf-8" });
21441
21436
  if (inspect.status === 0) {
21442
21437
  const [stateRaw, id] = inspect.stdout.trim().split("|");
21443
21438
  const state = stateRaw === "running" ? "running" : "stopped";
@@ -21460,7 +21455,8 @@ var AuthContainerController = class {
21460
21455
  */
21461
21456
  start() {
21462
21457
  const current = this.status();
21463
- if (current.state === "running") return;
21458
+ if (current.state === "running")
21459
+ return;
21464
21460
  if (current.state === "stopped") {
21465
21461
  execFileSync("docker", ["start", this.containerName], { stdio: "pipe" });
21466
21462
  return;
@@ -21483,15 +21479,9 @@ var AuthContainerController = class {
21483
21479
  buildImage() {
21484
21480
  const dockerfileDir = resolveAuthServicePath();
21485
21481
  if (!existsSync3(path3.join(dockerfileDir, "Dockerfile"))) {
21486
- throw new Error(
21487
- `auth image '${this.imageTag}' is not present locally and no Dockerfile is available at ${dockerfileDir} to build from. Run \`olam bootstrap\` to pull the published image, or check out the olam source tree.`
21488
- );
21482
+ throw new Error(`auth image '${this.imageTag}' is not present locally and no Dockerfile is available at ${dockerfileDir} to build from. Run \`olam bootstrap\` to pull the published image, or check out the olam source tree.`);
21489
21483
  }
21490
- execFileSync(
21491
- "docker",
21492
- ["build", "--tag", this.imageTag, dockerfileDir],
21493
- { stdio: "inherit" }
21494
- );
21484
+ execFileSync("docker", ["build", "--tag", this.imageTag, dockerfileDir], { stdio: "inherit" });
21495
21485
  }
21496
21486
  /**
21497
21487
  * `docker run` the auth container. Injects the shared secret so every
@@ -21499,33 +21489,30 @@ var AuthContainerController = class {
21499
21489
  */
21500
21490
  runContainer() {
21501
21491
  const secret = getOrCreateSecret();
21502
- execFileSync(
21503
- "docker",
21504
- [
21505
- "run",
21506
- "--detach",
21507
- "--name",
21508
- this.containerName,
21509
- "--restart",
21510
- "unless-stopped",
21511
- "--publish",
21512
- `${this.port}:9999`,
21513
- "--volume",
21514
- `${this.volume}:/auth-data`,
21515
- "--env",
21516
- `AUTH_BIND=0.0.0.0`,
21517
- "--env",
21518
- `AUTH_DATA_DIR=/auth-data`,
21519
- "--env",
21520
- `OLAM_AUTH_SECRET=${secret}`,
21521
- this.imageTag
21522
- ],
21523
- { stdio: "pipe" }
21524
- );
21492
+ execFileSync("docker", [
21493
+ "run",
21494
+ "--detach",
21495
+ "--name",
21496
+ this.containerName,
21497
+ "--restart",
21498
+ "unless-stopped",
21499
+ "--publish",
21500
+ `${this.port}:9999`,
21501
+ "--volume",
21502
+ `${this.volume}:/auth-data`,
21503
+ "--env",
21504
+ `AUTH_BIND=0.0.0.0`,
21505
+ "--env",
21506
+ `AUTH_DATA_DIR=/auth-data`,
21507
+ "--env",
21508
+ `OLAM_AUTH_SECRET=${secret}`,
21509
+ this.imageTag
21510
+ ], { stdio: "pipe" });
21525
21511
  }
21526
21512
  stop() {
21527
21513
  const current = this.status();
21528
- if (current.state !== "running") return;
21514
+ if (current.state !== "running")
21515
+ return;
21529
21516
  execFileSync("docker", ["stop", this.containerName], { stdio: "pipe" });
21530
21517
  }
21531
21518
  remove() {
@@ -21537,7 +21524,8 @@ var AuthContainerController = class {
21537
21524
  const deadline = Date.now() + timeoutMs;
21538
21525
  while (Date.now() < deadline) {
21539
21526
  const health = await client.health();
21540
- if (health.ok) return true;
21527
+ if (health.ok)
21528
+ return true;
21541
21529
  await sleep2(500);
21542
21530
  }
21543
21531
  return false;
@@ -21552,7 +21540,7 @@ function sleep2(ms) {
21552
21540
  return new Promise((resolve6) => setTimeout(resolve6, ms));
21553
21541
  }
21554
21542
 
21555
- // ../core/src/auth/preflight.ts
21543
+ // ../core/dist/auth/preflight.js
21556
21544
  async function runAuthPreflight(options = {}) {
21557
21545
  const client = new AuthClient(options);
21558
21546
  const controller = new AuthContainerController();
@@ -21760,7 +21748,7 @@ __export(pr_exports, {
21760
21748
  register: () => register3
21761
21749
  });
21762
21750
 
21763
- // ../core/src/world/registry.ts
21751
+ // ../core/dist/world/registry.js
21764
21752
  import { createRequire } from "node:module";
21765
21753
  import * as net from "node:net";
21766
21754
  import * as os2 from "node:os";
@@ -21795,15 +21783,18 @@ function rowToMetadata(row) {
21795
21783
  let expectedServices;
21796
21784
  let appPortUrls;
21797
21785
  try {
21798
- if (row.readiness_chain) readinessChain = JSON.parse(row.readiness_chain);
21786
+ if (row.readiness_chain)
21787
+ readinessChain = JSON.parse(row.readiness_chain);
21799
21788
  } catch {
21800
21789
  }
21801
21790
  try {
21802
- if (row.expected_services) expectedServices = JSON.parse(row.expected_services);
21791
+ if (row.expected_services)
21792
+ expectedServices = JSON.parse(row.expected_services);
21803
21793
  } catch {
21804
21794
  }
21805
21795
  try {
21806
- if (row.app_port_urls) appPortUrls = JSON.parse(row.app_port_urls);
21796
+ if (row.app_port_urls)
21797
+ appPortUrls = JSON.parse(row.app_port_urls);
21807
21798
  } catch {
21808
21799
  }
21809
21800
  return {
@@ -21884,9 +21875,7 @@ var WorldRegistry = class {
21884
21875
  if (!row) {
21885
21876
  this.db.prepare("INSERT INTO meta (key, value) VALUES (?, ?)").run("schema_version", SCHEMA_VERSION);
21886
21877
  }
21887
- const cols = this.db.prepare("PRAGMA table_info(worlds)").all().map(
21888
- (r) => r.name
21889
- );
21878
+ const cols = this.db.prepare("PRAGMA table_info(worlds)").all().map((r) => r.name);
21890
21879
  if (!cols.includes("pr_url")) {
21891
21880
  this.db.exec("ALTER TABLE worlds ADD COLUMN pr_url TEXT");
21892
21881
  this.db.exec("ALTER TABLE worlds ADD COLUMN pr_number INTEGER");
@@ -21894,43 +21883,16 @@ var WorldRegistry = class {
21894
21883
  this.db.exec("ALTER TABLE worlds ADD COLUMN pr_created_at TEXT");
21895
21884
  this.db.exec("ALTER TABLE worlds ADD COLUMN pr_state TEXT NOT NULL DEFAULT 'none'");
21896
21885
  this.db.exec("ALTER TABLE worlds ADD COLUMN pr_merged_at TEXT");
21897
- this.db.exec(
21898
- "ALTER TABLE worlds ADD COLUMN auto_destroy_on_merge INTEGER NOT NULL DEFAULT 1"
21899
- );
21886
+ this.db.exec("ALTER TABLE worlds ADD COLUMN auto_destroy_on_merge INTEGER NOT NULL DEFAULT 1");
21900
21887
  }
21901
21888
  }
21902
21889
  register(world) {
21903
- this.db.prepare(
21904
- `INSERT INTO worlds
21890
+ this.db.prepare(`INSERT INTO worlds
21905
21891
  (id, name, status, repos, branch, port_offset, workspace_path,
21906
21892
  compute_provider, total_cost_usd, thought_count, created_at, updated_at,
21907
21893
  pr_url, pr_number, pr_repo, pr_created_at, pr_state, pr_merged_at, auto_destroy_on_merge,
21908
21894
  readiness_chain, expected_services, app_port_urls)
21909
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
21910
- ).run(
21911
- world.id,
21912
- world.name,
21913
- world.status,
21914
- JSON.stringify(world.repos),
21915
- world.branch,
21916
- world.portOffset,
21917
- world.workspacePath,
21918
- world.computeProvider,
21919
- world.totalCostUsd,
21920
- world.thoughtCount,
21921
- world.createdAt,
21922
- world.updatedAt,
21923
- world.prUrl ?? null,
21924
- world.prNumber ?? null,
21925
- world.prRepo ?? null,
21926
- world.prCreatedAt ?? null,
21927
- world.prState ?? "none",
21928
- world.prMergedAt ?? null,
21929
- world.autoDestroyOnMerge === false ? 0 : 1,
21930
- world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null,
21931
- world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null,
21932
- world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null
21933
- );
21895
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(world.id, world.name, world.status, JSON.stringify(world.repos), world.branch, world.portOffset, world.workspacePath, world.computeProvider, world.totalCostUsd, world.thoughtCount, world.createdAt, world.updatedAt, world.prUrl ?? null, world.prNumber ?? null, world.prRepo ?? null, world.prCreatedAt ?? null, world.prState ?? "none", world.prMergedAt ?? null, world.autoDestroyOnMerge === false ? 0 : 1, world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null, world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null, world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null);
21934
21896
  }
21935
21897
  update(worldId, updates) {
21936
21898
  const setClauses = [];
@@ -21971,7 +21933,8 @@ var WorldRegistry = class {
21971
21933
  }
21972
21934
  }
21973
21935
  }
21974
- if (setClauses.length === 0) return;
21936
+ if (setClauses.length === 0)
21937
+ return;
21975
21938
  if (!updates.updatedAt) {
21976
21939
  setClauses.push("updated_at = ?");
21977
21940
  values.push((/* @__PURE__ */ new Date()).toISOString());
@@ -21996,9 +21959,7 @@ var WorldRegistry = class {
21996
21959
  return rows.map(rowToMetadata);
21997
21960
  }
21998
21961
  listWithPr() {
21999
- const rows = this.db.prepare(
22000
- "SELECT * FROM worlds WHERE pr_url IS NOT NULL AND pr_state != 'merged_destroyed' ORDER BY created_at DESC"
22001
- ).all();
21962
+ const rows = this.db.prepare("SELECT * FROM worlds WHERE pr_url IS NOT NULL AND pr_state != 'merged_destroyed' ORDER BY created_at DESC").all();
22002
21963
  return rows.map(rowToMetadata);
22003
21964
  }
22004
21965
  remove(worldId) {
@@ -22010,13 +21971,13 @@ var WorldRegistry = class {
22010
21971
  * control plane port (19080+offset) is not already bound on the host.
22011
21972
  */
22012
21973
  getNextPortOffset() {
22013
- const rows = this.db.prepare(
22014
- `SELECT port_offset FROM worlds WHERE status != 'destroyed' ORDER BY port_offset`
22015
- ).all();
21974
+ const rows = this.db.prepare(`SELECT port_offset FROM worlds WHERE status != 'destroyed' ORDER BY port_offset`).all();
22016
21975
  const usedOffsets = new Set(rows.map((r) => r.port_offset));
22017
21976
  for (let candidate = 0; candidate <= 1e4; candidate += 100) {
22018
- if (usedOffsets.has(candidate)) continue;
22019
- if (isPortInUse(19080 + candidate)) continue;
21977
+ if (usedOffsets.has(candidate))
21978
+ continue;
21979
+ if (isPortInUse(19080 + candidate))
21980
+ continue;
22020
21981
  return candidate;
22021
21982
  }
22022
21983
  const max = rows.length > 0 ? rows[rows.length - 1].port_offset : -100;
@@ -22027,7 +21988,7 @@ var WorldRegistry = class {
22027
21988
  }
22028
21989
  };
22029
21990
 
22030
- // ../core/src/pr-gate/client.ts
21991
+ // ../core/dist/pr-gate/client.js
22031
21992
  var HOST_CONTROL_PLANE_BASE = 19080;
22032
21993
  var DEFAULT_TIMEOUT_MS2 = 3e3;
22033
21994
  function worldBaseUrl(portOffset) {
@@ -22044,24 +22005,24 @@ async function request(url, init = {}, timeoutMs = DEFAULT_TIMEOUT_MS2) {
22044
22005
  }
22045
22006
  async function listGates(portOffset) {
22046
22007
  const res = await request(`${worldBaseUrl(portOffset)}/api/pr-gate`);
22047
- if (!res.ok) throw new Error(`list gates failed: HTTP ${res.status}`);
22008
+ if (!res.ok)
22009
+ throw new Error(`list gates failed: HTTP ${res.status}`);
22048
22010
  return await res.json();
22049
22011
  }
22050
22012
  async function getGate(portOffset, id) {
22051
22013
  const res = await request(`${worldBaseUrl(portOffset)}/api/pr-gate/${encodeURIComponent(id)}`);
22052
- if (res.status === 404) return null;
22053
- if (!res.ok) throw new Error(`get gate failed: HTTP ${res.status}`);
22014
+ if (res.status === 404)
22015
+ return null;
22016
+ if (!res.ok)
22017
+ throw new Error(`get gate failed: HTTP ${res.status}`);
22054
22018
  return await res.json();
22055
22019
  }
22056
22020
  async function decideGate(portOffset, id, payload) {
22057
- const res = await request(
22058
- `${worldBaseUrl(portOffset)}/api/pr-gate/${encodeURIComponent(id)}/decision`,
22059
- {
22060
- method: "POST",
22061
- headers: { "Content-Type": "application/json" },
22062
- body: JSON.stringify(payload)
22063
- }
22064
- );
22021
+ const res = await request(`${worldBaseUrl(portOffset)}/api/pr-gate/${encodeURIComponent(id)}/decision`, {
22022
+ method: "POST",
22023
+ headers: { "Content-Type": "application/json" },
22024
+ body: JSON.stringify(payload)
22025
+ });
22065
22026
  if (!res.ok) {
22066
22027
  const text = await res.text().catch(() => "");
22067
22028
  throw new Error(`decide gate failed: HTTP ${res.status} ${text.slice(0, 200)}`);
@@ -22260,7 +22221,7 @@ __export(workspace_exports, {
22260
22221
  });
22261
22222
  import { stringify as stringifyYaml2 } from "yaml";
22262
22223
 
22263
- // ../core/src/workspace/schema.ts
22224
+ // ../core/dist/workspace/schema.js
22264
22225
  var ReadinessServiceSchema = external_exports.object({
22265
22226
  name: external_exports.string().min(1),
22266
22227
  port: external_exports.number().int().positive(),
@@ -22276,10 +22237,7 @@ var RESERVED_REPO_NAMES = /* @__PURE__ */ new Set([
22276
22237
  "tostring",
22277
22238
  "valueof"
22278
22239
  ]);
22279
- var repoNameSchema = external_exports.string().min(1).max(64).regex(
22280
- REPO_NAME_PATTERN,
22281
- 'repo name must be ASCII lowercase + digits + dash (1-64 chars, no leading/trailing dash). E.g. "atlas-core", "diner-app". The `${repos.<name>.<field>}` reference syntax reserves "."; worktree paths reserve "/" and whitespace.'
22282
- ).refine((name) => !RESERVED_REPO_NAMES.has(name), {
22240
+ var repoNameSchema = external_exports.string().min(1).max(64).regex(REPO_NAME_PATTERN, 'repo name must be ASCII lowercase + digits + dash (1-64 chars, no leading/trailing dash). E.g. "atlas-core", "diner-app". The `${repos.<name>.<field>}` reference syntax reserves "."; worktree paths reserve "/" and whitespace.').refine((name) => !RESERVED_REPO_NAMES.has(name), {
22283
22241
  message: 'repo name shadows an Object.prototype member (e.g. "constructor", "toString") \u2014 choose a different name to avoid downstream confusion'
22284
22242
  });
22285
22243
  var WorkspaceRepoSchema = external_exports.object({
@@ -22325,32 +22283,29 @@ var WorkspaceSchema = external_exports.object({
22325
22283
  updatedAt: external_exports.number().int().nonnegative()
22326
22284
  });
22327
22285
 
22328
- // ../core/src/workspace/store.ts
22286
+ // ../core/dist/workspace/store.js
22329
22287
  import * as fs4 from "node:fs";
22330
22288
  import * as os4 from "node:os";
22331
22289
  import * as path6 from "node:path";
22332
22290
  import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
22333
22291
 
22334
- // ../core/src/config/version.ts
22335
- var versionStringSchema = external_exports.string().regex(
22336
- /^[\d][\w.+-]*$/,
22337
- "Version must start with a digit and contain only alphanumeric, dots, dashes, plus signs"
22338
- );
22292
+ // ../core/dist/config/version.js
22293
+ var versionStringSchema = external_exports.string().regex(/^[\d][\w.+-]*$/, "Version must start with a digit and contain only alphanumeric, dots, dashes, plus signs");
22339
22294
  var runtimeVersionSchema = external_exports.object({
22340
22295
  ruby: versionStringSchema.optional(),
22341
22296
  node: versionStringSchema.optional(),
22342
22297
  python: versionStringSchema.optional()
22343
22298
  });
22344
22299
 
22345
- // ../core/src/world/repo-manifest.ts
22300
+ // ../core/dist/world/repo-manifest.js
22346
22301
  import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync3 } from "node:fs";
22347
22302
  import { join as join5 } from "node:path";
22348
22303
  import YAML from "yaml";
22349
22304
 
22350
- // ../core/src/manifest/version.ts
22305
+ // ../core/dist/manifest/version.js
22351
22306
  var MANIFEST_VERSION = 1;
22352
22307
 
22353
- // ../core/src/world/repo-manifest.ts
22308
+ // ../core/dist/world/repo-manifest.js
22354
22309
  var runtimeSchema = external_exports.object({
22355
22310
  ruby: versionStringSchema.optional(),
22356
22311
  node: versionStringSchema.optional(),
@@ -22449,12 +22404,7 @@ function refineForbiddenKeys(value, path21, ctx, rejectSource) {
22449
22404
  });
22450
22405
  continue;
22451
22406
  }
22452
- refineForbiddenKeys(
22453
- value[key],
22454
- [...path21, key],
22455
- ctx,
22456
- false
22457
- );
22407
+ refineForbiddenKeys(value[key], [...path21, key], ctx, false);
22458
22408
  }
22459
22409
  }
22460
22410
  function rejectForbiddenKeys(value, path21, rejectSource) {
@@ -22463,20 +22413,12 @@ function rejectForbiddenKeys(value, path21, rejectSource) {
22463
22413
  }
22464
22414
  for (const key of Object.keys(value)) {
22465
22415
  if (FORBIDDEN_KEYS.has(key)) {
22466
- throw new Error(
22467
- `[manifest] ${path21}: forbidden key "${key}" (prototype-pollution surface)`
22468
- );
22416
+ throw new Error(`[manifest] ${path21}: forbidden key "${key}" (prototype-pollution surface)`);
22469
22417
  }
22470
22418
  if (rejectSource && key === "source") {
22471
- throw new Error(
22472
- `[manifest] ${path21}: top-level "source" is loader-stamped \u2014 manifests must not author it`
22473
- );
22419
+ throw new Error(`[manifest] ${path21}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
22474
22420
  }
22475
- rejectForbiddenKeys(
22476
- value[key],
22477
- `${path21}.${key}`,
22478
- false
22479
- );
22421
+ rejectForbiddenKeys(value[key], `${path21}.${key}`, false);
22480
22422
  }
22481
22423
  }
22482
22424
  function unknownTopLevelKeys(parsed) {
@@ -22498,64 +22440,51 @@ function loadRepoManifest(repoDir) {
22498
22440
  }
22499
22441
  const stat = lstatSync(manifestPath);
22500
22442
  if (stat.isSymbolicLink()) {
22501
- throw new Error(
22502
- `[manifest] ${manifestPath}: symbolic links are not permitted`
22503
- );
22443
+ throw new Error(`[manifest] ${manifestPath}: symbolic links are not permitted`);
22504
22444
  }
22505
22445
  const raw = readFileSync3(manifestPath, "utf-8");
22506
22446
  const parsed = YAML.parse(raw, { maxAliasCount: 100 });
22507
22447
  if (parsed === null || parsed === void 0) {
22508
22448
  if (source === "olam" && existsSync4(adbPath)) {
22509
- console.warn(
22510
- `[manifest] ${manifestPath}: file is empty; .adb.yaml is NOT consulted (delete .olam.yaml to fall back)`
22511
- );
22449
+ console.warn(`[manifest] ${manifestPath}: file is empty; .adb.yaml is NOT consulted (delete .olam.yaml to fall back)`);
22512
22450
  }
22513
22451
  return null;
22514
22452
  }
22515
22453
  if (typeof parsed !== "object" || Array.isArray(parsed)) {
22516
- throw new Error(
22517
- `[manifest] ${manifestPath}: expected a YAML mapping at the top level`
22518
- );
22454
+ throw new Error(`[manifest] ${manifestPath}: expected a YAML mapping at the top level`);
22519
22455
  }
22520
22456
  rejectForbiddenKeys(parsed, manifestPath, true);
22521
22457
  const body = RepoManifestSchema.parse(parsed);
22522
22458
  if (parsed["version"] === void 0) {
22523
- console.warn(
22524
- `[manifest] ${manifestPath}: missing "version: ${MANIFEST_VERSION}" field \u2014 add it to suppress this warning (backward-compat: file still parses)`
22525
- );
22459
+ console.warn(`[manifest] ${manifestPath}: missing "version: ${MANIFEST_VERSION}" field \u2014 add it to suppress this warning (backward-compat: file still parses)`);
22526
22460
  }
22527
22461
  const unknown2 = unknownTopLevelKeys(parsed);
22528
22462
  if (unknown2.length > 0) {
22529
- console.warn(
22530
- `[manifest] ${manifestPath}: unknown top-level fields preserved (passthrough): ${unknown2.join(", ")}`
22531
- );
22463
+ console.warn(`[manifest] ${manifestPath}: unknown top-level fields preserved (passthrough): ${unknown2.join(", ")}`);
22532
22464
  }
22533
22465
  return { ...body, source };
22534
22466
  }
22535
22467
 
22536
- // ../core/src/util/path.ts
22468
+ // ../core/dist/util/path.js
22537
22469
  import * as os3 from "node:os";
22538
22470
  import * as path5 from "node:path";
22539
22471
  function resolveTildePath(p) {
22540
- if (p === "~") return os3.homedir();
22541
- if (p.startsWith("~/")) return path5.join(os3.homedir(), p.slice(2));
22472
+ if (p === "~")
22473
+ return os3.homedir();
22474
+ if (p.startsWith("~/"))
22475
+ return path5.join(os3.homedir(), p.slice(2));
22542
22476
  if (p.startsWith("~")) {
22543
- throw new Error(
22544
- `[path] POSIX "~user" syntax is not supported (got "${p}"). Use "~/..." for the operator's home or an absolute path.`
22545
- );
22477
+ throw new Error(`[path] POSIX "~user" syntax is not supported (got "${p}"). Use "~/..." for the operator's home or an absolute path.`);
22546
22478
  }
22547
- if (p.startsWith("/")) return p;
22548
- throw new Error(
22549
- `[path] expected absolute path or "~/..."; got "${p}"`
22550
- );
22479
+ if (p.startsWith("/"))
22480
+ return p;
22481
+ throw new Error(`[path] expected absolute path or "~/..."; got "${p}"`);
22551
22482
  }
22552
22483
 
22553
- // ../core/src/workspace/store.ts
22484
+ // ../core/dist/workspace/store.js
22554
22485
  var WorkspaceNameError = class extends Error {
22555
22486
  constructor(name) {
22556
- super(
22557
- `invalid workspace name "${name}": must match ${WORKSPACE_NAME_PATTERN} (lowercase alnum + dashes, 1\u201364 chars, no leading/trailing dash)`
22558
- );
22487
+ super(`invalid workspace name "${name}": must match ${WORKSPACE_NAME_PATTERN} (lowercase alnum + dashes, 1\u201364 chars, no leading/trailing dash)`);
22559
22488
  this.name = "WorkspaceNameError";
22560
22489
  }
22561
22490
  };
@@ -22567,7 +22496,8 @@ var WorkspaceExistsError = class extends Error {
22567
22496
  };
22568
22497
  function workspacesDir() {
22569
22498
  const override = process.env["OLAM_WORKSPACES_DIR"];
22570
- if (override && override.length > 0) return override;
22499
+ if (override && override.length > 0)
22500
+ return override;
22571
22501
  return path6.join(os4.homedir(), ".olam", "workspaces");
22572
22502
  }
22573
22503
  function validateName(name) {
@@ -22580,7 +22510,8 @@ function filePathFor(name) {
22580
22510
  }
22581
22511
  function listWorkspaces() {
22582
22512
  const dir = workspacesDir();
22583
- if (!fs4.existsSync(dir)) return [];
22513
+ if (!fs4.existsSync(dir))
22514
+ return [];
22584
22515
  const entries = fs4.readdirSync(dir).filter((f) => f.endsWith(".yaml"));
22585
22516
  const result = [];
22586
22517
  for (const entry of entries) {
@@ -22601,7 +22532,8 @@ function listWorkspaces() {
22601
22532
  function readWorkspace(name) {
22602
22533
  validateName(name);
22603
22534
  const file = filePathFor(name);
22604
- if (!fs4.existsSync(file)) return null;
22535
+ if (!fs4.existsSync(file))
22536
+ return null;
22605
22537
  const raw = fs4.readFileSync(file, "utf-8");
22606
22538
  return WorkspaceSchema.parse(parseYaml(raw));
22607
22539
  }
@@ -22621,7 +22553,8 @@ function writeWorkspace(ws, options = {}) {
22621
22553
  function removeWorkspace(name) {
22622
22554
  validateName(name);
22623
22555
  const file = filePathFor(name);
22624
- if (!fs4.existsSync(file)) return false;
22556
+ if (!fs4.existsSync(file))
22557
+ return false;
22625
22558
  fs4.unlinkSync(file);
22626
22559
  return true;
22627
22560
  }
@@ -22633,9 +22566,7 @@ function workspaceToRepoConfigs(ws) {
22633
22566
  manifest = repoPath ? loadRepoManifest(repoPath) : null;
22634
22567
  } catch (err) {
22635
22568
  const msg = err instanceof Error ? err.message : String(err);
22636
- throw new Error(
22637
- `[workspace "${ws.name}"] repo "${repo.name}" at ${repoPath}: ${msg}`
22638
- );
22569
+ throw new Error(`[workspace "${ws.name}"] repo "${repo.name}" at ${repoPath}: ${msg}`);
22639
22570
  }
22640
22571
  if (manifest?.runtime) {
22641
22572
  logRuntimeReconciliation(repo.name, manifest.runtime);
@@ -22657,15 +22588,16 @@ function workspaceToRepoConfigs(ws) {
22657
22588
  function logRuntimeReconciliation(repoName, runtime) {
22658
22589
  const validated = [];
22659
22590
  for (const [lang, version2] of Object.entries(runtime)) {
22660
- if (typeof version2 !== "string" || version2.length === 0) continue;
22661
- if (!versionStringSchema.safeParse(version2).success) continue;
22591
+ if (typeof version2 !== "string" || version2.length === 0)
22592
+ continue;
22593
+ if (!versionStringSchema.safeParse(version2).success)
22594
+ continue;
22662
22595
  const safeLang = lang.replace(/[\r\n\x00-\x1f]/g, "?");
22663
22596
  validated.push(`${safeLang}=${version2}`);
22664
22597
  }
22665
- if (validated.length === 0) return;
22666
- console.warn(
22667
- `[manifest] repo "${repoName}" supersedes central stack: ${validated.join(", ")}`
22668
- );
22598
+ if (validated.length === 0)
22599
+ return;
22600
+ console.warn(`[manifest] repo "${repoName}" supersedes central stack: ${validated.join(", ")}`);
22669
22601
  }
22670
22602
 
22671
22603
  // ../mcp-server/src/tools/workspace.ts
@@ -24764,18 +24696,18 @@ __export(world_dispatch_exports, {
24764
24696
  });
24765
24697
  import "node:path";
24766
24698
 
24767
- // ../core/src/world-paths.ts
24699
+ // ../core/dist/world-paths.js
24768
24700
  import * as path8 from "node:path";
24769
24701
  var WORLD_DB_FILENAME = "world.db";
24770
24702
  function getWorldDbPath(workspacePath) {
24771
24703
  return path8.join(workspacePath, WORLD_DB_FILENAME);
24772
24704
  }
24773
24705
 
24774
- // ../core/src/orchestrator/dispatch.ts
24706
+ // ../core/dist/orchestrator/dispatch.js
24775
24707
  var DEEP_MODE_SUFFIX = "\n\nUltrathink and use sub-agents (the Agent tool) to parallelize independent work. Break complex tasks into focused sub-tasks.";
24776
24708
  var COMPLEX_PROMPT_RE = /\b(implement|build|create|design|refactor|architect|analyze|research|write.*documentation)\b/i;
24777
24709
 
24778
- // ../core/src/thought/local-store.ts
24710
+ // ../core/dist/thought/local-store.js
24779
24711
  import { createRequire as createRequire2 } from "node:module";
24780
24712
  var _require2 = createRequire2(import.meta.url);
24781
24713
  var _Database2 = null;
@@ -25007,13 +24939,11 @@ var ThoughtLocalStore = class {
25007
24939
  }
25008
24940
  /** Returns distinct session IDs ordered by earliest appearance. Uses idx_nodes_session. */
25009
24941
  getDistinctSessionIds() {
25010
- const rows = this.db.prepare(
25011
- `SELECT session_id, MIN(created_at) AS first_at
24942
+ const rows = this.db.prepare(`SELECT session_id, MIN(created_at) AS first_at
25012
24943
  FROM thought_nodes
25013
24944
  WHERE session_id IS NOT NULL AND session_id != ''
25014
24945
  GROUP BY session_id
25015
- ORDER BY first_at DESC`
25016
- ).all();
24946
+ ORDER BY first_at DESC`).all();
25017
24947
  return rows.map((r) => r.session_id);
25018
24948
  }
25019
24949
  /** Returns all nodes for a given session, ordered by sequence number. */
@@ -25023,8 +24953,7 @@ var ThoughtLocalStore = class {
25023
24953
  }
25024
24954
  /** Returns per-session aggregates in a single query. */
25025
24955
  getSessionAggregates() {
25026
- const rows = this.db.prepare(
25027
- `SELECT session_id,
24956
+ const rows = this.db.prepare(`SELECT session_id,
25028
24957
  COUNT(*) AS node_count,
25029
24958
  MIN(created_at) AS first_at,
25030
24959
  MAX(created_at) AS last_at,
@@ -25032,8 +24961,7 @@ var ThoughtLocalStore = class {
25032
24961
  FROM thought_nodes
25033
24962
  WHERE session_id IS NOT NULL AND session_id != ''
25034
24963
  GROUP BY session_id
25035
- ORDER BY first_at DESC`
25036
- ).all();
24964
+ ORDER BY first_at DESC`).all();
25037
24965
  return rows.map((r) => ({
25038
24966
  sessionId: r.session_id,
25039
24967
  nodeCount: r.node_count,
@@ -25054,14 +24982,14 @@ var ThoughtLocalStore = class {
25054
24982
  }
25055
24983
  };
25056
24984
 
25057
- // ../core/src/world/env-setup.ts
24985
+ // ../core/dist/world/env-setup.js
25058
24986
  import * as crypto2 from "node:crypto";
25059
24987
  import * as fs6 from "node:fs";
25060
24988
  import * as os6 from "node:os";
25061
24989
  import * as path9 from "node:path";
25062
24990
  import { globSync } from "node:fs";
25063
24991
 
25064
- // ../core/src/thought/hooks-config.ts
24992
+ // ../core/dist/thought/hooks-config.js
25065
24993
  var DEFAULT_HOOK_SERVER_URL = "http://localhost:8080";
25066
24994
  function generateHooksConfig(hookServerUrl = DEFAULT_HOOK_SERVER_URL) {
25067
24995
  const makeHookEntry = (hookPath) => [{
@@ -25133,11 +25061,12 @@ function generateHooksConfig(hookServerUrl = DEFAULT_HOOK_SERVER_URL) {
25133
25061
  };
25134
25062
  }
25135
25063
 
25136
- // ../core/src/world/env-setup.ts
25064
+ // ../core/dist/world/env-setup.js
25137
25065
  function copyClaudeConfig(workspacePath, homeDir) {
25138
25066
  const sourceClaudeDir = path9.join(homeDir ?? os6.homedir(), ".claude");
25139
25067
  const destClaudeDir = path9.join(workspacePath, ".claude-host-config");
25140
- if (!fs6.existsSync(sourceClaudeDir)) return;
25068
+ if (!fs6.existsSync(sourceClaudeDir))
25069
+ return;
25141
25070
  fs6.mkdirSync(destClaudeDir, { recursive: true });
25142
25071
  const settingsPath = path9.join(sourceClaudeDir, "settings.json");
25143
25072
  let settings = {};
@@ -25150,10 +25079,7 @@ function copyClaudeConfig(workspacePath, homeDir) {
25150
25079
  }
25151
25080
  const hooksConfig = generateHooksConfig(DEFAULT_HOOK_SERVER_URL);
25152
25081
  settings["hooks"] = hooksConfig["hooks"];
25153
- fs6.writeFileSync(
25154
- path9.join(destClaudeDir, "settings.json"),
25155
- JSON.stringify(settings, null, 2)
25156
- );
25082
+ fs6.writeFileSync(path9.join(destClaudeDir, "settings.json"), JSON.stringify(settings, null, 2));
25157
25083
  const claudeMdPath = path9.join(sourceClaudeDir, "CLAUDE.md");
25158
25084
  if (fs6.existsSync(claudeMdPath)) {
25159
25085
  fs6.copyFileSync(claudeMdPath, path9.join(destClaudeDir, "CLAUDE.md"));
@@ -25199,14 +25125,19 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([
25199
25125
  "backups"
25200
25126
  ]);
25201
25127
  function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new Set()) {
25202
- if (depth > 10) return;
25128
+ if (depth > 10)
25129
+ return;
25203
25130
  fs6.mkdirSync(dest, { recursive: true });
25204
25131
  for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
25205
25132
  const { name } = entry;
25206
- if (skipFiles.has(name)) continue;
25207
- if (SKIP_FILES.has(name)) continue;
25208
- if (DENY_PATTERNS.some((p) => p.test(name))) continue;
25209
- if (entry.isDirectory() && SKIP_DIRS.has(name)) continue;
25133
+ if (skipFiles.has(name))
25134
+ continue;
25135
+ if (SKIP_FILES.has(name))
25136
+ continue;
25137
+ if (DENY_PATTERNS.some((p) => p.test(name)))
25138
+ continue;
25139
+ if (entry.isDirectory() && SKIP_DIRS.has(name))
25140
+ continue;
25210
25141
  const srcPath = path9.join(src, name);
25211
25142
  const destPath = path9.join(dest, name);
25212
25143
  if (entry.isSymbolicLink()) {
@@ -25217,7 +25148,8 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
25217
25148
  continue;
25218
25149
  }
25219
25150
  if (stat.isDirectory()) {
25220
- if (SKIP_DIRS.has(name)) continue;
25151
+ if (SKIP_DIRS.has(name))
25152
+ continue;
25221
25153
  copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
25222
25154
  } else if (stat.isFile()) {
25223
25155
  fs6.copyFileSync(srcPath, destPath);
@@ -25243,9 +25175,7 @@ async function copyClaudeConfigIntoContainer(containerName) {
25243
25175
  dockerExec("test -d /home/olam/workspace/.claude-host-config/skills && cp -r /home/olam/workspace/.claude-host-config/skills/* /home/olam/.claude/skills/ 2>/dev/null || true");
25244
25176
  dockerExec("mkdir -p /home/olam/.claude/scripts");
25245
25177
  dockerExec("test -d /home/olam/workspace/.claude-host-config/scripts && cp -r /home/olam/workspace/.claude-host-config/scripts/* /home/olam/.claude/scripts/ 2>/dev/null || true");
25246
- dockerExec(
25247
- 'OWNER="$(stat -c %U:%G /home/olam/.claude 2>/dev/null || echo olam:olam)"; chown -R "$OWNER" /home/olam/.claude 2>/dev/null || true'
25248
- );
25178
+ dockerExec('OWNER="$(stat -c %U:%G /home/olam/.claude 2>/dev/null || echo olam:olam)"; chown -R "$OWNER" /home/olam/.claude 2>/dev/null || true');
25249
25179
  await sanitizeContainerClaudeHooks(containerName);
25250
25180
  }
25251
25181
  async function sanitizeContainerClaudeHooks(containerName) {
@@ -25293,10 +25223,7 @@ if (changed) {
25293
25223
  }
25294
25224
  `;
25295
25225
  try {
25296
- execSync6(
25297
- `docker exec ${containerName} /usr/local/bin/node -e ${shQuote(script)}`,
25298
- { stdio: "pipe" }
25299
- );
25226
+ execSync6(`docker exec ${containerName} /usr/local/bin/node -e ${shQuote(script)}`, { stdio: "pipe" });
25300
25227
  } catch {
25301
25228
  }
25302
25229
  }
@@ -25350,25 +25277,17 @@ function sanitizeEnvKeyValue(repoName, source, raw) {
25350
25277
  clean[k] = v;
25351
25278
  }
25352
25279
  if (rejectedKeys.length > 0) {
25353
- console.warn(
25354
- `[env] repo "${repoName}" (${source}): dropped ${rejectedKeys.length} entr${rejectedKeys.length === 1 ? "y" : "ies"} with invalid key shape (must match /^[A-Z_][A-Z0-9_]*$/): ${rejectedKeys.join(", ")}`
25355
- );
25280
+ console.warn(`[env] repo "${repoName}" (${source}): dropped ${rejectedKeys.length} entr${rejectedKeys.length === 1 ? "y" : "ies"} with invalid key shape (must match /^[A-Z_][A-Z0-9_]*$/): ${rejectedKeys.join(", ")}`);
25356
25281
  }
25357
25282
  if (rejectedValues.length > 0) {
25358
- console.warn(
25359
- `[env] repo "${repoName}" (${source}): dropped ${rejectedValues.length} entr${rejectedValues.length === 1 ? "y" : "ies"} with control chars in value: ${rejectedValues.join(", ")}`
25360
- );
25283
+ console.warn(`[env] repo "${repoName}" (${source}): dropped ${rejectedValues.length} entr${rejectedValues.length === 1 ? "y" : "ies"} with control chars in value: ${rejectedValues.join(", ")}`);
25361
25284
  }
25362
25285
  return { clean, rejectedKeys, rejectedValues };
25363
25286
  }
25364
25287
  function buildRepoEnvBundle(repoName, serviceEnv, crossRepoEnv, envOverrides) {
25365
25288
  const injectables = {};
25366
25289
  if (crossRepoEnv) {
25367
- const { clean: sanitizedManifest } = sanitizeEnvKeyValue(
25368
- repoName,
25369
- "manifest",
25370
- crossRepoEnv
25371
- );
25290
+ const { clean: sanitizedManifest } = sanitizeEnvKeyValue(repoName, "manifest", crossRepoEnv);
25372
25291
  const droppedProtected = [];
25373
25292
  for (const [k, v] of Object.entries(sanitizedManifest)) {
25374
25293
  if (PROTECTED_ENV_KEY_SET.has(k)) {
@@ -25378,18 +25297,10 @@ function buildRepoEnvBundle(repoName, serviceEnv, crossRepoEnv, envOverrides) {
25378
25297
  injectables[k] = v;
25379
25298
  }
25380
25299
  if (droppedProtected.length > 0) {
25381
- console.warn(
25382
- `[env] repo "${repoName}": manifest tried to set protected key(s) ${droppedProtected.join(
25383
- ", "
25384
- )}; service-discovery value(s) preserved`
25385
- );
25300
+ console.warn(`[env] repo "${repoName}": manifest tried to set protected key(s) ${droppedProtected.join(", ")}; service-discovery value(s) preserved`);
25386
25301
  }
25387
25302
  }
25388
- const { clean: sanitizedOverrides } = sanitizeEnvKeyValue(
25389
- repoName,
25390
- "overrides",
25391
- envOverrides
25392
- );
25303
+ const { clean: sanitizedOverrides } = sanitizeEnvKeyValue(repoName, "overrides", envOverrides);
25393
25304
  const overrideProtected = [];
25394
25305
  for (const [k, v] of Object.entries(sanitizedOverrides)) {
25395
25306
  if (PROTECTED_ENV_KEY_SET.has(k)) {
@@ -25398,11 +25309,7 @@ function buildRepoEnvBundle(repoName, serviceEnv, crossRepoEnv, envOverrides) {
25398
25309
  injectables[k] = v;
25399
25310
  }
25400
25311
  if (overrideProtected.length > 0) {
25401
- console.warn(
25402
- `[env] repo "${repoName}": env_overrides set protected key(s) ${overrideProtected.join(
25403
- ", "
25404
- )} \u2014 operator override wins, but verify this is intentional (service discovery may break)`
25405
- );
25312
+ console.warn(`[env] repo "${repoName}": env_overrides set protected key(s) ${overrideProtected.join(", ")} \u2014 operator override wins, but verify this is intentional (service discovery may break)`);
25406
25313
  }
25407
25314
  const merged = { ...serviceEnv, ...injectables };
25408
25315
  return { merged, injectables };
@@ -25415,16 +25322,13 @@ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}) {
25415
25322
  for (const repo of repos) {
25416
25323
  const worktreePath = path9.join(workspacePath, repo.name);
25417
25324
  const sourcePath = repo.path;
25418
- if (!sourcePath || !fs6.existsSync(worktreePath)) continue;
25325
+ if (!sourcePath || !fs6.existsSync(worktreePath))
25326
+ continue;
25419
25327
  const envSetup = repo.env_setup;
25420
- if (!envSetup) continue;
25328
+ if (!envSetup)
25329
+ continue;
25421
25330
  const repoCrossEnv = crossRepoEnv[repo.name];
25422
- const { merged, injectables } = buildRepoEnvBundle(
25423
- repo.name,
25424
- serviceEnv,
25425
- repoCrossEnv,
25426
- envSetup.env_overrides
25427
- );
25331
+ const { merged, injectables } = buildRepoEnvBundle(repo.name, serviceEnv, repoCrossEnv, envSetup.env_overrides);
25428
25332
  for (const pattern of envSetup.credential_patterns) {
25429
25333
  copyMatchingFiles(sourcePath, worktreePath, pattern);
25430
25334
  }
@@ -25462,10 +25366,12 @@ function generateEnvFromExample(repoPath, overrides) {
25462
25366
  const exampleFiles = [".env.example", ".env.sample", ".env.local.example"];
25463
25367
  for (const exampleName of exampleFiles) {
25464
25368
  const examplePath = path9.join(repoPath, exampleName);
25465
- if (!fs6.existsSync(examplePath)) continue;
25369
+ if (!fs6.existsSync(examplePath))
25370
+ continue;
25466
25371
  const targetName = exampleName.replace(".example", "").replace(".sample", "");
25467
25372
  const targetPath = path9.join(repoPath, targetName);
25468
- if (fs6.existsSync(targetPath)) continue;
25373
+ if (fs6.existsSync(targetPath))
25374
+ continue;
25469
25375
  const template = fs6.readFileSync(examplePath, "utf-8");
25470
25376
  const generated = template.split("\n").map((line) => {
25471
25377
  const match = /^([A-Z_][A-Z0-9_]*)=(.*)$/.exec(line);
@@ -25484,9 +25390,7 @@ function applyEnvOverrides(repoPath, overrides) {
25484
25390
  const envPath = path9.join(repoPath, ".env");
25485
25391
  if (fs6.existsSync(envPath)) {
25486
25392
  const existing = fs6.readFileSync(envPath, "utf-8");
25487
- const existingKeys = new Set(
25488
- existing.split("\n").map((l) => l.split("=")[0]?.trim()).filter(Boolean)
25489
- );
25393
+ const existingKeys = new Set(existing.split("\n").map((l) => l.split("=")[0]?.trim()).filter(Boolean));
25490
25394
  const additions = [];
25491
25395
  for (const [key, value] of Object.entries(overrides)) {
25492
25396
  if (!existingKeys.has(key)) {
@@ -25658,7 +25562,7 @@ __export(world_enter_exports, {
25658
25562
  register: () => register11
25659
25563
  });
25660
25564
 
25661
- // ../core/src/orchestrator/enter.ts
25565
+ // ../core/dist/orchestrator/enter.js
25662
25566
  function getEnterCommand(worldId, containerId, provider, sshHost) {
25663
25567
  if (provider === "docker") {
25664
25568
  const command = `docker exec -it ${containerId} claude`;
@@ -25753,7 +25657,7 @@ __export(world_crystallize_exports, {
25753
25657
  import "node:path";
25754
25658
  import * as fs7 from "node:fs";
25755
25659
 
25756
- // ../core/src/crystallize/checksum.ts
25660
+ // ../core/dist/crystallize/checksum.js
25757
25661
  import { createHash as createHash2 } from "node:crypto";
25758
25662
  function computeGraphChecksum(nodes, edges) {
25759
25663
  const sortedNodes = [...nodes].sort((a, b) => a.id.localeCompare(b.id));
@@ -27711,7 +27615,7 @@ __export(create_from_prompt_exports, {
27711
27615
  register: () => register21
27712
27616
  });
27713
27617
 
27714
- // ../core/src/world/infer-repos.ts
27618
+ // ../core/dist/world/infer-repos.js
27715
27619
  var PICKER_CONFIDENCE_THRESHOLD = 0.7;
27716
27620
  var TOKEN_REGEX = /\b[a-z][a-z0-9]*(?:[-_][a-z0-9]+)+\b/g;
27717
27621
  function extractCandidates(prompt) {
@@ -27760,7 +27664,7 @@ function inferRepos(input) {
27760
27664
  };
27761
27665
  }
27762
27666
 
27763
- // ../core/src/world/match-workspace.ts
27667
+ // ../core/dist/world/match-workspace.js
27764
27668
  var SUBSET_MATCH_RATIO = 0.5;
27765
27669
  function decideWorkspaceMatch(input) {
27766
27670
  if (input.exactMatches.length === 1 && input.exactMatches[0]) {
@@ -27790,16 +27694,14 @@ function decideWorkspaceMatch(input) {
27790
27694
  for (const ws of input.fullCatalog) {
27791
27695
  const wsProjectsLower = ws.projects.map((p) => p.toLowerCase());
27792
27696
  const wsProjectSet = new Set(wsProjectsLower);
27793
- const matched = input.inferredRepos.filter(
27794
- (r) => wsProjectSet.has(r.toLowerCase())
27795
- );
27796
- if (matched.length === 0) continue;
27697
+ const matched = input.inferredRepos.filter((r) => wsProjectSet.has(r.toLowerCase()));
27698
+ if (matched.length === 0)
27699
+ continue;
27797
27700
  const ratio = matched.length / Math.max(1, wsProjectsLower.length);
27798
- if (ratio < SUBSET_MATCH_RATIO) continue;
27701
+ if (ratio < SUBSET_MATCH_RATIO)
27702
+ continue;
27799
27703
  const confidence = 0.5 + 0.4 * ratio;
27800
- const extraRepos = input.inferredRepos.filter(
27801
- (r) => !wsProjectSet.has(r.toLowerCase())
27802
- );
27704
+ const extraRepos = input.inferredRepos.filter((r) => !wsProjectSet.has(r.toLowerCase()));
27803
27705
  subsetCandidates.push({
27804
27706
  workspace: ws,
27805
27707
  confidence,
@@ -27808,7 +27710,8 @@ function decideWorkspaceMatch(input) {
27808
27710
  });
27809
27711
  }
27810
27712
  subsetCandidates.sort((a, b) => {
27811
- if (b.confidence !== a.confidence) return b.confidence - a.confidence;
27713
+ if (b.confidence !== a.confidence)
27714
+ return b.confidence - a.confidence;
27812
27715
  return a.workspace.name.localeCompare(b.workspace.name);
27813
27716
  });
27814
27717
  if (subsetCandidates.length === 1) {
@@ -27837,7 +27740,7 @@ function decideWorkspaceMatch(input) {
27837
27740
  };
27838
27741
  }
27839
27742
 
27840
- // ../core/src/util/open-url.ts
27743
+ // ../core/dist/util/open-url.js
27841
27744
  import { spawnSync as spawnSync2 } from "node:child_process";
27842
27745
  function openUrl(url) {
27843
27746
  if (process.env.CI === "true") {
@@ -28166,12 +28069,12 @@ function createServer3(ctx, initError) {
28166
28069
  return server;
28167
28070
  }
28168
28071
 
28169
- // ../core/src/config/loader.ts
28072
+ // ../core/dist/config/loader.js
28170
28073
  import * as fs9 from "node:fs";
28171
28074
  import * as path12 from "node:path";
28172
28075
  import { parse as parseYaml2 } from "yaml";
28173
28076
 
28174
- // ../core/src/config/schema.ts
28077
+ // ../core/dist/config/schema.js
28175
28078
  var repoTypeSchema = external_exports.enum(["rails", "node", "python", "generic"]);
28176
28079
  var envSetupSchema = external_exports.object({
28177
28080
  credential_patterns: external_exports.array(external_exports.string()).optional().default([]),
@@ -28216,10 +28119,7 @@ var ServiceConfigSchema = external_exports.object({
28216
28119
  // optional <variant>. Rejects empty string explicitly — dockerode silently
28217
28120
  // falls back to host arch when Platform is empty, which would silently
28218
28121
  // recreate the very wrong-arch bug T11 exists to prevent.
28219
- platform: external_exports.string().regex(
28220
- /^[a-z0-9]+\/[a-z0-9_]+(?:\/v[0-9]+)?$/,
28221
- "platform must match OCI shape, e.g. linux/amd64, linux/arm64, linux/arm64/v8"
28222
- ).optional()
28122
+ platform: external_exports.string().regex(/^[a-z0-9]+\/[a-z0-9_]+(?:\/v[0-9]+)?$/, "platform must match OCI shape, e.g. linux/amd64, linux/arm64, linux/arm64/v8").optional()
28223
28123
  });
28224
28124
  var sshHostSchema = external_exports.object({
28225
28125
  host: external_exports.string().min(1),
@@ -28239,8 +28139,10 @@ function isSecureOrLocalhost(value) {
28239
28139
  } catch {
28240
28140
  return false;
28241
28141
  }
28242
- if (parsed.protocol === "https:") return true;
28243
- if (parsed.protocol !== "http:") return false;
28142
+ if (parsed.protocol === "https:")
28143
+ return true;
28144
+ if (parsed.protocol !== "http:")
28145
+ return false;
28244
28146
  return parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]" || parsed.hostname === "::1";
28245
28147
  }
28246
28148
  var computeProvidersSchema = external_exports.object({
@@ -28297,9 +28199,7 @@ var PleriConfigSchema = external_exports.object({
28297
28199
  var authModeSchema = external_exports.enum(["api_key", "oauth"]);
28298
28200
  var AuthConfigSchema = external_exports.object({
28299
28201
  mode: authModeSchema.default("oauth"),
28300
- autoInject: external_exports.boolean().default(true).describe(
28301
- "Copy host credentials into world at creation. Set false to use browser OAuth instead."
28302
- )
28202
+ autoInject: external_exports.boolean().default(true).describe("Copy host credentials into world at creation. Set false to use browser OAuth instead.")
28303
28203
  });
28304
28204
  var DevboxRegistrySchema = external_exports.object({
28305
28205
  /**
@@ -28331,14 +28231,9 @@ var DevboxImageSelectorSchema = external_exports.object({
28331
28231
  * from corrupting the amd64 container's mise installs.
28332
28232
  */
28333
28233
  cache_arch: external_exports.enum(["x64", "arm64"]).optional()
28334
- }).refine(
28335
- (s) => Boolean(
28336
- s.requires_all && s.requires_all.length > 0 || s.requires_any && s.requires_any.length > 0 || s.requires_type
28337
- ),
28338
- {
28339
- message: "selector must declare at least one of requires_all, requires_any, or requires_type"
28340
- }
28341
- );
28234
+ }).refine((s) => Boolean(s.requires_all && s.requires_all.length > 0 || s.requires_any && s.requires_any.length > 0 || s.requires_type), {
28235
+ message: "selector must declare at least one of requires_all, requires_any, or requires_type"
28236
+ });
28342
28237
  var DevboxConfigSchema = external_exports.object({
28343
28238
  registry: DevboxRegistrySchema.optional(),
28344
28239
  /**
@@ -28370,12 +28265,12 @@ var OlamConfigSchema = external_exports.object({
28370
28265
  devbox: DevboxConfigSchema.optional()
28371
28266
  });
28372
28267
 
28373
- // ../core/src/config/defaults.ts
28268
+ // ../core/dist/config/defaults.js
28374
28269
  var CONFIG_DIR_NAME = ".olam";
28375
28270
  var CONFIG_FILENAME = "config.yaml";
28376
28271
  var LEGACY_CONFIG_FILENAME = "olam.yaml";
28377
28272
 
28378
- // ../core/src/config/errors.ts
28273
+ // ../core/dist/config/errors.js
28379
28274
  var OlamConfigNotFoundError = class extends Error {
28380
28275
  code = "CONFIG_NOT_FOUND";
28381
28276
  searchedPaths;
@@ -28435,7 +28330,7 @@ var OlamConfigEnvError = class extends Error {
28435
28330
  }
28436
28331
  };
28437
28332
 
28438
- // ../core/src/config/substitute.ts
28333
+ // ../core/dist/config/substitute.js
28439
28334
  var ENV_VAR_PATTERN = /\$\{([^}]+)\}/g;
28440
28335
  function isCrossReference(expr) {
28441
28336
  return expr.includes(".");
@@ -28458,10 +28353,7 @@ function resolveExpression(expr) {
28458
28353
  return value;
28459
28354
  }
28460
28355
  function substituteString(input) {
28461
- return input.replace(
28462
- ENV_VAR_PATTERN,
28463
- (_, expr) => resolveExpression(expr)
28464
- );
28356
+ return input.replace(ENV_VAR_PATTERN, (_, expr) => resolveExpression(expr));
28465
28357
  }
28466
28358
  function substituteEnvVars(obj) {
28467
28359
  if (typeof obj === "string") {
@@ -28480,16 +28372,19 @@ function substituteEnvVars(obj) {
28480
28372
  return obj;
28481
28373
  }
28482
28374
 
28483
- // ../core/src/config/dotenv.ts
28375
+ // ../core/dist/config/dotenv.js
28484
28376
  import * as fs8 from "node:fs";
28485
28377
  function loadDotEnv(envPath) {
28486
- if (!fs8.existsSync(envPath)) return;
28378
+ if (!fs8.existsSync(envPath))
28379
+ return;
28487
28380
  const content = fs8.readFileSync(envPath, "utf-8");
28488
28381
  for (const line of content.split("\n")) {
28489
28382
  const trimmed = line.trim();
28490
- if (!trimmed || trimmed.startsWith("#")) continue;
28383
+ if (!trimmed || trimmed.startsWith("#"))
28384
+ continue;
28491
28385
  const eqIndex = trimmed.indexOf("=");
28492
- if (eqIndex === -1) continue;
28386
+ if (eqIndex === -1)
28387
+ continue;
28493
28388
  const key = trimmed.slice(0, eqIndex).trim();
28494
28389
  const value = trimmed.slice(eqIndex + 1).trim().replace(/^["']|["']$/g, "");
28495
28390
  if (process.env[key] === void 0) {
@@ -28498,7 +28393,7 @@ function loadDotEnv(envPath) {
28498
28393
  }
28499
28394
  }
28500
28395
 
28501
- // ../core/src/config/loader.ts
28396
+ // ../core/dist/config/loader.js
28502
28397
  function findConfigFile(startDir) {
28503
28398
  const searched = [];
28504
28399
  let current = path12.resolve(startDir);
@@ -28513,7 +28408,8 @@ function findConfigFile(startDir) {
28513
28408
  return { path: legacyLayout, isLegacy: true };
28514
28409
  }
28515
28410
  const parent = path12.dirname(current);
28516
- if (parent === current) break;
28411
+ if (parent === current)
28412
+ break;
28517
28413
  current = parent;
28518
28414
  }
28519
28415
  throw new OlamConfigNotFoundError(searched);
@@ -28522,11 +28418,9 @@ function loadConfig(startDir) {
28522
28418
  const dir = startDir ?? process.cwd();
28523
28419
  const found = findConfigFile(dir);
28524
28420
  if (found.isLegacy) {
28525
- process.stderr.write(
28526
- `[olam] DEPRECATED: found legacy config at ${found.path}
28421
+ process.stderr.write(`[olam] DEPRECATED: found legacy config at ${found.path}
28527
28422
  Run /olam:init to migrate to .olam/config.yaml
28528
- `
28529
- );
28423
+ `);
28530
28424
  } else {
28531
28425
  const envPath = path12.join(path12.dirname(found.path), ".env");
28532
28426
  loadDotEnv(envPath);
@@ -28535,9 +28429,7 @@ function loadConfig(startDir) {
28535
28429
  try {
28536
28430
  rawContent = fs9.readFileSync(found.path, "utf-8");
28537
28431
  } catch (err) {
28538
- throw new Error(
28539
- `Failed to read ${found.path}: ${err instanceof Error ? err.message : String(err)}`
28540
- );
28432
+ throw new Error(`Failed to read ${found.path}: ${err instanceof Error ? err.message : String(err)}`);
28541
28433
  }
28542
28434
  let parsed;
28543
28435
  try {
@@ -28547,9 +28439,7 @@ function loadConfig(startDir) {
28547
28439
  throw new Error(`Invalid YAML in ${found.path}: ${message}`);
28548
28440
  }
28549
28441
  if (parsed === null || parsed === void 0 || typeof parsed !== "object") {
28550
- throw new Error(
28551
- `Invalid YAML in ${found.path}: expected an object at the document root`
28552
- );
28442
+ throw new Error(`Invalid YAML in ${found.path}: expected an object at the document root`);
28553
28443
  }
28554
28444
  const substituted = substituteEnvVars(parsed);
28555
28445
  try {
@@ -28566,14 +28456,14 @@ function loadConfig(startDir) {
28566
28456
  }
28567
28457
  }
28568
28458
 
28569
- // ../core/src/world/manager.ts
28570
- import "node:crypto";
28459
+ // ../core/dist/world/manager.js
28460
+ import * as crypto4 from "node:crypto";
28571
28461
  import { execSync as execSync4 } from "node:child_process";
28572
28462
  import * as fs14 from "node:fs";
28573
28463
  import * as os8 from "node:os";
28574
28464
  import * as path18 from "node:path";
28575
28465
 
28576
- // ../core/src/world/state.ts
28466
+ // ../core/dist/world/state.js
28577
28467
  var VALID_TRANSITIONS = {
28578
28468
  creating: ["running", "error"],
28579
28469
  running: ["paused", "crystallizing", "destroyed", "error"],
@@ -28583,12 +28473,12 @@ var VALID_TRANSITIONS = {
28583
28473
  error: ["destroyed"]
28584
28474
  };
28585
28475
  var WorldStateMachine = class {
28476
+ worldId;
28477
+ _state;
28586
28478
  constructor(worldId, initialState) {
28587
28479
  this.worldId = worldId;
28588
28480
  this._state = initialState;
28589
28481
  }
28590
- worldId;
28591
- _state;
28592
28482
  get state() {
28593
28483
  return this._state;
28594
28484
  }
@@ -28598,18 +28488,17 @@ var WorldStateMachine = class {
28598
28488
  }
28599
28489
  transition(to) {
28600
28490
  if (!this.canTransition(to)) {
28601
- throw new Error(
28602
- `Invalid state transition for world "${this.worldId}": ${this._state} \u2192 ${to}`
28603
- );
28491
+ throw new Error(`Invalid state transition for world "${this.worldId}": ${this._state} \u2192 ${to}`);
28604
28492
  }
28605
28493
  this._state = to;
28606
28494
  }
28607
28495
  };
28608
28496
 
28609
- // ../core/src/world/devbox-image.ts
28497
+ // ../core/dist/world/devbox-image.js
28610
28498
  function selectDevboxImage(config2, repos) {
28611
28499
  const selectors = config2.devbox?.image_selectors;
28612
- if (!selectors || selectors.length === 0) return void 0;
28500
+ if (!selectors || selectors.length === 0)
28501
+ return void 0;
28613
28502
  const repoNames = new Set(repos.map((r) => r.name));
28614
28503
  const repoTypes = new Set(repos.map((r) => r.type));
28615
28504
  for (const sel of selectors) {
@@ -28625,19 +28514,23 @@ function selectDevboxImage(config2, repos) {
28625
28514
  }
28626
28515
  function matches(sel, repoNames, repoTypes) {
28627
28516
  if (sel.requires_all && sel.requires_all.length > 0) {
28628
- if (!sel.requires_all.every((n) => repoNames.has(n))) return false;
28517
+ if (!sel.requires_all.every((n) => repoNames.has(n)))
28518
+ return false;
28629
28519
  }
28630
28520
  if (sel.requires_any && sel.requires_any.length > 0) {
28631
- if (!sel.requires_any.some((n) => repoNames.has(n))) return false;
28521
+ if (!sel.requires_any.some((n) => repoNames.has(n)))
28522
+ return false;
28632
28523
  }
28633
28524
  if (sel.requires_type) {
28634
- if (!repoTypes.has(sel.requires_type)) return false;
28525
+ if (!repoTypes.has(sel.requires_type))
28526
+ return false;
28635
28527
  }
28636
28528
  return true;
28637
28529
  }
28638
28530
  function resolveDevboxImage(config2, tag) {
28639
28531
  const registry2 = config2.devbox?.registry;
28640
- if (!registry2) return `olam-devbox:${tag}`;
28532
+ if (!registry2)
28533
+ return `olam-devbox:${tag}`;
28641
28534
  if (registry2.tags && registry2.tags[tag]) {
28642
28535
  return registry2.tags[tag];
28643
28536
  }
@@ -28648,7 +28541,7 @@ function resolveDevboxImage(config2, tag) {
28648
28541
  return `olam-devbox:${tag}`;
28649
28542
  }
28650
28543
 
28651
- // ../core/src/world/worktree.ts
28544
+ // ../core/dist/world/worktree.js
28652
28545
  import { execFileSync as execFileSync2 } from "node:child_process";
28653
28546
  import * as fs10 from "node:fs";
28654
28547
  import * as path13 from "node:path";
@@ -28656,9 +28549,7 @@ function resolveGitDir(repo) {
28656
28549
  if (repo.path) {
28657
28550
  return repo.path;
28658
28551
  }
28659
- throw new Error(
28660
- `Repo "${repo.name}" has no local path. Clone from ${repo.url} first.`
28661
- );
28552
+ throw new Error(`Repo "${repo.name}" has no local path. Clone from ${repo.url} first.`);
28662
28553
  }
28663
28554
  async function createWorktrees(repos, worldId, workspacePath, branch) {
28664
28555
  const created = [];
@@ -28694,9 +28585,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
28694
28585
  }
28695
28586
  }
28696
28587
  const message = err instanceof Error ? err.message : String(err);
28697
- throw new Error(
28698
- `Failed to create worktree for repo "${repo.name}": ${message}`
28699
- );
28588
+ throw new Error(`Failed to create worktree for repo "${repo.name}": ${message}`);
28700
28589
  }
28701
28590
  }
28702
28591
  }
@@ -28746,11 +28635,7 @@ function removeBranch(repo, branch) {
28746
28635
  }
28747
28636
  let hasUpstream = false;
28748
28637
  try {
28749
- execFileSync2(
28750
- "git",
28751
- ["rev-parse", "--abbrev-ref", `${branch}@{upstream}`],
28752
- { cwd: gitDir, stdio: "pipe" }
28753
- );
28638
+ execFileSync2("git", ["rev-parse", "--abbrev-ref", `${branch}@{upstream}`], { cwd: gitDir, stdio: "pipe" });
28754
28639
  hasUpstream = true;
28755
28640
  } catch {
28756
28641
  }
@@ -28759,11 +28644,7 @@ function removeBranch(repo, branch) {
28759
28644
  }
28760
28645
  let localCommitCount = 0;
28761
28646
  try {
28762
- const output = execFileSync2(
28763
- "git",
28764
- ["rev-list", "--count", branch, "--not", "--remotes"],
28765
- { cwd: gitDir, stdio: "pipe" }
28766
- ).toString().trim();
28647
+ const output = execFileSync2("git", ["rev-list", "--count", branch, "--not", "--remotes"], { cwd: gitDir, stdio: "pipe" }).toString().trim();
28767
28648
  localCommitCount = parseInt(output, 10) || 0;
28768
28649
  } catch {
28769
28650
  localCommitCount = 1;
@@ -28778,14 +28659,12 @@ function removeBranch(repo, branch) {
28778
28659
  }
28779
28660
  return { branch, action: "deleted" };
28780
28661
  }
28781
- process.stderr.write(
28782
- `[olam] Branch "${branch}" has ${localCommitCount} unpushed commit(s). Keeping branch \u2014 push or merge before re-creating a world with the same branch name.
28783
- `
28784
- );
28662
+ process.stderr.write(`[olam] Branch "${branch}" has ${localCommitCount} unpushed commit(s). Keeping branch \u2014 push or merge before re-creating a world with the same branch name.
28663
+ `);
28785
28664
  return { branch, action: "kept-local-commits", localCommitCount };
28786
28665
  }
28787
28666
 
28788
- // ../core/src/world/baseline-diff.ts
28667
+ // ../core/dist/world/baseline-diff.js
28789
28668
  import { execFileSync as execFileSync3 } from "node:child_process";
28790
28669
  import * as fs11 from "node:fs";
28791
28670
  import * as os7 from "node:os";
@@ -28799,12 +28678,14 @@ function sanitizeRepoFilename(name) {
28799
28678
  return sanitized.length > 0 ? sanitized : "_";
28800
28679
  }
28801
28680
  function isOversizeError(err) {
28802
- if (!err || typeof err !== "object") return false;
28681
+ if (!err || typeof err !== "object")
28682
+ return false;
28803
28683
  const code = err.code;
28804
28684
  return code === "ENOBUFS";
28805
28685
  }
28806
28686
  function isNoHeadError(err) {
28807
- if (!err || typeof err !== "object") return false;
28687
+ if (!err || typeof err !== "object")
28688
+ return false;
28808
28689
  const msg = err.message ?? "";
28809
28690
  const stderr = String(err.stderr ?? "");
28810
28691
  const blob = `${msg}
@@ -28825,7 +28706,8 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
28825
28706
  const perRepo = [];
28826
28707
  let total = 0;
28827
28708
  for (const repo of repos) {
28828
- if (!repo.path) continue;
28709
+ if (!repo.path)
28710
+ continue;
28829
28711
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
28830
28712
  const outPath = path14.join(baselineDir, filename);
28831
28713
  const repoPath = expandHome(repo.path, homedir11);
@@ -28876,9 +28758,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
28876
28758
  } catch (err) {
28877
28759
  if (isOversizeError(err)) {
28878
28760
  oversized = true;
28879
- console.warn(
28880
- `[baseline-diff] ${repo.name}: git diff HEAD exceeded ${DEFAULT_MAX_BUFFER_BYTES / (1024 * 1024)}MB; baseline could not be captured \u2014 reaper PR for this repo will treat all tracked changes as claude's work, review carefully`
28881
- );
28761
+ console.warn(`[baseline-diff] ${repo.name}: git diff HEAD exceeded ${DEFAULT_MAX_BUFFER_BYTES / (1024 * 1024)}MB; baseline could not be captured \u2014 reaper PR for this repo will treat all tracked changes as claude's work, review carefully`);
28882
28762
  } else {
28883
28763
  const msg = err instanceof Error ? err.message : String(err);
28884
28764
  console.warn(`[baseline-diff] ${repo.name}: git diff failed (${msg}); skipping`);
@@ -28907,7 +28787,8 @@ function writeBaselineFile(outPath, content) {
28907
28787
  function stripWorktreeEdits(repos, workspacePath) {
28908
28788
  for (const repo of repos) {
28909
28789
  const worktreePath = path14.join(workspacePath, repo.name);
28910
- if (!fs11.existsSync(worktreePath)) continue;
28790
+ if (!fs11.existsSync(worktreePath))
28791
+ continue;
28911
28792
  try {
28912
28793
  execFileSync3("git", ["checkout", "--", "."], {
28913
28794
  cwd: worktreePath,
@@ -28923,8 +28804,10 @@ function formatBaselineSummary(result) {
28923
28804
  const noHeadRepos = result.perRepo.filter((r) => r.noHead).map((r) => r.name);
28924
28805
  const oversizedRepos = result.perRepo.filter((r) => r.oversized).map((r) => r.name);
28925
28806
  const flagsSuffix = [];
28926
- if (noHeadRepos.length > 0) flagsSuffix.push(`noHead: ${noHeadRepos.join(", ")}`);
28927
- if (oversizedRepos.length > 0) flagsSuffix.push(`oversized: ${oversizedRepos.join(", ")}`);
28807
+ if (noHeadRepos.length > 0)
28808
+ flagsSuffix.push(`noHead: ${noHeadRepos.join(", ")}`);
28809
+ if (oversizedRepos.length > 0)
28810
+ flagsSuffix.push(`oversized: ${oversizedRepos.join(", ")}`);
28928
28811
  const flagsStr = flagsSuffix.length > 0 ? ` [${flagsSuffix.join("; ")}]` : "";
28929
28812
  if (result.totalUncommittedFiles === 0) {
28930
28813
  return `[baseline] no uncommitted files; per-repo baseline files written empty${flagsStr}`;
@@ -28933,7 +28816,7 @@ function formatBaselineSummary(result) {
28933
28816
  return `[baseline] skipping ${result.totalUncommittedFiles} uncommitted file(s) (${perRepoStr})${flagsStr}; pass --carry-uncommitted to bring them in`;
28934
28817
  }
28935
28818
 
28936
- // ../core/src/world/context-injection.ts
28819
+ // ../core/dist/world/context-injection.js
28937
28820
  import * as fs12 from "node:fs";
28938
28821
  import * as path15 from "node:path";
28939
28822
  function injectWorldContext(opts) {
@@ -29112,7 +28995,8 @@ function formatTaskSource(ctx) {
29112
28995
  return ctx.source;
29113
28996
  }
29114
28997
  function hasPlanFile(world) {
29115
- if (world.repos.length === 0) return false;
28998
+ if (world.repos.length === 0)
28999
+ return false;
29116
29000
  const plansDir = path15.join(world.workspacePath, world.repos[0], "docs", "plans");
29117
29001
  try {
29118
29002
  return fs12.existsSync(plansDir) && fs12.readdirSync(plansDir).length > 0;
@@ -29121,11 +29005,13 @@ function hasPlanFile(world) {
29121
29005
  }
29122
29006
  }
29123
29007
 
29124
- // ../core/src/world/stack-detect.ts
29008
+ // ../core/dist/world/stack-detect.js
29125
29009
  function sanitizeVersion(raw) {
29126
- if (!raw) return void 0;
29010
+ if (!raw)
29011
+ return void 0;
29127
29012
  const trimmed = raw.trim();
29128
- if (!trimmed) return void 0;
29013
+ if (!trimmed)
29014
+ return void 0;
29129
29015
  return versionStringSchema.safeParse(trimmed).success ? trimmed : void 0;
29130
29016
  }
29131
29017
  function shellEscapePath(p) {
@@ -29134,24 +29020,30 @@ function shellEscapePath(p) {
29134
29020
  async function detectRubyVersion(exec, repoDir) {
29135
29021
  const escapedDir = shellEscapePath(repoDir);
29136
29022
  const rv = await tryReadFile(exec, `${escapedDir}/.ruby-version`);
29137
- if (rv) return sanitizeVersion(rv);
29023
+ if (rv)
29024
+ return sanitizeVersion(rv);
29138
29025
  const gemfile = await tryReadFile(exec, `${escapedDir}/Gemfile`);
29139
29026
  if (gemfile) {
29140
29027
  const match = gemfile.match(/^\s*ruby\s+['"]([^'"~>=<]+)['"]/m);
29141
- if (match) return sanitizeVersion(match[1]);
29028
+ if (match)
29029
+ return sanitizeVersion(match[1]);
29142
29030
  const rangeMatch = gemfile.match(/^\s*ruby\s+['"]~>\s*(\d+\.\d+(?:\.\d+)?)['"]/m);
29143
- if (rangeMatch) return sanitizeVersion(rangeMatch[1]);
29031
+ if (rangeMatch)
29032
+ return sanitizeVersion(rangeMatch[1]);
29144
29033
  const minMatch = gemfile.match(/^\s*ruby\s+['"]>=?\s*(\d+\.\d+(?:\.\d+)?)['"]/m);
29145
- if (minMatch) return sanitizeVersion(minMatch[1]);
29034
+ if (minMatch)
29035
+ return sanitizeVersion(minMatch[1]);
29146
29036
  }
29147
29037
  const tv = await tryReadToolVersions(exec, escapedDir, "ruby");
29148
- if (tv) return sanitizeVersion(tv);
29038
+ if (tv)
29039
+ return sanitizeVersion(tv);
29149
29040
  return void 0;
29150
29041
  }
29151
29042
  async function detectNodeVersion(exec, repoDir) {
29152
29043
  const escapedDir = shellEscapePath(repoDir);
29153
29044
  const nv = await tryReadFile(exec, `${escapedDir}/.node-version`);
29154
- if (nv) return sanitizeVersion(nv);
29045
+ if (nv)
29046
+ return sanitizeVersion(nv);
29155
29047
  const pkg = await tryReadFile(exec, `${escapedDir}/package.json`);
29156
29048
  if (pkg) {
29157
29049
  try {
@@ -29159,30 +29051,37 @@ async function detectNodeVersion(exec, repoDir) {
29159
29051
  const nodeVersion = parsed.engines?.node;
29160
29052
  if (nodeVersion) {
29161
29053
  const exact = nodeVersion.match(/(\d+\.\d+\.\d+)/);
29162
- if (exact) return sanitizeVersion(exact[1]);
29054
+ if (exact)
29055
+ return sanitizeVersion(exact[1]);
29163
29056
  const major = nodeVersion.match(/(\d+)/);
29164
- if (major) return sanitizeVersion(major[1]);
29057
+ if (major)
29058
+ return sanitizeVersion(major[1]);
29165
29059
  }
29166
29060
  } catch {
29167
29061
  }
29168
29062
  }
29169
29063
  const nvmrc = await tryReadFile(exec, `${escapedDir}/.nvmrc`);
29170
- if (nvmrc) return sanitizeVersion(nvmrc);
29064
+ if (nvmrc)
29065
+ return sanitizeVersion(nvmrc);
29171
29066
  const tv = await tryReadToolVersions(exec, escapedDir, "nodejs");
29172
- if (tv) return sanitizeVersion(tv);
29067
+ if (tv)
29068
+ return sanitizeVersion(tv);
29173
29069
  return void 0;
29174
29070
  }
29175
29071
  async function detectPythonVersion(exec, repoDir) {
29176
29072
  const escapedDir = shellEscapePath(repoDir);
29177
29073
  const pv = await tryReadFile(exec, `${escapedDir}/.python-version`);
29178
- if (pv) return sanitizeVersion(pv);
29074
+ if (pv)
29075
+ return sanitizeVersion(pv);
29179
29076
  const pyproject = await tryReadFile(exec, `${escapedDir}/pyproject.toml`);
29180
29077
  if (pyproject) {
29181
29078
  const match = pyproject.match(/requires-python\s*=\s*["']>=?\s*(\d+\.\d+(?:\.\d+)?)/);
29182
- if (match) return sanitizeVersion(match[1]);
29079
+ if (match)
29080
+ return sanitizeVersion(match[1]);
29183
29081
  }
29184
29082
  const tv = await tryReadToolVersions(exec, escapedDir, "python");
29185
- if (tv) return sanitizeVersion(tv);
29083
+ if (tv)
29084
+ return sanitizeVersion(tv);
29186
29085
  return void 0;
29187
29086
  }
29188
29087
  async function tryReadFile(exec, escapedPath) {
@@ -29197,10 +29096,12 @@ async function tryReadFile(exec, escapedPath) {
29197
29096
  }
29198
29097
  async function tryReadToolVersions(exec, escapedDir, runtime) {
29199
29098
  const content = await tryReadFile(exec, `${escapedDir}/.tool-versions`);
29200
- if (!content) return void 0;
29099
+ if (!content)
29100
+ return void 0;
29201
29101
  for (const line of content.split("\n")) {
29202
29102
  const trimmed = line.trim();
29203
- if (trimmed.startsWith("#") || !trimmed) continue;
29103
+ if (trimmed.startsWith("#") || !trimmed)
29104
+ continue;
29204
29105
  const parts = trimmed.split(/\s+/);
29205
29106
  if (parts[0] === runtime && parts[1]) {
29206
29107
  return parts[1].trim();
@@ -29215,16 +29116,20 @@ async function detectRepoStack(exec, repoDir, repoName) {
29215
29116
  detectPythonVersion(exec, repoDir)
29216
29117
  ]);
29217
29118
  const versions = {};
29218
- if (ruby) versions.ruby = ruby;
29219
- if (node) versions.node = node;
29220
- if (python) versions.python = python;
29119
+ if (ruby)
29120
+ versions.ruby = ruby;
29121
+ if (node)
29122
+ versions.node = node;
29123
+ if (python)
29124
+ versions.python = python;
29221
29125
  return { repoName, versions };
29222
29126
  }
29223
29127
  function collectUniqueRuntimes(stacks) {
29224
29128
  const runtimes = /* @__PURE__ */ new Map();
29225
29129
  for (const stack of stacks) {
29226
29130
  for (const [runtime, version2] of Object.entries(stack.versions)) {
29227
- if (!version2) continue;
29131
+ if (!version2)
29132
+ continue;
29228
29133
  const existing = runtimes.get(runtime) ?? /* @__PURE__ */ new Set();
29229
29134
  existing.add(version2);
29230
29135
  runtimes.set(runtime, existing);
@@ -29233,7 +29138,7 @@ function collectUniqueRuntimes(stacks) {
29233
29138
  return runtimes;
29234
29139
  }
29235
29140
 
29236
- // ../core/src/world/stack-install.ts
29141
+ // ../core/dist/world/stack-install.js
29237
29142
  var MISE_RUNTIME_NAME = {
29238
29143
  ruby: "ruby",
29239
29144
  node: "node",
@@ -29297,11 +29202,13 @@ async function installStack(exec, repos, stacks) {
29297
29202
  }
29298
29203
  for (const repo of repos) {
29299
29204
  const stack = stacks.get(repo.name);
29300
- if (!stack || Object.keys(stack.versions).length === 0) continue;
29205
+ if (!stack || Object.keys(stack.versions).length === 0)
29206
+ continue;
29301
29207
  const repoDir = `/home/olam/workspace/${shellEscapePath2(repo.name)}`;
29302
29208
  const entries = [];
29303
29209
  for (const [runtime, version2] of Object.entries(stack.versions)) {
29304
- if (!version2) continue;
29210
+ if (!version2)
29211
+ continue;
29305
29212
  const miseName = MISE_RUNTIME_NAME[runtime] ?? runtime;
29306
29213
  entries.push(`${miseName} ${version2}`);
29307
29214
  }
@@ -29317,7 +29224,7 @@ async function installStack(exec, repos, stacks) {
29317
29224
  };
29318
29225
  }
29319
29226
 
29320
- // ../core/src/world/stack-image.ts
29227
+ // ../core/dist/world/stack-image.js
29321
29228
  import { execSync as execSync2 } from "node:child_process";
29322
29229
  import * as crypto3 from "node:crypto";
29323
29230
  var BASE_IMAGE = "olam-devbox";
@@ -29331,7 +29238,8 @@ function computeFingerprint(runtimes) {
29331
29238
  }
29332
29239
  }
29333
29240
  parts.sort();
29334
- if (parts.length === 0) return "base";
29241
+ if (parts.length === 0)
29242
+ return "base";
29335
29243
  const joined = parts.join("_");
29336
29244
  return sanitizeTag(joined);
29337
29245
  }
@@ -29361,19 +29269,14 @@ function lookupCachedImage(runtimes) {
29361
29269
  function commitAsImage(containerName, imageName) {
29362
29270
  const baseDigest = getBaseImageDigest();
29363
29271
  const now = (/* @__PURE__ */ new Date()).toISOString();
29364
- execSync2(
29365
- `docker commit --change 'LABEL ${LABEL_PREFIX}=true' --change 'LABEL ${LABEL_PREFIX}.created-at=${now}' --change 'LABEL ${LABEL_PREFIX}.base-digest=${baseDigest}' ${containerName} ${imageName}`,
29366
- { stdio: "pipe", timeout: 12e4 }
29367
- );
29272
+ execSync2(`docker commit --change 'LABEL ${LABEL_PREFIX}=true' --change 'LABEL ${LABEL_PREFIX}.created-at=${now}' --change 'LABEL ${LABEL_PREFIX}.base-digest=${baseDigest}' ${containerName} ${imageName}`, { stdio: "pipe", timeout: 12e4 });
29368
29273
  }
29369
29274
  var cachedBaseDigest;
29370
29275
  function getBaseImageDigest() {
29371
- if (cachedBaseDigest) return cachedBaseDigest;
29276
+ if (cachedBaseDigest)
29277
+ return cachedBaseDigest;
29372
29278
  try {
29373
- const digest = execSync2(
29374
- `docker inspect ${BASE_IMAGE}:latest --format '{{.Id}}'`,
29375
- { encoding: "utf-8", timeout: 5e3 }
29376
- ).trim();
29279
+ const digest = execSync2(`docker inspect ${BASE_IMAGE}:latest --format '{{.Id}}'`, { encoding: "utf-8", timeout: 5e3 }).trim();
29377
29280
  cachedBaseDigest = digest.replace("sha256:", "").slice(0, 16);
29378
29281
  return cachedBaseDigest;
29379
29282
  } catch {
@@ -29390,52 +29293,46 @@ function sanitizeTag(raw) {
29390
29293
  return tag;
29391
29294
  }
29392
29295
 
29393
- // ../core/src/world/manager.ts
29296
+ // ../core/dist/world/manager.js
29394
29297
  import YAML3 from "yaml";
29395
29298
 
29396
- // ../core/src/world/manifest-env.ts
29299
+ // ../core/dist/world/manifest-env.js
29397
29300
  var EXPR_PATTERN = /\$\{[^}]+\}/;
29398
29301
  var MAX_DEPTH = 8;
29399
29302
  var REPO_FIELDS = /* @__PURE__ */ new Set(["url", "path", "port", "branch"]);
29400
29303
  var SERVICE_FIELDS = /* @__PURE__ */ new Set(["port", "host"]);
29401
29304
  var WORLD_FIELDS = /* @__PURE__ */ new Set(["id", "branch", "portOffset"]);
29402
29305
  var EnvSubstCycleError = class extends Error {
29306
+ key;
29307
+ chain;
29403
29308
  constructor(key, chain) {
29404
- super(
29405
- `[manifest-env] cycle detected for key "${key}" \u2014 values cycled: ${chain.map((v) => `"${v}"`).join(" \u2192 ")}`
29406
- );
29309
+ super(`[manifest-env] cycle detected for key "${key}" \u2014 values cycled: ${chain.map((v) => `"${v}"`).join(" \u2192 ")}`);
29407
29310
  this.key = key;
29408
29311
  this.chain = chain;
29409
29312
  this.name = "EnvSubstCycleError";
29410
29313
  }
29411
- key;
29412
- chain;
29413
29314
  };
29414
29315
  var EnvSubstDepthExceededError = class extends Error {
29316
+ key;
29317
+ lastValue;
29318
+ maxDepth;
29415
29319
  constructor(key, lastValue, maxDepth) {
29416
- super(
29417
- `[manifest-env] reference for key "${key}" did not resolve within ${maxDepth} passes (last value: "${lastValue}"); chain too deep \u2014 examine for unintended indirection`
29418
- );
29320
+ super(`[manifest-env] reference for key "${key}" did not resolve within ${maxDepth} passes (last value: "${lastValue}"); chain too deep \u2014 examine for unintended indirection`);
29419
29321
  this.key = key;
29420
29322
  this.lastValue = lastValue;
29421
29323
  this.maxDepth = maxDepth;
29422
29324
  this.name = "EnvSubstDepthExceededError";
29423
29325
  }
29424
- key;
29425
- lastValue;
29426
- maxDepth;
29427
29326
  };
29428
29327
  var EnvSubstMissingRepoError = class extends Error {
29328
+ subject;
29329
+ expression;
29429
29330
  constructor(subject, expression) {
29430
- super(
29431
- `[manifest-env] \${${expression}}: ${subject} unresolved; using empty string`
29432
- );
29331
+ super(`[manifest-env] \${${expression}}: ${subject} unresolved; using empty string`);
29433
29332
  this.subject = subject;
29434
29333
  this.expression = expression;
29435
29334
  this.name = "EnvSubstMissingRepoError";
29436
29335
  }
29437
- subject;
29438
- expression;
29439
29336
  };
29440
29337
  function parseExpression(expr) {
29441
29338
  const idx = expr.indexOf(":-");
@@ -29445,15 +29342,20 @@ function parseExpression(expr) {
29445
29342
  return { name: expr.slice(0, idx), fallback: expr.slice(idx + 2) };
29446
29343
  }
29447
29344
  function readWhitelistedField(obj, field, whitelist) {
29448
- if (!obj) return void 0;
29449
- if (!whitelist.has(field)) return void 0;
29450
- if (!Object.hasOwn(obj, field)) return void 0;
29345
+ if (!obj)
29346
+ return void 0;
29347
+ if (!whitelist.has(field))
29348
+ return void 0;
29349
+ if (!Object.hasOwn(obj, field))
29350
+ return void 0;
29451
29351
  const value = obj[field];
29452
- if (value === void 0 || value === null) return void 0;
29352
+ if (value === void 0 || value === null)
29353
+ return void 0;
29453
29354
  return String(value);
29454
29355
  }
29455
29356
  function readEnvVar(env, name) {
29456
- if (!Object.hasOwn(env, name)) return void 0;
29357
+ if (!Object.hasOwn(env, name))
29358
+ return void 0;
29457
29359
  const v = env[name];
29458
29360
  return v;
29459
29361
  }
@@ -29471,11 +29373,7 @@ function resolveRef(name, ctx) {
29471
29373
  reason: `repo field "${field}" is not a permitted reference (allowed: ${[...REPO_FIELDS].join(", ")})`
29472
29374
  };
29473
29375
  }
29474
- const value = readWhitelistedField(
29475
- repo,
29476
- field,
29477
- REPO_FIELDS
29478
- );
29376
+ const value = readWhitelistedField(repo, field, REPO_FIELDS);
29479
29377
  if (value === void 0) {
29480
29378
  return { kind: "miss", reason: `repo "${repoName}" has no field "${field}"` };
29481
29379
  }
@@ -29493,11 +29391,7 @@ function resolveRef(name, ctx) {
29493
29391
  reason: `service field "${field}" is not a permitted reference (allowed: ${[...SERVICE_FIELDS].join(", ")})`
29494
29392
  };
29495
29393
  }
29496
- const value = readWhitelistedField(
29497
- svc,
29498
- field,
29499
- SERVICE_FIELDS
29500
- );
29394
+ const value = readWhitelistedField(svc, field, SERVICE_FIELDS);
29501
29395
  if (value === void 0) {
29502
29396
  return { kind: "miss", reason: `service "${serviceName}" has no field "${field}"` };
29503
29397
  }
@@ -29511,11 +29405,7 @@ function resolveRef(name, ctx) {
29511
29405
  reason: `world field "${field}" is not a permitted reference (allowed: ${[...WORLD_FIELDS].join(", ")})`
29512
29406
  };
29513
29407
  }
29514
- const value = readWhitelistedField(
29515
- ctx.world,
29516
- field,
29517
- WORLD_FIELDS
29518
- );
29408
+ const value = readWhitelistedField(ctx.world, field, WORLD_FIELDS);
29519
29409
  if (value === void 0) {
29520
29410
  return { kind: "miss", reason: `world has no field "${field}"` };
29521
29411
  }
@@ -29547,11 +29437,11 @@ function substituteOnce(input, ctx, warnings) {
29547
29437
  return input.replace(/\$\{([^}]+)\}/g, (_, expr) => {
29548
29438
  const { name, fallback } = parseExpression(expr);
29549
29439
  const ref = resolveRef(name, ctx);
29550
- if (ref.kind === "ok") return ref.value;
29551
- if (fallback !== void 0) return fallback;
29552
- warnings.push(
29553
- new EnvSubstMissingRepoError(ref.reason, expr).message
29554
- );
29440
+ if (ref.kind === "ok")
29441
+ return ref.value;
29442
+ if (fallback !== void 0)
29443
+ return fallback;
29444
+ warnings.push(new EnvSubstMissingRepoError(ref.reason, expr).message);
29555
29445
  return "";
29556
29446
  });
29557
29447
  }
@@ -29562,9 +29452,11 @@ function resolveManifestEnv(env, ctx) {
29562
29452
  let current = rawValue;
29563
29453
  const seen = /* @__PURE__ */ new Set([current]);
29564
29454
  for (let depth = 0; depth < MAX_DEPTH; depth++) {
29565
- if (!EXPR_PATTERN.test(current)) break;
29455
+ if (!EXPR_PATTERN.test(current))
29456
+ break;
29566
29457
  const next = substituteOnce(current, ctx, warnings);
29567
- if (next === current) break;
29458
+ if (next === current)
29459
+ break;
29568
29460
  if (seen.has(next)) {
29569
29461
  throw new EnvSubstCycleError(key, [...seen, next]);
29570
29462
  }
@@ -29579,7 +29471,7 @@ function resolveManifestEnv(env, ctx) {
29579
29471
  return { env: resolved, warnings: [...new Set(warnings)] };
29580
29472
  }
29581
29473
 
29582
- // ../core/src/world/bootstrap-runner.ts
29474
+ // ../core/dist/world/bootstrap-runner.js
29583
29475
  var BootstrapStepError = class extends Error {
29584
29476
  step;
29585
29477
  index;
@@ -29597,12 +29489,12 @@ ${stderr}`);
29597
29489
  var SAFE_IDENT = /^[a-z0-9][a-z0-9-]{0,63}$/;
29598
29490
  var SAFE_WORKDIR_SEGMENT = /^[\w.-]+$/;
29599
29491
  function isSafeWorkdir(workdir) {
29600
- if (!workdir.startsWith("/")) return false;
29492
+ if (!workdir.startsWith("/"))
29493
+ return false;
29601
29494
  const segments = workdir.slice(1).split("/");
29602
- if (segments.length === 0) return false;
29603
- return segments.every(
29604
- (seg) => seg.length > 0 && seg !== "." && seg !== ".." && SAFE_WORKDIR_SEGMENT.test(seg)
29605
- );
29495
+ if (segments.length === 0)
29496
+ return false;
29497
+ return segments.every((seg) => seg.length > 0 && seg !== "." && seg !== ".." && SAFE_WORKDIR_SEGMENT.test(seg));
29606
29498
  }
29607
29499
  var SENTINEL_PREFIX = ".olam-bootstrap-";
29608
29500
  var SENTINEL_SUFFIX = "-done";
@@ -29611,14 +29503,10 @@ function sentinelPath(workdir, index) {
29611
29503
  }
29612
29504
  async function runBootstrap(containerName, workdir, steps, exec, options = {}) {
29613
29505
  if (!SAFE_IDENT.test(containerName)) {
29614
- throw new Error(
29615
- `containerName "${containerName}" must match ${SAFE_IDENT} (defensive guard)`
29616
- );
29506
+ throw new Error(`containerName "${containerName}" must match ${SAFE_IDENT} (defensive guard)`);
29617
29507
  }
29618
29508
  if (!isSafeWorkdir(workdir)) {
29619
- throw new Error(
29620
- `workdir "${workdir}" must be an absolute path with no "." or ".." segments (defensive guard)`
29621
- );
29509
+ throw new Error(`workdir "${workdir}" must be an absolute path with no "." or ".." segments (defensive guard)`);
29622
29510
  }
29623
29511
  const clock = options.clock ?? Date.now;
29624
29512
  if (options.rebootstrap) {
@@ -29668,16 +29556,19 @@ function shellQuote(s) {
29668
29556
  return `'${s.replace(/'/g, `'\\''`)}'`;
29669
29557
  }
29670
29558
 
29671
- // ../core/src/world/secrets-fetcher.ts
29559
+ // ../core/dist/world/secrets-fetcher.js
29672
29560
  import { execSync as execSync3 } from "node:child_process";
29673
29561
  function parseGcpSecretUrl(url) {
29674
- if (!url.startsWith("gcp://")) return null;
29562
+ if (!url.startsWith("gcp://"))
29563
+ return null;
29675
29564
  const without = url.slice("gcp://".length);
29676
29565
  const slash = without.indexOf("/");
29677
- if (slash === -1) return null;
29566
+ if (slash === -1)
29567
+ return null;
29678
29568
  const project = without.slice(0, slash);
29679
29569
  const secretName = without.slice(slash + 1);
29680
- if (!project || !secretName) return null;
29570
+ if (!project || !secretName)
29571
+ return null;
29681
29572
  return { project, secretName };
29682
29573
  }
29683
29574
  function defaultExecFn(cmd, opts) {
@@ -29687,27 +29578,18 @@ function fetchGcpSecret(ref, execFn = defaultExecFn) {
29687
29578
  const { project, secretName } = ref;
29688
29579
  let raw;
29689
29580
  try {
29690
- raw = execFn(
29691
- `gcloud secrets versions access latest --secret=${secretName} --project=${project}`,
29692
- { timeout: 15e3 }
29693
- ).trim();
29581
+ raw = execFn(`gcloud secrets versions access latest --secret=${secretName} --project=${project}`, { timeout: 15e3 }).trim();
29694
29582
  } catch (err) {
29695
29583
  const msg = err instanceof Error ? err.message : String(err);
29696
29584
  if (msg.includes("NOT_FOUND") || msg.includes("not found")) {
29697
- throw new Error(
29698
- `Secret not found: gcp://${project}/${secretName}. Check the secret name exists in project ${project}.`
29699
- );
29585
+ throw new Error(`Secret not found: gcp://${project}/${secretName}. Check the secret name exists in project ${project}.`);
29700
29586
  }
29701
29587
  if (msg.includes("PERMISSION_DENIED") || msg.includes("403")) {
29702
- throw new Error(
29703
- `Permission denied fetching gcp://${project}/${secretName}. Grant your gcloud account roles/secretmanager.secretAccessor on this secret.`
29704
- );
29588
+ throw new Error(`Permission denied fetching gcp://${project}/${secretName}. Grant your gcloud account roles/secretmanager.secretAccessor on this secret.`);
29705
29589
  }
29706
29590
  if (msg.includes("not authenticated") || msg.includes("credentials") || msg.includes("login") || msg.includes("authenticated")) {
29707
- throw new Error(
29708
- `No gcloud credentials found while fetching gcp://${project}/${secretName}.
29709
- Run: gcloud auth application-default login`
29710
- );
29591
+ throw new Error(`No gcloud credentials found while fetching gcp://${project}/${secretName}.
29592
+ Run: gcloud auth application-default login`);
29711
29593
  }
29712
29594
  throw new Error(`Failed to fetch secret gcp://${project}/${secretName}: ${msg}`);
29713
29595
  }
@@ -29718,14 +29600,10 @@ Run: gcloud auth application-default login`
29718
29600
  try {
29719
29601
  parsed = JSON.parse(raw);
29720
29602
  } catch {
29721
- throw new Error(
29722
- `Secret gcp://${project}/${secretName} is not valid JSON. The secret value must be a JSON object: {"ENV_VAR": "value", ...}`
29723
- );
29603
+ throw new Error(`Secret gcp://${project}/${secretName} is not valid JSON. The secret value must be a JSON object: {"ENV_VAR": "value", ...}`);
29724
29604
  }
29725
29605
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
29726
- throw new Error(
29727
- `Secret gcp://${project}/${secretName} must be a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}.`
29728
- );
29606
+ throw new Error(`Secret gcp://${project}/${secretName} must be a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}.`);
29729
29607
  }
29730
29608
  const result = {};
29731
29609
  for (const [k, v] of Object.entries(parsed)) {
@@ -29737,11 +29615,10 @@ var FILE_BACKED_SECRET_KEYS = [
29737
29615
  { envVar: "RAILS_MASTER_KEY", filePath: "config/credentials/development.key" }
29738
29616
  ];
29739
29617
  function fetchSecretsForRepos(repoSecretUrls, execFn = defaultExecFn) {
29740
- if (repoSecretUrls.length === 0) return { env: {}, fileWrites: [] };
29618
+ if (repoSecretUrls.length === 0)
29619
+ return { env: {}, fileWrites: [] };
29741
29620
  if (!gcloudAvailable(execFn)) {
29742
- console.warn(
29743
- "[secrets] WARN: gcloud CLI not installed or not authenticated \u2014 skipping GCP secret injection for ALL repos. To enable: install gcloud and run `gcloud auth application-default login`. World will boot WITHOUT declared GCP secrets."
29744
- );
29621
+ console.warn("[secrets] WARN: gcloud CLI not installed or not authenticated \u2014 skipping GCP secret injection for ALL repos. To enable: install gcloud and run `gcloud auth application-default login`. World will boot WITHOUT declared GCP secrets.");
29745
29622
  return { env: {}, fileWrites: [] };
29746
29623
  }
29747
29624
  const env = {};
@@ -29774,9 +29651,7 @@ function fetchSecretsForRepos(repoSecretUrls, execFn = defaultExecFn) {
29774
29651
  envCount++;
29775
29652
  }
29776
29653
  }
29777
- console.log(
29778
- `[secrets] ${repoName}: ${envCount} env var(s) + ${fileCount} file-backed key(s) from ${secretsUrl}`
29779
- );
29654
+ console.log(`[secrets] ${repoName}: ${envCount} env var(s) + ${fileCount} file-backed key(s) from ${secretsUrl}`);
29780
29655
  }
29781
29656
  return { env, fileWrites };
29782
29657
  }
@@ -29789,7 +29664,7 @@ function gcloudAvailable(execFn = defaultExecFn) {
29789
29664
  }
29790
29665
  }
29791
29666
 
29792
- // ../core/src/world/olam-yaml.ts
29667
+ // ../core/dist/world/olam-yaml.js
29793
29668
  import * as path16 from "node:path";
29794
29669
  import YAML2 from "yaml";
29795
29670
  function enrichReposWithManifests(repos, workspacePath) {
@@ -29805,18 +29680,20 @@ function enrichReposWithManifests(repos, workspacePath) {
29805
29680
  const msg = err instanceof Error ? err.message : String(err);
29806
29681
  console.warn(`[olam-yaml] failed to load manifest for repo "${repo.name}": ${msg}`);
29807
29682
  }
29808
- if (manifest === null) return repo;
29683
+ if (manifest === null)
29684
+ return repo;
29809
29685
  return { ...repo, manifest };
29810
29686
  });
29811
29687
  }
29812
29688
 
29813
- // ../core/src/policies/loader.ts
29689
+ // ../core/dist/policies/loader.js
29814
29690
  import * as fs13 from "node:fs";
29815
29691
  import * as path17 from "node:path";
29816
29692
  import { parse as parseYaml3 } from "yaml";
29817
29693
  function parseFrontmatter(content) {
29818
29694
  const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
29819
- if (!match) return null;
29695
+ if (!match)
29696
+ return null;
29820
29697
  const [, yamlText = "", body = ""] = match;
29821
29698
  try {
29822
29699
  const frontmatter = parseYaml3(yamlText);
@@ -29826,12 +29703,14 @@ function parseFrontmatter(content) {
29826
29703
  }
29827
29704
  }
29828
29705
  function toStringArray(v) {
29829
- if (!Array.isArray(v)) return [];
29706
+ if (!Array.isArray(v))
29707
+ return [];
29830
29708
  return v.filter((x) => typeof x === "string");
29831
29709
  }
29832
29710
  function loadPolicies(workspaceRoot) {
29833
29711
  const policiesDir = path17.join(workspaceRoot, ".olam", "policies");
29834
- if (!fs13.existsSync(policiesDir)) return [];
29712
+ if (!fs13.existsSync(policiesDir))
29713
+ return [];
29835
29714
  let files;
29836
29715
  try {
29837
29716
  files = fs13.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
@@ -29854,9 +29733,7 @@ function loadPolicies(workspaceRoot) {
29854
29733
  continue;
29855
29734
  }
29856
29735
  const requires = fm.requires !== null && typeof fm.requires === "object" ? {
29857
- diff_includes: toStringArray(
29858
- fm.requires.diff_includes
29859
- )
29736
+ diff_includes: toStringArray(fm.requires.diff_includes)
29860
29737
  } : void 0;
29861
29738
  const policy = {
29862
29739
  id: fm.id,
@@ -29876,7 +29753,8 @@ function loadPolicies(workspaceRoot) {
29876
29753
  return policies;
29877
29754
  }
29878
29755
  function formatPoliciesBrief(policies) {
29879
- if (policies.length === 0) return "";
29756
+ if (policies.length === 0)
29757
+ return "";
29880
29758
  const lines = [
29881
29759
  "## Active policies for this workspace",
29882
29760
  "The following policies apply to your work. Read them carefully \u2014 your",
@@ -29893,15 +29771,13 @@ function formatPoliciesBrief(policies) {
29893
29771
  return lines.join("\n");
29894
29772
  }
29895
29773
 
29896
- // ../core/src/world/tmux-supervisor.ts
29774
+ // ../core/dist/world/tmux-supervisor.js
29897
29775
  var PortInUseError = class extends Error {
29898
29776
  port;
29899
29777
  repo;
29900
29778
  manifestPath;
29901
29779
  constructor(port, repo, manifestPath) {
29902
- super(
29903
- `Port ${port} already in use on host (claimed by repo "${repo}"). Free the port or change \`app_port\` in ${manifestPath}.`
29904
- );
29780
+ super(`Port ${port} already in use on host (claimed by repo "${repo}"). Free the port or change \`app_port\` in ${manifestPath}.`);
29905
29781
  this.name = "PortInUseError";
29906
29782
  this.port = port;
29907
29783
  this.repo = repo;
@@ -29911,25 +29787,17 @@ var PortInUseError = class extends Error {
29911
29787
  var SAFE_IDENT2 = /^[a-z0-9][a-z0-9-]{0,63}$/;
29912
29788
  async function startSupervisedApps(containerName, worldId, repos, exec, options = {}) {
29913
29789
  if (!SAFE_IDENT2.test(containerName)) {
29914
- throw new Error(
29915
- `containerName "${containerName}" must match ${SAFE_IDENT2} (defensive guard)`
29916
- );
29790
+ throw new Error(`containerName "${containerName}" must match ${SAFE_IDENT2} (defensive guard)`);
29917
29791
  }
29918
29792
  if (!SAFE_IDENT2.test(worldId)) {
29919
- throw new Error(
29920
- `worldId "${worldId}" must match ${SAFE_IDENT2} (defensive guard)`
29921
- );
29793
+ throw new Error(`worldId "${worldId}" must match ${SAFE_IDENT2} (defensive guard)`);
29922
29794
  }
29923
29795
  for (const repo of repos) {
29924
29796
  if (!SAFE_IDENT2.test(repo.name)) {
29925
- throw new Error(
29926
- `repo.name "${repo.name}" must match ${SAFE_IDENT2} (defensive guard)`
29927
- );
29797
+ throw new Error(`repo.name "${repo.name}" must match ${SAFE_IDENT2} (defensive guard)`);
29928
29798
  }
29929
29799
  if (!Number.isInteger(repo.hostPort) || repo.hostPort < 1 || repo.hostPort > 65535) {
29930
- throw new Error(
29931
- `repo.hostPort ${repo.hostPort} for "${repo.name}" must be an integer in [1, 65535]`
29932
- );
29800
+ throw new Error(`repo.hostPort ${repo.hostPort} for "${repo.name}" must be an integer in [1, 65535]`);
29933
29801
  }
29934
29802
  }
29935
29803
  const sessionName = `olam-${worldId}`;
@@ -29943,13 +29811,8 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
29943
29811
  }
29944
29812
  }
29945
29813
  exec(containerName, `tmux new-session -A -d -s ${sessionName}`);
29946
- const existingRaw = exec(
29947
- containerName,
29948
- `tmux list-windows -t ${sessionName} -F '#W' 2>/dev/null || true`
29949
- );
29950
- const existingWindows = new Set(
29951
- existingRaw.split("\n").map((s) => s.trim()).filter(Boolean)
29952
- );
29814
+ const existingRaw = exec(containerName, `tmux list-windows -t ${sessionName} -F '#W' 2>/dev/null || true`);
29815
+ const existingWindows = new Set(existingRaw.split("\n").map((s) => s.trim()).filter(Boolean));
29953
29816
  const windowsCreated = [];
29954
29817
  const windowsExisting = [];
29955
29818
  for (const repo of repos) {
@@ -29957,25 +29820,17 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
29957
29820
  windowsExisting.push(repo.name);
29958
29821
  continue;
29959
29822
  }
29960
- const expandedStart = repo.start.replace(
29961
- /\$\{?PORT\}?/g,
29962
- String(repo.hostPort)
29963
- );
29823
+ const expandedStart = repo.start.replace(/\$\{?PORT\}?/g, String(repo.hostPort));
29964
29824
  const startCmd = `cd ${shellQuote2(repo.dir)} && exec ${expandedStart}`;
29965
- exec(
29966
- containerName,
29967
- `tmux new-window -t ${sessionName} -n ${repo.name} -d ${shellQuote2(startCmd)}`
29968
- );
29825
+ exec(containerName, `tmux new-window -t ${sessionName} -n ${repo.name} -d ${shellQuote2(startCmd)}`);
29969
29826
  windowsCreated.push(repo.name);
29970
29827
  }
29971
- const health = await Promise.all(
29972
- repos.map((repo) => probeOne(exec, containerName, repo, {
29973
- probeTimeoutMs,
29974
- probeIntervalMs,
29975
- clock,
29976
- sleep: sleep3
29977
- }))
29978
- );
29828
+ const health = await Promise.all(repos.map((repo) => probeOne(exec, containerName, repo, {
29829
+ probeTimeoutMs,
29830
+ probeIntervalMs,
29831
+ clock,
29832
+ sleep: sleep3
29833
+ })));
29979
29834
  return {
29980
29835
  sessionName,
29981
29836
  windowsCreated,
@@ -30014,7 +29869,7 @@ function shellQuote2(s) {
30014
29869
  return `'${s.replace(/'/g, `'\\''`)}'`;
30015
29870
  }
30016
29871
 
30017
- // ../core/src/world/manager.ts
29872
+ // ../core/dist/world/manager.js
30018
29873
  var BotIdentityError = class extends Error {
30019
29874
  constructor(message) {
30020
29875
  super(message);
@@ -30030,7 +29885,8 @@ function getTokenScopes(ghToken, _exec = execSync4) {
30030
29885
  });
30031
29886
  const m = out.match(/Token scopes:\s*(.+)/);
30032
29887
  const list = m?.[1];
30033
- if (!list) return [];
29888
+ if (!list)
29889
+ return [];
30034
29890
  return list.split(",").map((s) => s.trim().replace(/^['"]|['"]$/g, "")).filter((s) => s.length > 0);
30035
29891
  } catch {
30036
29892
  return [];
@@ -30051,19 +29907,16 @@ async function setupContainerGit(containerName, repos, branch) {
30051
29907
  const SAFE_BOT_NAME = /^[A-Za-z0-9 .,()@_+\-]+$/;
30052
29908
  const SAFE_BOT_EMAIL = /^[A-Za-z0-9._+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$/;
30053
29909
  if (!SAFE_BOT_NAME.test(actorName)) {
30054
- throw new BotIdentityError(
30055
- `OLAM_BOT_NAME contains unsafe characters: ${JSON.stringify(actorName)}. Allowed: alphanumeric + space + .,()@_+-. Shell metacharacters are rejected to prevent injection into the world container.`
30056
- );
29910
+ throw new BotIdentityError(`OLAM_BOT_NAME contains unsafe characters: ${JSON.stringify(actorName)}. Allowed: alphanumeric + space + .,()@_+-. Shell metacharacters are rejected to prevent injection into the world container.`);
30057
29911
  }
30058
29912
  if (!SAFE_BOT_EMAIL.test(actorEmail)) {
30059
- throw new BotIdentityError(
30060
- `OLAM_BOT_EMAIL is not a valid email or contains unsafe characters: ${JSON.stringify(actorEmail)}. Expected format: localpart@domain.tld with alphanumeric + ._+- only.`
30061
- );
29913
+ throw new BotIdentityError(`OLAM_BOT_EMAIL is not a valid email or contains unsafe characters: ${JSON.stringify(actorEmail)}. Expected format: localpart@domain.tld with alphanumeric + ._+- only.`);
30062
29914
  }
30063
29915
  if (ghToken) {
30064
29916
  for (const repo of repos) {
30065
29917
  const ghMatch = repo.url.match(/(?:git@github\.com:|github\.com\/)([^/]+\/[^.]+)/);
30066
- if (!ghMatch) continue;
29918
+ if (!ghMatch)
29919
+ continue;
30067
29920
  const ownerRepo = ghMatch[1];
30068
29921
  try {
30069
29922
  execSync4(`gh api repos/${ownerRepo} --silent`, {
@@ -30080,9 +29933,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
30080
29933
  }
30081
29934
  const tokenScopes = getTokenScopes(ghToken);
30082
29935
  if (tokenScopes.length > 0 && !tokenScopes.includes("workflow")) {
30083
- console.warn(
30084
- "[world] WARN: gh token is missing the `workflow` scope. Pushes that modify .github/workflows/* will be rejected by GitHub. If this world will touch CI files, run: `gh auth refresh -h github.com -s workflow` then re-spawn."
30085
- );
29936
+ console.warn("[world] WARN: gh token is missing the `workflow` scope. Pushes that modify .github/workflows/* will be rejected by GitHub. If this world will touch CI files, run: `gh auth refresh -h github.com -s workflow` then re-spawn.");
30086
29937
  }
30087
29938
  }
30088
29939
  for (const repo of repos) {
@@ -30115,10 +29966,8 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
30115
29966
  dockerExec(`gh auth setup-git`);
30116
29967
  } catch (err) {
30117
29968
  const msg = err instanceof Error ? err.message : String(err);
30118
- console.warn(
30119
- `[world] gh auth setup failed for ${containerName}: ${msg}
30120
- PR push from inside the world will not work. Operator must inject GH_TOKEN manually or run \`gh auth login\` inside the container.`
30121
- );
29969
+ console.warn(`[world] gh auth setup failed for ${containerName}: ${msg}
29970
+ PR push from inside the world will not work. Operator must inject GH_TOKEN manually or run \`gh auth login\` inside the container.`);
30122
29971
  } finally {
30123
29972
  if (tokenWritten) {
30124
29973
  try {
@@ -30142,10 +29991,7 @@ function makeHostExecFn() {
30142
29991
  function makeContainerExecFn(containerName) {
30143
29992
  return async (cmd) => {
30144
29993
  try {
30145
- const result = execSync4(
30146
- `docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`,
30147
- { stdio: "pipe", timeout: 6e5 }
30148
- );
29994
+ const result = execSync4(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
30149
29995
  return { stdout: result.toString(), stderr: "", exitCode: 0 };
30150
29996
  } catch (err) {
30151
29997
  const execErr = err;
@@ -30202,12 +30048,11 @@ function planManifestPipeline(repos, baselineServices, worldId, branch, portOffs
30202
30048
  const mergedServices = [...baselineServices];
30203
30049
  const existingNames = new Set(mergedServices.map((s) => s.name));
30204
30050
  for (const repo of repos) {
30205
- if (!repo.manifest?.services) continue;
30051
+ if (!repo.manifest?.services)
30052
+ continue;
30206
30053
  for (const [svcName, svcConf] of Object.entries(repo.manifest.services)) {
30207
30054
  if (existingNames.has(svcName)) {
30208
- console.warn(
30209
- `[manifest] step 2b service "${svcName}" from "${repo.name}" ignored (already declared by central or earlier manifest); first-write-wins`
30210
- );
30055
+ console.warn(`[manifest] step 2b service "${svcName}" from "${repo.name}" ignored (already declared by central or earlier manifest); first-write-wins`);
30211
30056
  continue;
30212
30057
  }
30213
30058
  mergedServices.push({
@@ -30217,79 +30062,63 @@ function planManifestPipeline(repos, baselineServices, worldId, branch, portOffs
30217
30062
  environment: svcConf.environment
30218
30063
  });
30219
30064
  existingNames.add(svcName);
30220
- console.log(
30221
- `[manifest] step 2b service "${svcName}" registered from "${repo.name}"`
30222
- );
30065
+ console.log(`[manifest] step 2b service "${svcName}" registered from "${repo.name}"`);
30223
30066
  }
30224
30067
  }
30225
30068
  const ctx = {
30226
- repos: Object.fromEntries(
30227
- repos.map((r) => [
30228
- r.name,
30229
- {
30230
- url: r.url,
30231
- ...r.path !== void 0 ? { path: r.path } : {},
30232
- ...r.manifest?.app?.port !== void 0 || r.app_port !== void 0 ? { port: r.manifest?.app?.port ?? r.app_port } : {},
30233
- branch
30234
- }
30235
- ])
30236
- ),
30237
- services: Object.fromEntries(
30238
- mergedServices.map((s) => [s.name, { port: s.port, host: s.name }])
30239
- ),
30069
+ repos: Object.fromEntries(repos.map((r) => [
30070
+ r.name,
30071
+ {
30072
+ url: r.url,
30073
+ ...r.path !== void 0 ? { path: r.path } : {},
30074
+ ...r.manifest?.app?.port !== void 0 || r.app_port !== void 0 ? { port: r.manifest?.app?.port ?? r.app_port } : {},
30075
+ branch
30076
+ }
30077
+ ])),
30078
+ services: Object.fromEntries(mergedServices.map((s) => [s.name, { port: s.port, host: s.name }])),
30240
30079
  world: { id: worldId, branch, portOffset },
30241
30080
  env: process.env
30242
30081
  };
30243
30082
  const crossRepoEnv = {};
30244
30083
  for (const repo of repos) {
30245
- if (!repo.manifest?.env) continue;
30084
+ if (!repo.manifest?.env)
30085
+ continue;
30246
30086
  try {
30247
- const { env: resolvedEnv, warnings } = resolveManifestEnv(
30248
- repo.manifest.env,
30249
- ctx
30250
- );
30087
+ const { env: resolvedEnv, warnings } = resolveManifestEnv(repo.manifest.env, ctx);
30251
30088
  crossRepoEnv[repo.name] = resolvedEnv;
30252
30089
  for (const w of warnings) {
30253
30090
  console.warn(`[manifest] step 2c env warning for "${repo.name}": ${w}`);
30254
30091
  }
30255
- console.log(
30256
- `[manifest] step 2c env resolved for "${repo.name}" (${Object.keys(resolvedEnv).length} keys)`
30257
- );
30092
+ console.log(`[manifest] step 2c env resolved for "${repo.name}" (${Object.keys(resolvedEnv).length} keys)`);
30258
30093
  } catch (err) {
30259
30094
  if (err instanceof EnvSubstCycleError || err instanceof EnvSubstDepthExceededError) {
30260
30095
  throw err;
30261
30096
  }
30262
30097
  const msg = err instanceof Error ? err.message : String(err);
30263
- console.warn(
30264
- `[manifest] step 2c env resolution failed for "${repo.name}": ${msg}`
30265
- );
30098
+ console.warn(`[manifest] step 2c env resolution failed for "${repo.name}": ${msg}`);
30266
30099
  }
30267
30100
  }
30268
30101
  return { services: mergedServices, crossRepoEnv };
30269
30102
  }
30270
30103
  async function runManifestRuntime(containerName, worldId, repos, exec) {
30271
30104
  const hasAnyManifest = repos.some((r) => r.manifest !== void 0);
30272
- if (!hasAnyManifest) return {};
30105
+ if (!hasAnyManifest)
30106
+ return {};
30273
30107
  const bootstrapTasks = [];
30274
30108
  for (const repo of repos) {
30275
30109
  const bootstrap = repo.manifest?.bootstrap;
30276
- if (!bootstrap || bootstrap.length === 0) continue;
30110
+ if (!bootstrap || bootstrap.length === 0)
30111
+ continue;
30277
30112
  if (repo.setup_commands.length > 0) {
30278
- console.warn(
30279
- `[manifest] step 4e' both bootstrap[] and setup_commands populated for "${repo.name}". HARD-STOP semantics apply to bootstrap[] (OQ9): if any bootstrap step exits non-zero, the world transitions to 'error' and the legacy setup_commands path will NOT run as a fallback. Migrate setup_commands \u2192 manifest.bootstrap and remove the duplicate.`
30280
- );
30113
+ console.warn(`[manifest] step 4e' both bootstrap[] and setup_commands populated for "${repo.name}". HARD-STOP semantics apply to bootstrap[] (OQ9): if any bootstrap step exits non-zero, the world transitions to 'error' and the legacy setup_commands path will NOT run as a fallback. Migrate setup_commands \u2192 manifest.bootstrap and remove the duplicate.`);
30281
30114
  }
30282
30115
  const workdir = `/home/olam/workspace/${repo.name}`;
30283
30116
  const cmds = bootstrap.map(bootstrapStepCmd);
30284
- console.log(
30285
- `[manifest] step 4e bootstrap "${repo.name}" (${cmds.length} steps)`
30286
- );
30287
- bootstrapTasks.push(
30288
- (async () => {
30289
- await runBootstrap(containerName, workdir, cmds, exec);
30290
- console.log(`[manifest] step 4e bootstrap "${repo.name}" complete`);
30291
- })()
30292
- );
30117
+ console.log(`[manifest] step 4e bootstrap "${repo.name}" (${cmds.length} steps)`);
30118
+ bootstrapTasks.push((async () => {
30119
+ await runBootstrap(containerName, workdir, cmds, exec);
30120
+ console.log(`[manifest] step 4e bootstrap "${repo.name}" complete`);
30121
+ })());
30293
30122
  }
30294
30123
  if (bootstrapTasks.length > 0) {
30295
30124
  const results = await Promise.allSettled(bootstrapTasks);
@@ -30301,12 +30130,11 @@ async function runManifestRuntime(containerName, worldId, repos, exec) {
30301
30130
  const supervisedRepos = [];
30302
30131
  for (const repo of repos) {
30303
30132
  const start = repo.manifest?.start;
30304
- if (!start) continue;
30133
+ if (!start)
30134
+ continue;
30305
30135
  const hostPort = repo.manifest?.app?.port ?? repo.app_port ?? 0;
30306
30136
  if (!Number.isInteger(hostPort) || hostPort < 1) {
30307
- console.warn(
30308
- `[manifest] step 4g skipping "${repo.name}" \u2014 no app.port (got ${hostPort})`
30309
- );
30137
+ console.warn(`[manifest] step 4g skipping "${repo.name}" \u2014 no app.port (got ${hostPort})`);
30310
30138
  continue;
30311
30139
  }
30312
30140
  supervisedRepos.push({
@@ -30317,19 +30145,11 @@ async function runManifestRuntime(containerName, worldId, repos, exec) {
30317
30145
  manifestPath: repo.path ? `${repo.path}/.olam.yaml or ${repo.path}/.adb.yaml` : `<unknown manifest path for ${repo.name}>`
30318
30146
  });
30319
30147
  }
30320
- if (supervisedRepos.length === 0) return {};
30321
- console.log(
30322
- `[manifest] step 4f port pre-flight (${supervisedRepos.length} repos)`
30323
- );
30324
- const supervisor = await startSupervisedApps(
30325
- containerName,
30326
- worldId,
30327
- supervisedRepos,
30328
- exec
30329
- );
30330
- console.log(
30331
- `[manifest] step 4g tmux supervisor session=${supervisor.sessionName} created=${supervisor.windowsCreated.length} existing=${supervisor.windowsExisting.length}`
30332
- );
30148
+ if (supervisedRepos.length === 0)
30149
+ return {};
30150
+ console.log(`[manifest] step 4f port pre-flight (${supervisedRepos.length} repos)`);
30151
+ const supervisor = await startSupervisedApps(containerName, worldId, supervisedRepos, exec);
30152
+ console.log(`[manifest] step 4g tmux supervisor session=${supervisor.sessionName} created=${supervisor.windowsCreated.length} existing=${supervisor.windowsExisting.length}`);
30333
30153
  return { supervisor };
30334
30154
  }
30335
30155
  var ADJECTIVES = ["amber", "blue", "coral", "dawn", "ember", "frost", "gold", "haze", "iron", "jade"];
@@ -30341,28 +30161,29 @@ function generateWorldId() {
30341
30161
  return `${adj}-${noun}-${num}`;
30342
30162
  }
30343
30163
  var AuthPreflightError = class extends Error {
30164
+ verdict;
30165
+ remedy;
30344
30166
  constructor(verdict, message, remedy) {
30345
30167
  super(message);
30346
30168
  this.verdict = verdict;
30347
30169
  this.remedy = remedy;
30348
30170
  this.name = "AuthPreflightError";
30349
30171
  }
30350
- verdict;
30351
- remedy;
30352
30172
  };
30353
30173
  var WorkspaceNotFoundError = class extends Error {
30174
+ workspaceName;
30354
30175
  constructor(workspaceName) {
30355
30176
  super(`Workspace "${workspaceName}" not found \u2014 run \`olam workspace add ${workspaceName}\` first, or check the name.`);
30356
30177
  this.workspaceName = workspaceName;
30357
30178
  this.name = "WorkspaceNotFoundError";
30358
30179
  }
30359
- workspaceName;
30360
30180
  };
30361
30181
  function buildManifestRuntime(worldId, repos) {
30362
30182
  const runtimeRepos = [];
30363
30183
  for (const repo of repos) {
30364
30184
  const m = repo.manifest;
30365
- if (!m) continue;
30185
+ if (!m)
30186
+ continue;
30366
30187
  const services = {};
30367
30188
  for (const [name, svc] of Object.entries(m.services ?? {})) {
30368
30189
  services[name] = {
@@ -30383,6 +30204,13 @@ function buildManifestRuntime(worldId, repos) {
30383
30204
  return { worldId, repos: runtimeRepos };
30384
30205
  }
30385
30206
  var WorldManager = class {
30207
+ config;
30208
+ provider;
30209
+ registry;
30210
+ dashboardManager;
30211
+ pleriClient;
30212
+ dockerExec;
30213
+ manifestRuntimes = /* @__PURE__ */ new Map();
30386
30214
  constructor(config2, provider, registry2, dashboardManager, pleriClient, dockerExec) {
30387
30215
  this.config = config2;
30388
30216
  this.provider = provider;
@@ -30391,13 +30219,6 @@ var WorldManager = class {
30391
30219
  this.pleriClient = pleriClient;
30392
30220
  this.dockerExec = dockerExec ?? defaultDockerExec();
30393
30221
  }
30394
- config;
30395
- provider;
30396
- registry;
30397
- dashboardManager;
30398
- pleriClient;
30399
- dockerExec;
30400
- manifestRuntimes = /* @__PURE__ */ new Map();
30401
30222
  // -----------------------------------------------------------------------
30402
30223
  // createWorld
30403
30224
  // -----------------------------------------------------------------------
@@ -30463,10 +30284,12 @@ var WorldManager = class {
30463
30284
  ".env.test.local"
30464
30285
  ];
30465
30286
  for (const repo of repos) {
30466
- if (!repo.path) continue;
30287
+ if (!repo.path)
30288
+ continue;
30467
30289
  const sourceRoot = repo.path.replace(/^~/, os8.homedir());
30468
30290
  const worktreeRoot = path18.join(workspacePath, repo.name);
30469
- if (!fs14.existsSync(sourceRoot) || !fs14.existsSync(worktreeRoot)) continue;
30291
+ if (!fs14.existsSync(sourceRoot) || !fs14.existsSync(worktreeRoot))
30292
+ continue;
30470
30293
  let copied = 0;
30471
30294
  for (const pattern of RUNTIME_FILE_PATTERNS) {
30472
30295
  const matches2 = [];
@@ -30477,7 +30300,8 @@ var WorldManager = class {
30477
30300
  const ext = glob.replace(/^\*+/, "");
30478
30301
  try {
30479
30302
  for (const entry of fs14.readdirSync(sourceDir)) {
30480
- if (ext === "" || entry.endsWith(ext)) matches2.push(path18.join(dir, entry));
30303
+ if (ext === "" || entry.endsWith(ext))
30304
+ matches2.push(path18.join(dir, entry));
30481
30305
  }
30482
30306
  } catch {
30483
30307
  }
@@ -30490,7 +30314,8 @@ var WorldManager = class {
30490
30314
  const dst = path18.join(worktreeRoot, rel);
30491
30315
  try {
30492
30316
  const st = fs14.statSync(src);
30493
- if (!st.isFile()) continue;
30317
+ if (!st.isFile())
30318
+ continue;
30494
30319
  fs14.mkdirSync(path18.dirname(dst), { recursive: true });
30495
30320
  fs14.copyFileSync(src, dst);
30496
30321
  copied++;
@@ -30514,13 +30339,7 @@ var WorldManager = class {
30514
30339
  console.warn(`[manifest] worktree manifest discovery failed (non-fatal): ${msg}`);
30515
30340
  }
30516
30341
  const baselineServices = this.resolveServices(enrichedRepos);
30517
- const { services, crossRepoEnv } = planManifestPipeline(
30518
- enrichedRepos,
30519
- baselineServices,
30520
- worldId,
30521
- branch,
30522
- portOffset
30523
- );
30342
+ const { services, crossRepoEnv } = planManifestPipeline(enrichedRepos, baselineServices, worldId, branch, portOffset);
30524
30343
  this.manifestRuntimes.set(worldId, buildManifestRuntime(worldId, enrichedRepos));
30525
30344
  const serviceEnv = {};
30526
30345
  for (const svc of services) {
@@ -30623,17 +30442,13 @@ var WorldManager = class {
30623
30442
  if (selected) {
30624
30443
  selectedImage = selected.image;
30625
30444
  cacheArchOverride = selected.cacheArch;
30626
- console.log(
30627
- `[WorldManager] image_selector matched \u2014 using ${selected.image} (tag=${selected.tag}${selected.cacheArch ? `, cache_arch=${selected.cacheArch}` : ""})`
30628
- );
30445
+ console.log(`[WorldManager] image_selector matched \u2014 using ${selected.image} (tag=${selected.tag}${selected.cacheArch ? `, cache_arch=${selected.cacheArch}` : ""})`);
30629
30446
  } else {
30630
30447
  const hasRailsRepo = repos.some((r) => r.type === "rails");
30631
30448
  if (hasRailsRepo) {
30632
30449
  selectedImage = resolveDevboxImage(this.config, "amd64");
30633
30450
  cacheArchOverride = "x64";
30634
- console.log(
30635
- `[WorldManager] Rails repo detected \u2014 using ${selectedImage} + x64 mise-cache (Rosetta path)`
30636
- );
30451
+ console.log(`[WorldManager] Rails repo detected \u2014 using ${selectedImage} + x64 mise-cache (Rosetta path)`);
30637
30452
  }
30638
30453
  }
30639
30454
  }
@@ -30652,18 +30467,24 @@ var WorldManager = class {
30652
30467
  });
30653
30468
  try {
30654
30469
  const worldEnv = {};
30655
- if (opts.task) worldEnv.OLAM_TASK = opts.task;
30470
+ if (opts.task)
30471
+ worldEnv.OLAM_TASK = opts.task;
30656
30472
  const r2CredsPath = path18.join(os8.homedir(), ".olam", "r2-credentials.json");
30657
30473
  if (fs14.existsSync(r2CredsPath)) {
30658
30474
  try {
30659
30475
  const r2Raw = fs14.readFileSync(r2CredsPath, "utf-8").trim();
30660
30476
  if (r2Raw.length > 0) {
30661
30477
  const r2 = JSON.parse(r2Raw);
30662
- if (typeof r2.account_id === "string") worldEnv.OLAM_R2_ACCOUNT_ID = r2.account_id;
30663
- if (typeof r2.bucket === "string") worldEnv.OLAM_R2_BUCKET = r2.bucket;
30664
- if (typeof r2.access_key_id === "string") worldEnv.OLAM_R2_ACCESS_KEY_ID = r2.access_key_id;
30665
- if (typeof r2.secret_access_key === "string") worldEnv.OLAM_R2_SECRET_ACCESS_KEY = r2.secret_access_key;
30666
- if (typeof r2.public_url_base === "string") worldEnv.OLAM_R2_PUBLIC_URL_BASE = r2.public_url_base;
30478
+ if (typeof r2.account_id === "string")
30479
+ worldEnv.OLAM_R2_ACCOUNT_ID = r2.account_id;
30480
+ if (typeof r2.bucket === "string")
30481
+ worldEnv.OLAM_R2_BUCKET = r2.bucket;
30482
+ if (typeof r2.access_key_id === "string")
30483
+ worldEnv.OLAM_R2_ACCESS_KEY_ID = r2.access_key_id;
30484
+ if (typeof r2.secret_access_key === "string")
30485
+ worldEnv.OLAM_R2_SECRET_ACCESS_KEY = r2.secret_access_key;
30486
+ if (typeof r2.public_url_base === "string")
30487
+ worldEnv.OLAM_R2_PUBLIC_URL_BASE = r2.public_url_base;
30667
30488
  }
30668
30489
  } catch {
30669
30490
  }
@@ -30676,7 +30497,8 @@ var WorldManager = class {
30676
30497
  const parsed = YAML3.parse(keysRaw);
30677
30498
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
30678
30499
  for (const [k, v] of Object.entries(parsed)) {
30679
- if (typeof v !== "string") continue;
30500
+ if (typeof v !== "string")
30501
+ continue;
30680
30502
  const envKey = `OLAM_LLM_${k.toUpperCase()}`;
30681
30503
  if (!(envKey in worldEnv)) {
30682
30504
  worldEnv[envKey] = v;
@@ -30692,14 +30514,14 @@ var WorldManager = class {
30692
30514
  const seenFromRepo = /* @__PURE__ */ new Map();
30693
30515
  for (const repo of repos) {
30694
30516
  const repoEnv = crossRepoEnv[repo.name];
30695
- if (!repoEnv) continue;
30517
+ if (!repoEnv)
30518
+ continue;
30696
30519
  for (const [k, v] of Object.entries(repoEnv)) {
30697
- if (PROTECTED_ENV_KEY_SET.has(k)) continue;
30520
+ if (PROTECTED_ENV_KEY_SET.has(k))
30521
+ continue;
30698
30522
  const prevRepo = seenFromRepo.get(k);
30699
30523
  if (prevRepo !== void 0) {
30700
- console.warn(
30701
- `[manifest] cross-repo env collision on "${k}": "${prevRepo}" wins over "${repo.name}" (iteration order)`
30702
- );
30524
+ console.warn(`[manifest] cross-repo env collision on "${k}": "${prevRepo}" wins over "${repo.name}" (iteration order)`);
30703
30525
  continue;
30704
30526
  }
30705
30527
  worldEnv[k] = v;
@@ -30713,7 +30535,8 @@ var WorldManager = class {
30713
30535
  console.warn(`[secrets] ignoring "${k}" from GCP secret \u2014 OLAM_* keys are protected`);
30714
30536
  continue;
30715
30537
  }
30716
- if (!(k in worldEnv)) worldEnv[k] = v;
30538
+ if (!(k in worldEnv))
30539
+ worldEnv[k] = v;
30717
30540
  }
30718
30541
  for (const { repoName, relativePath, content } of fileWrites) {
30719
30542
  const absPath = path18.join(workspacePath, repoName, relativePath);
@@ -30773,7 +30596,8 @@ var WorldManager = class {
30773
30596
  try {
30774
30597
  await setupContainerGit(containerName, repos, branch);
30775
30598
  } catch (err) {
30776
- if (err instanceof BotIdentityError) throw err;
30599
+ if (err instanceof BotIdentityError)
30600
+ throw err;
30777
30601
  const msg = err instanceof Error ? err.message : String(err);
30778
30602
  console.warn(`[WorldManager] container git setup failed: ${msg}`);
30779
30603
  }
@@ -30829,12 +30653,8 @@ var WorldManager = class {
30829
30653
  } catch (err) {
30830
30654
  if (opts.allowBootstrapFailure && err instanceof BootstrapStepError) {
30831
30655
  const msg = err instanceof Error ? err.message : String(err);
30832
- console.warn(
30833
- `[manifest] WARN: bootstrap failure allowed by --allow-bootstrap-failure: ${msg}`
30834
- );
30835
- console.warn(
30836
- `[manifest] WARN: world ${worldId} stays running; rerun the failing step manually inside the world if needed.`
30837
- );
30656
+ console.warn(`[manifest] WARN: bootstrap failure allowed by --allow-bootstrap-failure: ${msg}`);
30657
+ console.warn(`[manifest] WARN: world ${worldId} stays running; rerun the failing step manually inside the world if needed.`);
30838
30658
  } else if (err instanceof BootstrapStepError || err instanceof PortInUseError || err instanceof EnvSubstCycleError || err instanceof EnvSubstDepthExceededError) {
30839
30659
  sm.transition("error");
30840
30660
  this.registry.update(worldId, { status: "error" });
@@ -30857,10 +30677,7 @@ var WorldManager = class {
30857
30677
  const escapedDir = `/home/olam/workspace/${repo.name.replace(/["$`\\]/g, "\\$&")}`;
30858
30678
  for (const cmd of repo.setup_commands) {
30859
30679
  try {
30860
- execSync4(
30861
- `docker exec ${containerName} sh -c 'cd "${escapedDir}" && ${cmd.replace(/'/g, "'\\''")}'`,
30862
- { stdio: "pipe", timeout: 6e5 }
30863
- );
30680
+ execSync4(`docker exec ${containerName} sh -c 'cd "${escapedDir}" && ${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
30864
30681
  } catch (err) {
30865
30682
  const msg = err instanceof Error ? err.message : String(err);
30866
30683
  console.warn(`[WorldManager] setup command failed for ${repo.name}: ${msg}`);
@@ -30870,10 +30687,7 @@ var WorldManager = class {
30870
30687
  }
30871
30688
  if (credentialsInjected.claude) {
30872
30689
  try {
30873
- execSync4(
30874
- `docker exec ${containerName} curl -sf -X POST http://localhost:8080/session/start-agent 2>/dev/null || true`,
30875
- { stdio: "pipe", timeout: 45e3 }
30876
- );
30690
+ execSync4(`docker exec ${containerName} curl -sf -X POST http://localhost:8080/session/start-agent 2>/dev/null || true`, { stdio: "pipe", timeout: 45e3 });
30877
30691
  } catch {
30878
30692
  }
30879
30693
  if (opts.task) {
@@ -30885,7 +30699,8 @@ var WorldManager = class {
30885
30699
  });
30886
30700
  const seen = /* @__PURE__ */ new Set();
30887
30701
  const uniquePolicies = allPolicies.filter((p) => {
30888
- if (seen.has(p.id)) return false;
30702
+ if (seen.has(p.id))
30703
+ return false;
30889
30704
  seen.add(p.id);
30890
30705
  return true;
30891
30706
  });
@@ -30893,17 +30708,11 @@ var WorldManager = class {
30893
30708
  const brief = formatPoliciesBrief(uniquePolicies);
30894
30709
  taskWithPolicies = `${brief}## Your task
30895
30710
  ${opts.task}`;
30896
- execSync4(
30897
- `docker exec ${containerName} mkdir -p /home/olam/.olam/policies`,
30898
- { stdio: "pipe", timeout: 1e4 }
30899
- );
30711
+ execSync4(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
30900
30712
  for (const repo of repos) {
30901
30713
  const policiesDir = path18.join(workspacePath, repo.name, ".olam", "policies");
30902
30714
  if (fs14.existsSync(policiesDir)) {
30903
- execSync4(
30904
- `docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`,
30905
- { stdio: "pipe", timeout: 15e3 }
30906
- );
30715
+ execSync4(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
30907
30716
  }
30908
30717
  }
30909
30718
  }
@@ -30913,10 +30722,7 @@ ${opts.task}`;
30913
30722
  }
30914
30723
  try {
30915
30724
  const payload = JSON.stringify({ prompt: taskWithPolicies }).replace(/'/g, "'\\''");
30916
- execSync4(
30917
- `docker exec ${containerName} curl -sf -X POST -H 'Content-Type: application/json' -d '${payload}' http://localhost:8080/dispatch 2>/dev/null || true`,
30918
- { stdio: "pipe", timeout: 3e4 }
30919
- );
30725
+ execSync4(`docker exec ${containerName} curl -sf -X POST -H 'Content-Type: application/json' -d '${payload}' http://localhost:8080/dispatch 2>/dev/null || true`, { stdio: "pipe", timeout: 3e4 });
30920
30726
  console.log("[world] Task auto-dispatched");
30921
30727
  } catch {
30922
30728
  }
@@ -30985,7 +30791,11 @@ ${opts.task}`;
30985
30791
  }
30986
30792
  try {
30987
30793
  fs14.rmSync(world.workspacePath, { recursive: true, force: true });
30988
- } catch {
30794
+ if (fs14.existsSync(world.workspacePath)) {
30795
+ console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
30796
+ }
30797
+ } catch (err) {
30798
+ console.warn(`[WorldManager] destroyWorld(${worldId}): failed to remove ${world.workspacePath}: ${err instanceof Error ? err.message : String(err)}. Run \`olam clean --apply\` to reap.`);
30989
30799
  }
30990
30800
  for (const repo of repos) {
30991
30801
  try {
@@ -31000,7 +30810,8 @@ ${opts.task}`;
31000
30810
  // -----------------------------------------------------------------------
31001
30811
  async pauseWorld(worldId) {
31002
30812
  const world = this.registry.get(worldId);
31003
- if (!world) throw new Error(`World "${worldId}" not found`);
30813
+ if (!world)
30814
+ throw new Error(`World "${worldId}" not found`);
31004
30815
  const sm = new WorldStateMachine(worldId, world.status);
31005
30816
  sm.transition("paused");
31006
30817
  if (this.provider.pauseWorld) {
@@ -31010,7 +30821,8 @@ ${opts.task}`;
31010
30821
  }
31011
30822
  async resumeWorld(worldId) {
31012
30823
  const world = this.registry.get(worldId);
31013
- if (!world) throw new Error(`World "${worldId}" not found`);
30824
+ if (!world)
30825
+ throw new Error(`World "${worldId}" not found`);
31014
30826
  const sm = new WorldStateMachine(worldId, world.status);
31015
30827
  sm.transition("running");
31016
30828
  if (this.provider.resumeWorld) {
@@ -31042,7 +30854,8 @@ ${opts.task}`;
31042
30854
  }
31043
30855
  if (opts.workspace) {
31044
30856
  const ws = readWorkspace(opts.workspace);
31045
- if (!ws) throw new WorkspaceNotFoundError(opts.workspace);
30857
+ if (!ws)
30858
+ throw new WorkspaceNotFoundError(opts.workspace);
31046
30859
  return workspaceToRepoConfigs(ws);
31047
30860
  }
31048
30861
  return this.resolveRepos(void 0);
@@ -31066,7 +30879,8 @@ ${opts.task}`;
31066
30879
  const planContent = fs14.readFileSync(planFilePath, "utf-8");
31067
30880
  const planFileName = path18.basename(planFilePath);
31068
30881
  const targetRepo = repoNames[0];
31069
- if (!targetRepo) return;
30882
+ if (!targetRepo)
30883
+ return;
31070
30884
  const plansDir = path18.join(workspacePath, targetRepo, "docs", "plans");
31071
30885
  fs14.mkdirSync(plansDir, { recursive: true });
31072
30886
  fs14.writeFileSync(path18.join(plansDir, planFileName), planContent);
@@ -31090,13 +30904,13 @@ ${opts.task}`;
31090
30904
  }
31091
30905
  };
31092
30906
 
31093
- // ../core/src/cost/tracker.ts
30907
+ // ../core/dist/cost/tracker.js
31094
30908
  var CostTracker = class {
30909
+ budgetConfig;
30910
+ records = [];
31095
30911
  constructor(budgetConfig) {
31096
30912
  this.budgetConfig = budgetConfig;
31097
30913
  }
31098
- budgetConfig;
31099
- records = [];
31100
30914
  // ── Mutations ────────────────────────────────────────────────────────────
31101
30915
  record(entry) {
31102
30916
  this.records.push(entry);
@@ -31139,26 +30953,29 @@ var CostTracker = class {
31139
30953
  }
31140
30954
  };
31141
30955
  function deriveStatus(percentUsed, warningThreshold) {
31142
- if (percentUsed >= 1) return "exceeded";
31143
- if (percentUsed >= warningThreshold) return "warning";
30956
+ if (percentUsed >= 1)
30957
+ return "exceeded";
30958
+ if (percentUsed >= warningThreshold)
30959
+ return "warning";
31144
30960
  return "ok";
31145
30961
  }
31146
30962
  function todayIsoPrefix() {
31147
30963
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
31148
30964
  }
31149
30965
 
31150
- // ../core/src/dashboard/index.ts
31151
- import "node:http";
30966
+ // ../core/dist/dashboard/index.js
30967
+ import * as http2 from "node:http";
31152
30968
 
31153
- // ../core/src/dashboard/server.ts
30969
+ // ../core/dist/dashboard/server.js
31154
30970
  import * as http from "node:http";
31155
30971
  import * as fs15 from "node:fs";
31156
30972
  import * as path19 from "node:path";
31157
30973
  import { fileURLToPath as fileURLToPath2 } from "node:url";
31158
30974
 
31159
- // ../core/src/dashboard/serialize.ts
30975
+ // ../core/dist/dashboard/serialize.js
31160
30976
  function serializeTokenUsage(usage) {
31161
- if (!usage) return void 0;
30977
+ if (!usage)
30978
+ return void 0;
31162
30979
  return {
31163
30980
  input_tokens: usage.inputTokens,
31164
30981
  output_tokens: usage.outputTokens,
@@ -31201,20 +31018,26 @@ function parsePsAux(stdout) {
31201
31018
  const result = [];
31202
31019
  for (const line of dataLines) {
31203
31020
  const trimmed = line.trim();
31204
- if (!trimmed) continue;
31021
+ if (!trimmed)
31022
+ continue;
31205
31023
  const parts = trimmed.split(/\s+/);
31206
- if (parts.length < 11) continue;
31024
+ if (parts.length < 11)
31025
+ continue;
31207
31026
  const pid = parseInt(parts[1], 10);
31208
- if (isNaN(pid)) continue;
31027
+ if (isNaN(pid))
31028
+ continue;
31209
31029
  const cpuPercent = parseFloat(parts[2]) || 0;
31210
31030
  const rssKb = parseInt(parts[5], 10) || 0;
31211
31031
  const stat = parts[7] ?? "";
31212
31032
  const command = parts.slice(10).join(" ");
31213
31033
  const name = command.split(/\s/)[0]?.split("/").pop() ?? command;
31214
31034
  let status = "running";
31215
- if (stat.startsWith("T")) status = "stopped";
31216
- else if (stat.startsWith("Z")) status = "error";
31217
- else if (stat.startsWith("S") && cpuPercent === 0) status = "idle";
31035
+ if (stat.startsWith("T"))
31036
+ status = "stopped";
31037
+ else if (stat.startsWith("Z"))
31038
+ status = "error";
31039
+ else if (stat.startsWith("S") && cpuPercent === 0)
31040
+ status = "idle";
31218
31041
  result.push({
31219
31042
  pid,
31220
31043
  name,
@@ -31311,7 +31134,7 @@ function serializeGanttTimeline(timeline) {
31311
31134
  };
31312
31135
  }
31313
31136
 
31314
- // ../core/src/dashboard/session-aggregator.ts
31137
+ // ../core/dist/dashboard/session-aggregator.js
31315
31138
  function sumTokenUsage(nodes) {
31316
31139
  let hasAny = false;
31317
31140
  let inputTokens = 0;
@@ -31319,28 +31142,33 @@ function sumTokenUsage(nodes) {
31319
31142
  let cacheCreation = 0;
31320
31143
  let cacheRead = 0;
31321
31144
  for (const node of nodes) {
31322
- if (!node.tokenUsage) continue;
31145
+ if (!node.tokenUsage)
31146
+ continue;
31323
31147
  hasAny = true;
31324
31148
  inputTokens += node.tokenUsage.inputTokens;
31325
31149
  outputTokens += node.tokenUsage.outputTokens;
31326
31150
  cacheCreation += node.tokenUsage.cacheCreationInputTokens ?? 0;
31327
31151
  cacheRead += node.tokenUsage.cacheReadInputTokens ?? 0;
31328
31152
  }
31329
- if (!hasAny) return null;
31153
+ if (!hasAny)
31154
+ return null;
31330
31155
  return { inputTokens, outputTokens, cacheCreationInputTokens: cacheCreation, cacheReadInputTokens: cacheRead };
31331
31156
  }
31332
31157
  function inferSessionStatus(nodes, lastAt) {
31333
31158
  for (const n of nodes) {
31334
- if (n.nodeType === "lifecycle" && n.hookEventName === "Stop") return "completed";
31159
+ if (n.nodeType === "lifecycle" && n.hookEventName === "Stop")
31160
+ return "completed";
31335
31161
  }
31336
31162
  const lastMs = new Date(lastAt).getTime();
31337
31163
  const fiveMinAgo = Date.now() - 5 * 60 * 1e3;
31338
- if (lastMs > fiveMinAgo) return "running";
31164
+ if (lastMs > fiveMinAgo)
31165
+ return "running";
31339
31166
  return "idle";
31340
31167
  }
31341
31168
  function deriveSessionTitle(nodes) {
31342
31169
  for (const n of nodes) {
31343
- if (n.nodeType === "intent" && n.summary) return n.summary.slice(0, 100);
31170
+ if (n.nodeType === "intent" && n.summary)
31171
+ return n.summary.slice(0, 100);
31344
31172
  }
31345
31173
  for (const n of nodes) {
31346
31174
  if (n.nodeType === "lifecycle" && n.hookEventName === "SessionStart") {
@@ -31352,13 +31180,16 @@ function deriveSessionTitle(nodes) {
31352
31180
  function countFilesModified(nodes) {
31353
31181
  const files = /* @__PURE__ */ new Set();
31354
31182
  for (const node of nodes) {
31355
- if (node.nodeType !== "action") continue;
31183
+ if (node.nodeType !== "action")
31184
+ continue;
31356
31185
  const content = node.content;
31357
31186
  const toolName = content.tool_name;
31358
- if (toolName !== "Write" && toolName !== "Edit") continue;
31187
+ if (toolName !== "Write" && toolName !== "Edit")
31188
+ continue;
31359
31189
  const toolInput = content.tool_input;
31360
31190
  const filePath = toolInput?.file_path;
31361
- if (filePath) files.add(filePath);
31191
+ if (filePath)
31192
+ files.add(filePath);
31362
31193
  }
31363
31194
  return files.size;
31364
31195
  }
@@ -31452,7 +31283,7 @@ function buildWorldTimeline(sessions) {
31452
31283
  };
31453
31284
  }
31454
31285
 
31455
- // ../core/src/dashboard/server.ts
31286
+ // ../core/dist/dashboard/server.js
31456
31287
  var MIME = {
31457
31288
  ".html": "text/html; charset=utf-8",
31458
31289
  ".js": "application/javascript; charset=utf-8",
@@ -31473,7 +31304,8 @@ function notFound(res) {
31473
31304
  }
31474
31305
  function openThoughtStore(workspacePath) {
31475
31306
  const dbPath = getWorldDbPath(workspacePath);
31476
- if (!fs15.existsSync(dbPath)) return null;
31307
+ if (!fs15.existsSync(dbPath))
31308
+ return null;
31477
31309
  return new ThoughtLocalStore(dbPath);
31478
31310
  }
31479
31311
  function handleGetWorlds(registry2) {
@@ -31509,7 +31341,8 @@ function handleGetWorlds(registry2) {
31509
31341
  }
31510
31342
  function handleGetWorld(registry2, worldId) {
31511
31343
  const w = registry2.get(worldId);
31512
- if (!w) return null;
31344
+ if (!w)
31345
+ return null;
31513
31346
  let nodeCount = 0;
31514
31347
  let edgeCount = 0;
31515
31348
  let sessionCount = 0;
@@ -31537,8 +31370,10 @@ function handleGetWorld(registry2, worldId) {
31537
31370
  latencyCount += 1;
31538
31371
  }
31539
31372
  }
31540
- if (tokenSum > 0) totalTokens = tokenSum;
31541
- if (latencyCount > 0) avgLatencyMs = Math.round(latencySum / latencyCount);
31373
+ if (tokenSum > 0)
31374
+ totalTokens = tokenSum;
31375
+ if (latencyCount > 0)
31376
+ avgLatencyMs = Math.round(latencySum / latencyCount);
31542
31377
  } finally {
31543
31378
  store.close();
31544
31379
  }
@@ -31560,7 +31395,8 @@ function handleGetWorld(registry2, worldId) {
31560
31395
  }
31561
31396
  function handleGetThoughts(registry2, worldId) {
31562
31397
  const w = registry2.get(worldId);
31563
- if (!w) return null;
31398
+ if (!w)
31399
+ return null;
31564
31400
  const store = openThoughtStore(w.workspacePath);
31565
31401
  if (!store) {
31566
31402
  return { nodes: [], edges: [] };
@@ -31609,10 +31445,12 @@ function handleGetCostsByWorld(registry2, worldId) {
31609
31445
  function findSessionNodes(registry2, sessionId) {
31610
31446
  for (const w of registry2.list()) {
31611
31447
  const store = openThoughtStore(w.workspacePath);
31612
- if (!store) continue;
31448
+ if (!store)
31449
+ continue;
31613
31450
  try {
31614
31451
  const nodes = store.getNodesBySession(sessionId);
31615
- if (nodes.length > 0) return { worldId: w.id, nodes };
31452
+ if (nodes.length > 0)
31453
+ return { worldId: w.id, nodes };
31616
31454
  } finally {
31617
31455
  store.close();
31618
31456
  }
@@ -31622,11 +31460,13 @@ function findSessionNodes(registry2, sessionId) {
31622
31460
  function findSessionInWorld(registry2, sessionId) {
31623
31461
  for (const w of registry2.list()) {
31624
31462
  const store = openThoughtStore(w.workspacePath);
31625
- if (!store) continue;
31463
+ if (!store)
31464
+ continue;
31626
31465
  try {
31627
31466
  const sessions = aggregateSessions(store, w.id);
31628
31467
  const found = sessions.find((s) => s.id === sessionId);
31629
- if (found) return found;
31468
+ if (found)
31469
+ return found;
31630
31470
  } finally {
31631
31471
  store.close();
31632
31472
  }
@@ -31669,13 +31509,15 @@ function createDashboardServer(opts) {
31669
31509
  }
31670
31510
  if (pathname === "/api/world" && req.method === "GET" && scopedWorldId) {
31671
31511
  const data = handleGetWorld(registry2, scopedWorldId);
31672
- if (!data) return notFound(res);
31512
+ if (!data)
31513
+ return notFound(res);
31673
31514
  jsonResponse(res, data);
31674
31515
  return;
31675
31516
  }
31676
31517
  if (pathname === "/api/thoughts" && req.method === "GET" && scopedWorldId) {
31677
31518
  const data = handleGetThoughts(registry2, scopedWorldId);
31678
- if (!data) return notFound(res);
31519
+ if (!data)
31520
+ return notFound(res);
31679
31521
  jsonResponse(res, data);
31680
31522
  return;
31681
31523
  }
@@ -31683,7 +31525,8 @@ function createDashboardServer(opts) {
31683
31525
  if (thoughtsMatch && req.method === "GET") {
31684
31526
  const worldId = scopedWorldId ?? thoughtsMatch[1];
31685
31527
  const data = handleGetThoughts(registry2, worldId);
31686
- if (!data) return notFound(res);
31528
+ if (!data)
31529
+ return notFound(res);
31687
31530
  jsonResponse(res, data);
31688
31531
  return;
31689
31532
  }
@@ -31801,7 +31644,8 @@ function createDashboardServer(opts) {
31801
31644
  if (worldMatch && req.method === "GET") {
31802
31645
  const worldId = scopedWorldId ?? worldMatch[1];
31803
31646
  const data = handleGetWorld(registry2, worldId);
31804
- if (!data) return notFound(res);
31647
+ if (!data)
31648
+ return notFound(res);
31805
31649
  jsonResponse(res, data);
31806
31650
  return;
31807
31651
  }
@@ -31908,9 +31752,7 @@ function createDashboardServer(opts) {
31908
31752
  }
31909
31753
  if (!hasPublicDir) {
31910
31754
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
31911
- res.end(
31912
- `<html><body style="font-family:system-ui;padding:2rem"><h1>Olam Dashboard</h1><p>The React app has not been built yet.</p><p>Run <code>npm run build:app</code> in <code>packages/control-plane</code> to build it.</p><p>API routes are available at <code>/api/*</code>.</p></body></html>`
31913
- );
31755
+ res.end(`<html><body style="font-family:system-ui;padding:2rem"><h1>Olam Dashboard</h1><p>The React app has not been built yet.</p><p>Run <code>npm run build:app</code> in <code>packages/control-plane</code> to build it.</p><p>API routes are available at <code>/api/*</code>.</p></body></html>`);
31914
31756
  return;
31915
31757
  }
31916
31758
  let filePath = path19.join(publicDir, pathname === "/" ? "index.html" : pathname);
@@ -31937,7 +31779,7 @@ function createDashboardServer(opts) {
31937
31779
  return server;
31938
31780
  }
31939
31781
 
31940
- // ../core/src/dashboard/state.ts
31782
+ // ../core/dist/dashboard/state.js
31941
31783
  import * as fs16 from "node:fs";
31942
31784
  import * as os9 from "node:os";
31943
31785
  import * as path20 from "node:path";
@@ -31962,7 +31804,8 @@ function clearDashboardState() {
31962
31804
  }
31963
31805
  function isDashboardRunning() {
31964
31806
  const state = loadDashboardState();
31965
- if (!state) return false;
31807
+ if (!state)
31808
+ return false;
31966
31809
  try {
31967
31810
  process.kill(state.pid, 0);
31968
31811
  return true;
@@ -31972,7 +31815,7 @@ function isDashboardRunning() {
31972
31815
  }
31973
31816
  }
31974
31817
 
31975
- // ../core/src/dashboard/tunnel.ts
31818
+ // ../core/dist/dashboard/tunnel.js
31976
31819
  import { spawn, execSync as execSync5 } from "node:child_process";
31977
31820
  var tunnelProcess = null;
31978
31821
  function isCloudflaredAvailable() {
@@ -31999,7 +31842,8 @@ function startTunnel(port) {
31999
31842
  }
32000
31843
  }, 3e4);
32001
31844
  function scan(data) {
32002
- if (resolved) return;
31845
+ if (resolved)
31846
+ return;
32003
31847
  const text = data.toString();
32004
31848
  const match = urlPattern.exec(text);
32005
31849
  if (match) {
@@ -32036,14 +31880,14 @@ function getTunnelPid() {
32036
31880
  return tunnelProcess?.pid;
32037
31881
  }
32038
31882
 
32039
- // ../core/src/dashboard/index.ts
31883
+ // ../core/dist/dashboard/index.js
32040
31884
  var DashboardManager = class {
32041
- constructor(config2 = { port: 9740, tunnel: false }) {
32042
- this.config = config2;
32043
- }
32044
31885
  config;
32045
31886
  server = null;
32046
31887
  info = null;
31888
+ constructor(config2 = { port: 9740, tunnel: false }) {
31889
+ this.config = config2;
31890
+ }
32047
31891
  /**
32048
31892
  * Ensure the dashboard is running. Idempotent — if already started
32049
31893
  * (in this process or another), returns existing info.
@@ -32101,7 +31945,8 @@ var DashboardManager = class {
32101
31945
  * Get current dashboard info, or null if not running.
32102
31946
  */
32103
31947
  getInfo() {
32104
- if (this.info) return this.info;
31948
+ if (this.info)
31949
+ return this.info;
32105
31950
  if (isDashboardRunning()) {
32106
31951
  const state = loadDashboardState();
32107
31952
  if (state) {
@@ -32129,7 +31974,7 @@ var DashboardManager = class {
32129
31974
  }
32130
31975
  };
32131
31976
 
32132
- // ../core/src/pleri/client.ts
31977
+ // ../core/dist/pleri/client.js
32133
31978
  var PleriClient = class {
32134
31979
  baseUrl;
32135
31980
  planeId;
@@ -32158,14 +32003,10 @@ var PleriClient = class {
32158
32003
  if (!res.ok) {
32159
32004
  const body = await res.text();
32160
32005
  if (res.status === 401 || res.status === 403) {
32161
- throw new Error(
32162
- `Pleri authentication error (${res.status}): ${body}. Check your API key and plane membership.`
32163
- );
32006
+ throw new Error(`Pleri authentication error (${res.status}): ${body}. Check your API key and plane membership.`);
32164
32007
  }
32165
32008
  if (res.status === 402) {
32166
- throw new Error(
32167
- `Pleri budget exhausted (402): ${body}. The plane's budget has been reached.`
32168
- );
32009
+ throw new Error(`Pleri budget exhausted (402): ${body}. The plane's budget has been reached.`);
32169
32010
  }
32170
32011
  throw new Error(`Pleri API error (${res.status}): ${body}`);
32171
32012
  }
@@ -32195,13 +32036,10 @@ var PleriClient = class {
32195
32036
  * Sends optional final cost and crystallization status in the body.
32196
32037
  */
32197
32038
  async deregisterWorld(worldId, data) {
32198
- await this.fetch(
32199
- `${this.planeUrl}/worlds/${encodeURIComponent(worldId)}`,
32200
- {
32201
- method: "DELETE",
32202
- body: data ? JSON.stringify(data) : void 0
32203
- }
32204
- );
32039
+ await this.fetch(`${this.planeUrl}/worlds/${encodeURIComponent(worldId)}`, {
32040
+ method: "DELETE",
32041
+ body: data ? JSON.stringify(data) : void 0
32042
+ });
32205
32043
  }
32206
32044
  /**
32207
32045
  * PUT {planeUrl}/worlds/{worldId}/status — send a heartbeat.
@@ -32209,13 +32047,10 @@ var PleriClient = class {
32209
32047
  */
32210
32048
  async updateStatus(worldId, heartbeat) {
32211
32049
  try {
32212
- await this.fetch(
32213
- `${this.planeUrl}/worlds/${encodeURIComponent(worldId)}/status`,
32214
- {
32215
- method: "PUT",
32216
- body: JSON.stringify(heartbeat)
32217
- }
32218
- );
32050
+ await this.fetch(`${this.planeUrl}/worlds/${encodeURIComponent(worldId)}/status`, {
32051
+ method: "PUT",
32052
+ body: JSON.stringify(heartbeat)
32053
+ });
32219
32054
  } catch {
32220
32055
  }
32221
32056
  }
@@ -32225,13 +32060,10 @@ var PleriClient = class {
32225
32060
  */
32226
32061
  async crystallize(req) {
32227
32062
  try {
32228
- return await this.fetch(
32229
- `${this.planeUrl}/worlds/${encodeURIComponent(req.worldId)}/crystallize`,
32230
- {
32231
- method: "POST",
32232
- body: JSON.stringify(req)
32233
- }
32234
- );
32063
+ return await this.fetch(`${this.planeUrl}/worlds/${encodeURIComponent(req.worldId)}/crystallize`, {
32064
+ method: "POST",
32065
+ body: JSON.stringify(req)
32066
+ });
32235
32067
  } catch (err) {
32236
32068
  if (err instanceof Error && /authentication error/i.test(err.message)) {
32237
32069
  throw err;