@pleri/olam-cli 0.1.55 → 0.1.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/__tests__/services.test.d.ts +8 -0
  2. package/dist/__tests__/services.test.d.ts.map +1 -0
  3. package/dist/__tests__/services.test.js +185 -0
  4. package/dist/__tests__/services.test.js.map +1 -0
  5. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts +6 -0
  6. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts.map +1 -0
  7. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js +26 -0
  8. package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js.map +1 -0
  9. package/dist/commands/__tests__/upgrade.all-three.test.js +1 -13
  10. package/dist/commands/__tests__/upgrade.all-three.test.js.map +1 -1
  11. package/dist/commands/__tests__/upgrade.compose-path.test.js +1 -13
  12. package/dist/commands/__tests__/upgrade.compose-path.test.js.map +1 -1
  13. package/dist/commands/__tests__/upgrade.olam-tag.test.js +1 -14
  14. package/dist/commands/__tests__/upgrade.olam-tag.test.js.map +1 -1
  15. package/dist/commands/__tests__/upgrade.recreate.test.js +1 -13
  16. package/dist/commands/__tests__/upgrade.recreate.test.js.map +1 -1
  17. package/dist/commands/__tests__/upgrade.rollback.test.js +1 -21
  18. package/dist/commands/__tests__/upgrade.rollback.test.js.map +1 -1
  19. package/dist/commands/__tests__/upgrade.smoke.test.js +9 -23
  20. package/dist/commands/__tests__/upgrade.smoke.test.js.map +1 -1
  21. package/dist/commands/__tests__/upgrade.swap.test.js +1 -22
  22. package/dist/commands/__tests__/upgrade.swap.test.js.map +1 -1
  23. package/dist/commands/auth.d.ts.map +1 -1
  24. package/dist/commands/auth.js +15 -38
  25. package/dist/commands/auth.js.map +1 -1
  26. package/dist/commands/bootstrap.d.ts +2 -0
  27. package/dist/commands/bootstrap.d.ts.map +1 -1
  28. package/dist/commands/bootstrap.js +3 -3
  29. package/dist/commands/bootstrap.js.map +1 -1
  30. package/dist/commands/create.d.ts.map +1 -1
  31. package/dist/commands/create.js +1 -9
  32. package/dist/commands/create.js.map +1 -1
  33. package/dist/commands/services.d.ts +39 -0
  34. package/dist/commands/services.d.ts.map +1 -0
  35. package/dist/commands/services.js +220 -0
  36. package/dist/commands/services.js.map +1 -0
  37. package/dist/commands/upgrade.d.ts +11 -12
  38. package/dist/commands/upgrade.d.ts.map +1 -1
  39. package/dist/commands/upgrade.js +81 -6
  40. package/dist/commands/upgrade.js.map +1 -1
  41. package/dist/image-digests.json +4 -3
  42. package/dist/index.js +1013 -1029
  43. package/dist/index.js.map +1 -1
  44. package/dist/mcp-server.js +310 -372
  45. package/package.json +1 -1
@@ -3228,8 +3228,8 @@ var require_utils = __commonJS({
3228
3228
  }
3229
3229
  return ind;
3230
3230
  }
3231
- function removeDotSegments(path22) {
3232
- let input = path22;
3231
+ function removeDotSegments(path21) {
3232
+ let input = path21;
3233
3233
  const output = [];
3234
3234
  let nextSlash = -1;
3235
3235
  let len = 0;
@@ -3428,8 +3428,8 @@ var require_schemes = __commonJS({
3428
3428
  wsComponent.secure = void 0;
3429
3429
  }
3430
3430
  if (wsComponent.resourceName) {
3431
- const [path22, query] = wsComponent.resourceName.split("?");
3432
- wsComponent.path = path22 && path22 !== "/" ? path22 : void 0;
3431
+ const [path21, query] = wsComponent.resourceName.split("?");
3432
+ wsComponent.path = path21 && path21 !== "/" ? path21 : void 0;
3433
3433
  wsComponent.query = query;
3434
3434
  wsComponent.resourceName = void 0;
3435
3435
  }
@@ -6791,12 +6791,12 @@ var require_dist = __commonJS({
6791
6791
  throw new Error(`Unknown format "${name}"`);
6792
6792
  return f;
6793
6793
  };
6794
- function addFormats(ajv, list, fs18, exportName) {
6794
+ function addFormats(ajv, list, fs17, exportName) {
6795
6795
  var _a;
6796
6796
  var _b;
6797
6797
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
6798
6798
  for (const f of list)
6799
- ajv.addFormat(f, fs18[f]);
6799
+ ajv.addFormat(f, fs17[f]);
6800
6800
  }
6801
6801
  module.exports = exports = formatsPlugin;
6802
6802
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -7002,10 +7002,10 @@ function assignProp(target, prop, value) {
7002
7002
  configurable: true
7003
7003
  });
7004
7004
  }
7005
- function getElementAtPath(obj, path22) {
7006
- if (!path22)
7005
+ function getElementAtPath(obj, path21) {
7006
+ if (!path21)
7007
7007
  return obj;
7008
- return path22.reduce((acc, key) => acc?.[key], obj);
7008
+ return path21.reduce((acc, key) => acc?.[key], obj);
7009
7009
  }
7010
7010
  function promiseAllObject(promisesObj) {
7011
7011
  const keys = Object.keys(promisesObj);
@@ -7325,11 +7325,11 @@ function aborted(x, startIndex = 0) {
7325
7325
  }
7326
7326
  return false;
7327
7327
  }
7328
- function prefixIssues(path22, issues) {
7328
+ function prefixIssues(path21, issues) {
7329
7329
  return issues.map((iss) => {
7330
7330
  var _a;
7331
7331
  (_a = iss).path ?? (_a.path = []);
7332
- iss.path.unshift(path22);
7332
+ iss.path.unshift(path21);
7333
7333
  return iss;
7334
7334
  });
7335
7335
  }
@@ -13403,8 +13403,8 @@ function getErrorMap() {
13403
13403
 
13404
13404
  // ../../node_modules/zod/v3/helpers/parseUtil.js
13405
13405
  var makeIssue = (params) => {
13406
- const { data, path: path22, errorMaps, issueData } = params;
13407
- const fullPath = [...path22, ...issueData.path || []];
13406
+ const { data, path: path21, errorMaps, issueData } = params;
13407
+ const fullPath = [...path21, ...issueData.path || []];
13408
13408
  const fullIssue = {
13409
13409
  ...issueData,
13410
13410
  path: fullPath
@@ -13520,11 +13520,11 @@ var errorUtil;
13520
13520
 
13521
13521
  // ../../node_modules/zod/v3/types.js
13522
13522
  var ParseInputLazyPath = class {
13523
- constructor(parent, value, path22, key) {
13523
+ constructor(parent, value, path21, key) {
13524
13524
  this._cachedPath = [];
13525
13525
  this.parent = parent;
13526
13526
  this.data = value;
13527
- this._path = path22;
13527
+ this._path = path21;
13528
13528
  this._key = key;
13529
13529
  }
13530
13530
  get path() {
@@ -21365,8 +21365,8 @@ var AuthClient = class {
21365
21365
  throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
21366
21366
  }
21367
21367
  }
21368
- async request(method, path22, body, attempt = 0) {
21369
- const url = `${this.baseUrl}${path22}`;
21368
+ async request(method, path21, body, attempt = 0) {
21369
+ const url = `${this.baseUrl}${path21}`;
21370
21370
  const controller = new AbortController();
21371
21371
  const timer = setTimeout(() => controller.abort(), this.timeoutMs);
21372
21372
  const headers = {};
@@ -21384,7 +21384,7 @@ var AuthClient = class {
21384
21384
  } catch (err) {
21385
21385
  if (attempt < RETRY_COUNT && isTransient(err)) {
21386
21386
  await sleep(RETRY_BACKOFF_MS * (attempt + 1));
21387
- return this.request(method, path22, body, attempt + 1);
21387
+ return this.request(method, path21, body, attempt + 1);
21388
21388
  }
21389
21389
  throw err;
21390
21390
  } finally {
@@ -22191,12 +22191,12 @@ function register3(server, _ctx, _initError) {
22191
22191
  registry2.close();
22192
22192
  }
22193
22193
  try {
22194
- const { default: fs18 } = await import("node:fs");
22194
+ const { default: fs17 } = await import("node:fs");
22195
22195
  const { default: os10 } = await import("node:os");
22196
- const { default: path22 } = await import("node:path");
22197
- const tokenPath = path22.join(os10.homedir(), ".olam", "host-cp.token");
22198
- if (fs18.existsSync(tokenPath)) {
22199
- const token = fs18.readFileSync(tokenPath, "utf-8").trim();
22196
+ const { default: path21 } = await import("node:path");
22197
+ const tokenPath = path21.join(os10.homedir(), ".olam", "host-cp.token");
22198
+ if (fs17.existsSync(tokenPath)) {
22199
+ const token = fs17.readFileSync(tokenPath, "utf-8").trim();
22200
22200
  await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
22201
22201
  method: "POST",
22202
22202
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
@@ -22389,7 +22389,7 @@ var KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
22389
22389
  "deploy"
22390
22390
  ]);
22391
22391
  var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
22392
- function refineForbiddenKeys(value, path22, ctx, rejectSource) {
22392
+ function refineForbiddenKeys(value, path21, ctx, rejectSource) {
22393
22393
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
22394
22394
  return;
22395
22395
  }
@@ -22397,12 +22397,12 @@ function refineForbiddenKeys(value, path22, ctx, rejectSource) {
22397
22397
  if (FORBIDDEN_KEYS.has(key)) {
22398
22398
  ctx.addIssue({
22399
22399
  code: external_exports.ZodIssueCode.custom,
22400
- path: [...path22, key],
22400
+ path: [...path21, key],
22401
22401
  message: `forbidden key "${key}" (prototype-pollution surface)`
22402
22402
  });
22403
22403
  continue;
22404
22404
  }
22405
- if (rejectSource && path22.length === 0 && key === "source") {
22405
+ if (rejectSource && path21.length === 0 && key === "source") {
22406
22406
  ctx.addIssue({
22407
22407
  code: external_exports.ZodIssueCode.custom,
22408
22408
  path: ["source"],
@@ -22410,21 +22410,21 @@ function refineForbiddenKeys(value, path22, ctx, rejectSource) {
22410
22410
  });
22411
22411
  continue;
22412
22412
  }
22413
- refineForbiddenKeys(value[key], [...path22, key], ctx, false);
22413
+ refineForbiddenKeys(value[key], [...path21, key], ctx, false);
22414
22414
  }
22415
22415
  }
22416
- function rejectForbiddenKeys(value, path22, rejectSource) {
22416
+ function rejectForbiddenKeys(value, path21, rejectSource) {
22417
22417
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
22418
22418
  return;
22419
22419
  }
22420
22420
  for (const key of Object.keys(value)) {
22421
22421
  if (FORBIDDEN_KEYS.has(key)) {
22422
- throw new Error(`[manifest] ${path22}: forbidden key "${key}" (prototype-pollution surface)`);
22422
+ throw new Error(`[manifest] ${path21}: forbidden key "${key}" (prototype-pollution surface)`);
22423
22423
  }
22424
22424
  if (rejectSource && key === "source") {
22425
- throw new Error(`[manifest] ${path22}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
22425
+ throw new Error(`[manifest] ${path21}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
22426
22426
  }
22427
- rejectForbiddenKeys(value[key], `${path22}.${key}`, false);
22427
+ rejectForbiddenKeys(value[key], `${path21}.${key}`, false);
22428
22428
  }
22429
22429
  }
22430
22430
  function unknownTopLevelKeys(parsed) {
@@ -22862,10 +22862,10 @@ function extractMcpConfig(claudeJsonPath) {
22862
22862
  }
22863
22863
  return { mcpServers, secrets };
22864
22864
  }
22865
- function readOptional(path22) {
22866
- if (!existsSync6(path22)) return null;
22865
+ function readOptional(path21) {
22866
+ if (!existsSync6(path21)) return null;
22867
22867
  try {
22868
- return readFileSync5(path22, "utf8");
22868
+ return readFileSync5(path21, "utf8");
22869
22869
  } catch {
22870
22870
  return null;
22871
22871
  }
@@ -24008,8 +24008,8 @@ var CloudflareProvider = class extends ComputeProvider {
24008
24008
  // -----------------------------------------------------------------------
24009
24009
  // Internal fetch helper
24010
24010
  // -----------------------------------------------------------------------
24011
- async request(path22, method, body) {
24012
- const url = `${this.config.workerUrl}${path22}`;
24011
+ async request(path21, method, body) {
24012
+ const url = `${this.config.workerUrl}${path21}`;
24013
24013
  const bearer = await this.config.mintToken();
24014
24014
  const headers = {
24015
24015
  Authorization: `Bearer ${bearer}`
@@ -24989,10 +24989,10 @@ var ThoughtLocalStore = class {
24989
24989
  };
24990
24990
 
24991
24991
  // ../core/dist/world/env-setup.js
24992
- import * as crypto3 from "node:crypto";
24993
- import * as fs7 from "node:fs";
24992
+ import * as crypto2 from "node:crypto";
24993
+ import * as fs6 from "node:fs";
24994
24994
  import * as os6 from "node:os";
24995
- import * as path10 from "node:path";
24995
+ import * as path9 from "node:path";
24996
24996
  import { globSync } from "node:fs";
24997
24997
 
24998
24998
  // ../core/dist/thought/hooks-config.js
@@ -25078,182 +25078,82 @@ function generateHooksConfig(hookServerUrl = DEFAULT_HOOK_SERVER_URL) {
25078
25078
  };
25079
25079
  }
25080
25080
 
25081
- // ../core/dist/world/merge-settings.js
25082
- import * as fs6 from "node:fs";
25083
- import * as path9 from "node:path";
25084
- import * as crypto2 from "node:crypto";
25085
- function mergeHomeSettingsJson(filePath, options) {
25086
- let settings;
25087
- try {
25088
- settings = readSettings(filePath);
25089
- } catch (err) {
25090
- throw new Error(`merge-settings: failed to parse existing settings.json: ${err?.message ?? err}`);
25091
- }
25092
- let changed = false;
25093
- if (options.ensureHook) {
25094
- const { stage, sentinel, entry } = options.ensureHook;
25095
- if (!settings.hooks || typeof settings.hooks !== "object") {
25096
- settings = { ...settings, hooks: {} };
25097
- changed = true;
25098
- }
25099
- const hooks = settings.hooks;
25100
- if (!Array.isArray(hooks[stage])) {
25101
- settings = {
25102
- ...settings,
25103
- hooks: { ...hooks, [stage]: [] }
25104
- };
25105
- changed = true;
25106
- }
25107
- const stageArr = settings.hooks[stage];
25108
- if (isHookSentinelPresent(stageArr, sentinel)) {
25109
- if (!changed) {
25110
- return { status: "already-present", message: `hook already present at ${filePath}` };
25111
- }
25112
- } else {
25113
- settings = {
25114
- ...settings,
25115
- hooks: {
25116
- ...settings.hooks,
25117
- [stage]: [...stageArr, entry]
25118
- }
25119
- };
25120
- changed = true;
25121
- }
25122
- }
25123
- if (options.env) {
25124
- const existingEnv = settings.env && typeof settings.env === "object" ? settings.env : {};
25125
- const mergedEnv = { ...existingEnv, ...options.env };
25126
- const sameKeys = Object.keys(mergedEnv).length === Object.keys(existingEnv).length && Object.keys(mergedEnv).every((k) => existingEnv[k] === mergedEnv[k]);
25127
- if (!sameKeys) {
25128
- settings = { ...settings, env: mergedEnv };
25129
- changed = true;
25130
- }
25131
- }
25132
- if (!changed) {
25133
- return { status: "no-op", message: `no change needed at ${filePath}` };
25134
- }
25135
- try {
25136
- atomicWriteJson(filePath, settings);
25137
- } catch (err) {
25138
- throw new Error(`merge-settings: failed to write settings.json: ${err?.message ?? err}`);
25139
- }
25140
- return { status: "installed", message: `settings.json updated at ${filePath}` };
25141
- }
25142
- function readSettings(filePath) {
25143
- if (!fs6.existsSync(filePath)) {
25144
- return {};
25145
- }
25146
- const raw = fs6.readFileSync(filePath, "utf-8");
25147
- if (!raw.trim())
25148
- return {};
25149
- return JSON.parse(raw);
25150
- }
25151
- function isHookSentinelPresent(matchers, sentinel) {
25152
- for (const matcher of matchers) {
25153
- if (typeof matcher?.command === "string" && matcher.command.includes(sentinel)) {
25154
- return true;
25155
- }
25156
- if (Array.isArray(matcher?.hooks)) {
25157
- for (const h of matcher.hooks) {
25158
- if (typeof h?.command === "string" && h.command.includes(sentinel)) {
25159
- return true;
25160
- }
25161
- }
25162
- }
25163
- }
25164
- return false;
25165
- }
25166
- function atomicWriteJson(filePath, data) {
25167
- const dir = path9.dirname(filePath);
25168
- fs6.mkdirSync(dir, { recursive: true });
25169
- const rand = crypto2.randomBytes(6).toString("hex");
25170
- const tmp = `${filePath}.tmp.${process.pid}.${rand}`;
25171
- const json = JSON.stringify(data, null, 2) + "\n";
25172
- fs6.writeFileSync(tmp, json, { mode: 420 });
25173
- fs6.renameSync(tmp, filePath);
25174
- }
25175
-
25176
25081
  // ../core/dist/world/env-setup.js
25177
25082
  function copyClaudeConfig(workspacePath, homeDir, configCtx) {
25178
- const sourceClaudeDir = path10.join(homeDir ?? os6.homedir(), ".claude");
25179
- const destClaudeDir = path10.join(workspacePath, ".claude-host-config");
25083
+ const sourceClaudeDir = path9.join(homeDir ?? os6.homedir(), ".claude");
25084
+ const destClaudeDir = path9.join(workspacePath, ".claude-host-config");
25180
25085
  void configCtx;
25181
- if (!fs7.existsSync(sourceClaudeDir))
25086
+ if (!fs6.existsSync(sourceClaudeDir))
25182
25087
  return;
25183
- fs7.mkdirSync(destClaudeDir, { recursive: true });
25184
- const settingsPath = path10.join(sourceClaudeDir, "settings.json");
25088
+ fs6.mkdirSync(destClaudeDir, { recursive: true });
25089
+ const settingsPath = path9.join(sourceClaudeDir, "settings.json");
25185
25090
  let settings = {};
25186
- if (fs7.existsSync(settingsPath)) {
25091
+ if (fs6.existsSync(settingsPath)) {
25187
25092
  try {
25188
- settings = JSON.parse(fs7.readFileSync(settingsPath, "utf-8"));
25093
+ settings = JSON.parse(fs6.readFileSync(settingsPath, "utf-8"));
25189
25094
  delete settings["hooks"];
25190
25095
  } catch {
25191
25096
  }
25192
25097
  }
25193
25098
  const hooksConfig = generateHooksConfig(DEFAULT_HOOK_SERVER_URL);
25194
25099
  settings["hooks"] = hooksConfig["hooks"];
25195
- fs7.writeFileSync(path10.join(destClaudeDir, "settings.json"), JSON.stringify(settings, null, 2));
25196
- const claudeMdPath = path10.join(sourceClaudeDir, "CLAUDE.md");
25197
- if (fs7.existsSync(claudeMdPath)) {
25198
- fs7.copyFileSync(claudeMdPath, path10.join(destClaudeDir, "CLAUDE.md"));
25100
+ fs6.writeFileSync(path9.join(destClaudeDir, "settings.json"), JSON.stringify(settings, null, 2));
25101
+ const claudeMdPath = path9.join(sourceClaudeDir, "CLAUDE.md");
25102
+ if (fs6.existsSync(claudeMdPath)) {
25103
+ fs6.copyFileSync(claudeMdPath, path9.join(destClaudeDir, "CLAUDE.md"));
25199
25104
  }
25200
- const rulesDir = path10.join(sourceClaudeDir, "rules");
25201
- if (fs7.existsSync(rulesDir)) {
25202
- copyDirRecursive(rulesDir, path10.join(destClaudeDir, "rules"));
25105
+ const rulesDir = path9.join(sourceClaudeDir, "rules");
25106
+ if (fs6.existsSync(rulesDir)) {
25107
+ copyDirRecursive(rulesDir, path9.join(destClaudeDir, "rules"));
25203
25108
  }
25204
- const agentsDir = path10.join(sourceClaudeDir, "agents");
25205
- if (fs7.existsSync(agentsDir)) {
25206
- copyDirRecursive(agentsDir, path10.join(destClaudeDir, "agents"));
25109
+ const agentsDir = path9.join(sourceClaudeDir, "agents");
25110
+ if (fs6.existsSync(agentsDir)) {
25111
+ copyDirRecursive(agentsDir, path9.join(destClaudeDir, "agents"));
25207
25112
  }
25208
- const pluginsDir = path10.join(sourceClaudeDir, "plugins");
25209
- if (fs7.existsSync(pluginsDir)) {
25210
- copyDirRecursive(pluginsDir, path10.join(destClaudeDir, "plugins"), 0, SKIP_FILES);
25113
+ const pluginsDir = path9.join(sourceClaudeDir, "plugins");
25114
+ if (fs6.existsSync(pluginsDir)) {
25115
+ copyDirRecursive(pluginsDir, path9.join(destClaudeDir, "plugins"), 0, SKIP_FILES);
25211
25116
  }
25212
- const skillsDir = path10.join(sourceClaudeDir, "skills");
25213
- if (fs7.existsSync(skillsDir)) {
25214
- copyDirRecursive(skillsDir, path10.join(destClaudeDir, "skills"));
25117
+ const skillsDir = path9.join(sourceClaudeDir, "skills");
25118
+ if (fs6.existsSync(skillsDir)) {
25119
+ copyDirRecursive(skillsDir, path9.join(destClaudeDir, "skills"));
25215
25120
  }
25216
- const scriptsDir = path10.join(sourceClaudeDir, "scripts");
25217
- if (fs7.existsSync(scriptsDir)) {
25218
- copyDirRecursive(scriptsDir, path10.join(destClaudeDir, "scripts"));
25121
+ const scriptsDir = path9.join(sourceClaudeDir, "scripts");
25122
+ if (fs6.existsSync(scriptsDir)) {
25123
+ copyDirRecursive(scriptsDir, path9.join(destClaudeDir, "scripts"));
25219
25124
  }
25220
25125
  applyProjectClaudeOverlay(workspacePath, destClaudeDir);
25221
25126
  writeStrippedMcpServersSnapshot(homeDir ?? os6.homedir(), workspacePath, destClaudeDir);
25222
- if (configCtx != null && configCtx.worlds_default?.agent_teams_enabled !== false) {
25223
- mergeHomeSettingsJson(path10.join(destClaudeDir, "settings.json"), {
25224
- env: { CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1" }
25225
- });
25226
- }
25227
25127
  }
25228
25128
  function applyProjectClaudeOverlay(workspacePath, destClaudeDir) {
25229
- const projectClaudeDir = path10.join(workspacePath, ".claude");
25230
- if (!fs7.existsSync(projectClaudeDir))
25129
+ const projectClaudeDir = path9.join(workspacePath, ".claude");
25130
+ if (!fs6.existsSync(projectClaudeDir))
25231
25131
  return;
25232
- const projectSettingsPath = path10.join(projectClaudeDir, "settings.json");
25233
- const destSettingsPath = path10.join(destClaudeDir, "settings.json");
25234
- if (fs7.existsSync(projectSettingsPath)) {
25132
+ const projectSettingsPath = path9.join(projectClaudeDir, "settings.json");
25133
+ const destSettingsPath = path9.join(destClaudeDir, "settings.json");
25134
+ if (fs6.existsSync(projectSettingsPath)) {
25235
25135
  try {
25236
- const projectSettings = JSON.parse(fs7.readFileSync(projectSettingsPath, "utf-8"));
25136
+ const projectSettings = JSON.parse(fs6.readFileSync(projectSettingsPath, "utf-8"));
25237
25137
  delete projectSettings["hooks"];
25238
- const existing = fs7.existsSync(destSettingsPath) ? JSON.parse(fs7.readFileSync(destSettingsPath, "utf-8")) : {};
25138
+ const existing = fs6.existsSync(destSettingsPath) ? JSON.parse(fs6.readFileSync(destSettingsPath, "utf-8")) : {};
25239
25139
  const merged = { ...existing, ...projectSettings, hooks: existing["hooks"] };
25240
- fs7.writeFileSync(destSettingsPath, JSON.stringify(merged, null, 2));
25140
+ fs6.writeFileSync(destSettingsPath, JSON.stringify(merged, null, 2));
25241
25141
  } catch {
25242
25142
  }
25243
25143
  }
25244
- const projectClaudeMd = path10.join(projectClaudeDir, "CLAUDE.md");
25245
- if (fs7.existsSync(projectClaudeMd)) {
25246
- fs7.copyFileSync(projectClaudeMd, path10.join(destClaudeDir, "CLAUDE.md"));
25144
+ const projectClaudeMd = path9.join(projectClaudeDir, "CLAUDE.md");
25145
+ if (fs6.existsSync(projectClaudeMd)) {
25146
+ fs6.copyFileSync(projectClaudeMd, path9.join(destClaudeDir, "CLAUDE.md"));
25247
25147
  }
25248
- const projectAgentsMd = path10.join(projectClaudeDir, "AGENTS.md");
25249
- if (fs7.existsSync(projectAgentsMd)) {
25250
- fs7.copyFileSync(projectAgentsMd, path10.join(destClaudeDir, "AGENTS.md"));
25148
+ const projectAgentsMd = path9.join(projectClaudeDir, "AGENTS.md");
25149
+ if (fs6.existsSync(projectAgentsMd)) {
25150
+ fs6.copyFileSync(projectAgentsMd, path9.join(destClaudeDir, "AGENTS.md"));
25251
25151
  }
25252
25152
  for (const subdir of ["rules", "agents", "plugins", "skills", "scripts"]) {
25253
- const projectSubdir = path10.join(projectClaudeDir, subdir);
25254
- if (fs7.existsSync(projectSubdir)) {
25153
+ const projectSubdir = path9.join(projectClaudeDir, subdir);
25154
+ if (fs6.existsSync(projectSubdir)) {
25255
25155
  const skip = subdir === "plugins" ? SKIP_FILES : /* @__PURE__ */ new Set();
25256
- copyDirRecursive(projectSubdir, path10.join(destClaudeDir, subdir), 0, skip);
25156
+ copyDirRecursive(projectSubdir, path9.join(destClaudeDir, subdir), 0, skip);
25257
25157
  }
25258
25158
  }
25259
25159
  }
@@ -25289,8 +25189,8 @@ function stripMcpServers(mcpServers) {
25289
25189
  return out;
25290
25190
  }
25291
25191
  function writeStrippedMcpServersSnapshot(homeDir, workspacePath, destClaudeDir) {
25292
- const hostMcpServers = readMcpServersFromFile(path10.join(homeDir, ".claude.json"));
25293
- const projectMcpServers = readMcpServersFromFile(path10.join(workspacePath, ".mcp.json"));
25192
+ const hostMcpServers = readMcpServersFromFile(path9.join(homeDir, ".claude.json"));
25193
+ const projectMcpServers = readMcpServersFromFile(path9.join(workspacePath, ".mcp.json"));
25294
25194
  if (Object.keys(hostMcpServers).length === 0 && Object.keys(projectMcpServers).length === 0) {
25295
25195
  return;
25296
25196
  }
@@ -25299,11 +25199,11 @@ function writeStrippedMcpServersSnapshot(homeDir, workspacePath, destClaudeDir)
25299
25199
  ...stripMcpServers(projectMcpServers)
25300
25200
  };
25301
25201
  const output = { mcpServers: stripped };
25302
- fs7.writeFileSync(path10.join(destClaudeDir, ".claude.json"), JSON.stringify(output, null, 2), { mode: 384 });
25202
+ fs6.writeFileSync(path9.join(destClaudeDir, ".claude.json"), JSON.stringify(output, null, 2), { mode: 384 });
25303
25203
  }
25304
25204
  function writeWorldEntitlementsJson(workspacePath, configCtx) {
25305
- const olamDir = path10.join(workspacePath, ".olam");
25306
- fs7.mkdirSync(olamDir, { recursive: true });
25205
+ const olamDir = path9.join(workspacePath, ".olam");
25206
+ fs6.mkdirSync(olamDir, { recursive: true });
25307
25207
  const resolvedRepos = configCtx.repos.map((repo) => {
25308
25208
  const repoEntitlement = repo;
25309
25209
  return {
@@ -25317,14 +25217,14 @@ function writeWorldEntitlementsJson(workspacePath, configCtx) {
25317
25217
  worlds_default: configCtx.worlds_default,
25318
25218
  repos: resolvedRepos
25319
25219
  };
25320
- const filePath = path10.join(olamDir, "world-entitlements.json");
25321
- fs7.writeFileSync(filePath, JSON.stringify(resolved, null, 2), { mode: 420 });
25220
+ const filePath = path9.join(olamDir, "world-entitlements.json");
25221
+ fs6.writeFileSync(filePath, JSON.stringify(resolved, null, 2), { mode: 420 });
25322
25222
  }
25323
25223
  function readMcpServersFromFile(filePath) {
25324
- if (!fs7.existsSync(filePath))
25224
+ if (!fs6.existsSync(filePath))
25325
25225
  return {};
25326
25226
  try {
25327
- const raw = fs7.readFileSync(filePath, "utf-8");
25227
+ const raw = fs6.readFileSync(filePath, "utf-8");
25328
25228
  if (!raw.trim())
25329
25229
  return {};
25330
25230
  const parsed = JSON.parse(raw);
@@ -25360,8 +25260,8 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([
25360
25260
  function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new Set()) {
25361
25261
  if (depth > 10)
25362
25262
  return;
25363
- fs7.mkdirSync(dest, { recursive: true });
25364
- for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
25263
+ fs6.mkdirSync(dest, { recursive: true });
25264
+ for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
25365
25265
  const { name } = entry;
25366
25266
  if (skipFiles.has(name))
25367
25267
  continue;
@@ -25371,12 +25271,12 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
25371
25271
  continue;
25372
25272
  if (entry.isDirectory() && SKIP_DIRS.has(name))
25373
25273
  continue;
25374
- const srcPath = path10.join(src, name);
25375
- const destPath = path10.join(dest, name);
25274
+ const srcPath = path9.join(src, name);
25275
+ const destPath = path9.join(dest, name);
25376
25276
  if (entry.isSymbolicLink()) {
25377
25277
  let stat;
25378
25278
  try {
25379
- stat = fs7.statSync(srcPath);
25279
+ stat = fs6.statSync(srcPath);
25380
25280
  } catch {
25381
25281
  continue;
25382
25282
  }
@@ -25385,12 +25285,12 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
25385
25285
  continue;
25386
25286
  copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
25387
25287
  } else if (stat.isFile()) {
25388
- fs7.copyFileSync(srcPath, destPath);
25288
+ fs6.copyFileSync(srcPath, destPath);
25389
25289
  }
25390
25290
  } else if (entry.isDirectory()) {
25391
25291
  copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
25392
25292
  } else {
25393
- fs7.copyFileSync(srcPath, destPath);
25293
+ fs6.copyFileSync(srcPath, destPath);
25394
25294
  }
25395
25295
  }
25396
25296
  }
@@ -25559,9 +25459,9 @@ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, conf
25559
25459
  }
25560
25460
  }
25561
25461
  for (const repo of repos) {
25562
- const worktreePath = path10.join(workspacePath, repo.name);
25462
+ const worktreePath = path9.join(workspacePath, repo.name);
25563
25463
  const sourcePath = repo.path;
25564
- if (!sourcePath || !fs7.existsSync(worktreePath))
25464
+ if (!sourcePath || !fs6.existsSync(worktreePath))
25565
25465
  continue;
25566
25466
  const envSetup = repo.env_setup;
25567
25467
  if (!envSetup)
@@ -25580,23 +25480,23 @@ function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, conf
25580
25480
  }
25581
25481
  }
25582
25482
  function copyMatchingFiles(sourcePath, destPath, pattern) {
25583
- const fullPattern = path10.join(sourcePath, pattern);
25483
+ const fullPattern = path9.join(sourcePath, pattern);
25584
25484
  if (!pattern.includes("*")) {
25585
- const sourceFile = path10.join(sourcePath, pattern);
25586
- const destFile = path10.join(destPath, pattern);
25587
- if (fs7.existsSync(sourceFile)) {
25588
- fs7.mkdirSync(path10.dirname(destFile), { recursive: true });
25589
- fs7.copyFileSync(sourceFile, destFile);
25485
+ const sourceFile = path9.join(sourcePath, pattern);
25486
+ const destFile = path9.join(destPath, pattern);
25487
+ if (fs6.existsSync(sourceFile)) {
25488
+ fs6.mkdirSync(path9.dirname(destFile), { recursive: true });
25489
+ fs6.copyFileSync(sourceFile, destFile);
25590
25490
  }
25591
25491
  return;
25592
25492
  }
25593
25493
  try {
25594
25494
  const matches2 = globSync(fullPattern);
25595
25495
  for (const match of matches2) {
25596
- const relative2 = path10.relative(sourcePath, match);
25597
- const dest = path10.join(destPath, relative2);
25598
- fs7.mkdirSync(path10.dirname(dest), { recursive: true });
25599
- fs7.copyFileSync(match, dest);
25496
+ const relative2 = path9.relative(sourcePath, match);
25497
+ const dest = path9.join(destPath, relative2);
25498
+ fs6.mkdirSync(path9.dirname(dest), { recursive: true });
25499
+ fs6.copyFileSync(match, dest);
25600
25500
  }
25601
25501
  } catch {
25602
25502
  }
@@ -25604,14 +25504,14 @@ function copyMatchingFiles(sourcePath, destPath, pattern) {
25604
25504
  function generateEnvFromExample(repoPath, overrides) {
25605
25505
  const exampleFiles = [".env.example", ".env.sample", ".env.local.example"];
25606
25506
  for (const exampleName of exampleFiles) {
25607
- const examplePath = path10.join(repoPath, exampleName);
25608
- if (!fs7.existsSync(examplePath))
25507
+ const examplePath = path9.join(repoPath, exampleName);
25508
+ if (!fs6.existsSync(examplePath))
25609
25509
  continue;
25610
25510
  const targetName = exampleName.replace(".example", "").replace(".sample", "");
25611
- const targetPath = path10.join(repoPath, targetName);
25612
- if (fs7.existsSync(targetPath))
25511
+ const targetPath = path9.join(repoPath, targetName);
25512
+ if (fs6.existsSync(targetPath))
25613
25513
  continue;
25614
- const template = fs7.readFileSync(examplePath, "utf-8");
25514
+ const template = fs6.readFileSync(examplePath, "utf-8");
25615
25515
  const generated = template.split("\n").map((line) => {
25616
25516
  const match = /^([A-Z_][A-Z0-9_]*)=(.*)$/.exec(line);
25617
25517
  if (match) {
@@ -25622,13 +25522,13 @@ function generateEnvFromExample(repoPath, overrides) {
25622
25522
  }
25623
25523
  return line;
25624
25524
  }).join("\n");
25625
- fs7.writeFileSync(targetPath, generated);
25525
+ fs6.writeFileSync(targetPath, generated);
25626
25526
  }
25627
25527
  }
25628
25528
  function applyEnvOverrides(repoPath, overrides) {
25629
- const envPath = path10.join(repoPath, ".env");
25630
- if (fs7.existsSync(envPath)) {
25631
- const existing = fs7.readFileSync(envPath, "utf-8");
25529
+ const envPath = path9.join(repoPath, ".env");
25530
+ if (fs6.existsSync(envPath)) {
25531
+ const existing = fs6.readFileSync(envPath, "utf-8");
25632
25532
  const existingKeys = new Set(existing.split("\n").map((l) => l.split("=")[0]?.trim()).filter(Boolean));
25633
25533
  const additions = [];
25634
25534
  for (const [key, value] of Object.entries(overrides)) {
@@ -25637,7 +25537,7 @@ function applyEnvOverrides(repoPath, overrides) {
25637
25537
  }
25638
25538
  }
25639
25539
  if (additions.length > 0) {
25640
- fs7.appendFileSync(envPath, "\n# Olam injected\n" + additions.join("\n") + "\n");
25540
+ fs6.appendFileSync(envPath, "\n# Olam injected\n" + additions.join("\n") + "\n");
25641
25541
  }
25642
25542
  }
25643
25543
  }
@@ -25894,7 +25794,7 @@ __export(world_crystallize_exports, {
25894
25794
  register: () => register12
25895
25795
  });
25896
25796
  import "node:path";
25897
- import * as fs8 from "node:fs";
25797
+ import * as fs7 from "node:fs";
25898
25798
 
25899
25799
  // ../core/dist/crystallize/checksum.js
25900
25800
  import { createHash as createHash2 } from "node:crypto";
@@ -25950,7 +25850,7 @@ function register12(server, ctx, initError) {
25950
25850
  }
25951
25851
  try {
25952
25852
  const thoughtDbPath = getWorldDbPath(world.workspacePath);
25953
- if (!fs8.existsSync(thoughtDbPath)) {
25853
+ if (!fs7.existsSync(thoughtDbPath)) {
25954
25854
  return {
25955
25855
  content: [{
25956
25856
  type: "text",
@@ -26536,23 +26436,23 @@ async function writeManifest(args) {
26536
26436
  capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
26537
26437
  shots: entries
26538
26438
  };
26539
- const path22 = join12(args.outDir, "manifest.json");
26540
- await writeFile(path22, `${JSON.stringify(manifest, null, 2)}
26439
+ const path21 = join12(args.outDir, "manifest.json");
26440
+ await writeFile(path21, `${JSON.stringify(manifest, null, 2)}
26541
26441
  `, "utf8");
26542
- return { path: path22, manifest };
26442
+ return { path: path21, manifest };
26543
26443
  }
26544
26444
 
26545
26445
  // ../mcp-server/src/tools/_capture/proxy.ts
26546
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync8, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
26446
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync7, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
26547
26447
  import { createServer as createServer2 } from "node:http";
26548
26448
  import { request as httpRequest } from "node:http";
26549
26449
  import { request as httpsRequest } from "node:https";
26550
26450
  import { connect as netConnect } from "node:net";
26551
- import { dirname as dirname7 } from "node:path";
26451
+ import { dirname as dirname6 } from "node:path";
26552
26452
  import { userInfo } from "node:os";
26553
26453
 
26554
26454
  // ../mcp-server/src/tools/_capture/token.ts
26555
- import { createHmac, randomBytes as randomBytes4, timingSafeEqual } from "node:crypto";
26455
+ import { createHmac, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
26556
26456
  var HOST_TTL_MAX_SEC = 600;
26557
26457
  var WORLD_TTL_MAX_SEC = 60;
26558
26458
  var WORLD_HOURLY_QUOTA = 50;
@@ -26594,7 +26494,7 @@ function loadHmacKey() {
26594
26494
  );
26595
26495
  _autoKeyWarned = true;
26596
26496
  }
26597
- _hmacKey = randomBytes4(32);
26497
+ _hmacKey = randomBytes3(32);
26598
26498
  return _hmacKey;
26599
26499
  }
26600
26500
  function base64url2(buf) {
@@ -26662,7 +26562,7 @@ function mintToken(input) {
26662
26562
  window2.count++;
26663
26563
  }
26664
26564
  }
26665
- const correlationId = base32Crockford(randomBytes4(16));
26565
+ const correlationId = base32Crockford(randomBytes3(16));
26666
26566
  const exp = Math.floor(_now() / 1e3) + ttlClamped;
26667
26567
  const scope = {
26668
26568
  allowedPaths: input.allowedPaths,
@@ -26793,9 +26693,9 @@ async function startProxy(opts) {
26793
26693
  const liveCompiled = verified.allowedPaths.map(compileGlob);
26794
26694
  const target = parseRequestTarget(req);
26795
26695
  if (!target) return httpReject(400, "invalid_target");
26796
- const path22 = target.pathname;
26797
- if (!liveCompiled.some((re) => re.test(path22))) {
26798
- return httpReject(403, "outside_allow_list", { path: path22 });
26696
+ const path21 = target.pathname;
26697
+ if (!liveCompiled.some((re) => re.test(path21))) {
26698
+ return httpReject(403, "outside_allow_list", { path: path21 });
26799
26699
  }
26800
26700
  const headerWorld = req.headers[WORLD_ASSERT_HEADER];
26801
26701
  const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
@@ -26950,7 +26850,7 @@ ${JSON.stringify({ error: reason })}`
26950
26850
  };
26951
26851
  }
26952
26852
  function ensureUdsParentDirSafe(udsPath) {
26953
- const parent = dirname7(udsPath);
26853
+ const parent = dirname6(udsPath);
26954
26854
  if (!parent || parent === udsPath || parent === ".") {
26955
26855
  throw new Error(
26956
26856
  `uds_parent_path_invalid: bindUdsPath "${udsPath}" has no manageable parent directory`
@@ -26967,7 +26867,7 @@ function ensureUdsParentDirSafe(udsPath) {
26967
26867
  }
26968
26868
  }
26969
26869
  if (!stat) {
26970
- mkdirSync8(parent, { recursive: true, mode: 448 });
26870
+ mkdirSync7(parent, { recursive: true, mode: 448 });
26971
26871
  return;
26972
26872
  }
26973
26873
  if (!stat.isDirectory()) {
@@ -27574,14 +27474,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
27574
27474
  await page.waitForTimeout(shot.afterLoadMs);
27575
27475
  }
27576
27476
  const ext = format === "jpeg" ? "jpg" : "png";
27577
- const path22 = join13(outDir, `${shot.name}.${ext}`);
27477
+ const path21 = join13(outDir, `${shot.name}.${ext}`);
27578
27478
  await page.screenshot({
27579
- path: path22,
27479
+ path: path21,
27580
27480
  type: format,
27581
27481
  ...format === "jpeg" ? { quality: jpegQuality } : {},
27582
27482
  fullPage: false
27583
27483
  });
27584
- return { name: shot.name, path: path22, urlRedacted: redactUrl(shot.url), viewport };
27484
+ return { name: shot.name, path: path21, urlRedacted: redactUrl(shot.url), viewport };
27585
27485
  } finally {
27586
27486
  await context.close();
27587
27487
  }
@@ -28024,12 +27924,12 @@ function openUrl(url) {
28024
27924
  var HOST_CP_URL = "http://127.0.0.1:19000";
28025
27925
  async function readHostCpToken2() {
28026
27926
  try {
28027
- const { default: fs18 } = await import("node:fs");
27927
+ const { default: fs17 } = await import("node:fs");
28028
27928
  const { default: os10 } = await import("node:os");
28029
- const { default: path22 } = await import("node:path");
28030
- const tp = path22.join(os10.homedir(), ".olam", "host-cp.token");
28031
- if (!fs18.existsSync(tp)) return { token: null };
28032
- return { token: fs18.readFileSync(tp, "utf-8").trim() };
27929
+ const { default: path21 } = await import("node:path");
27930
+ const tp = path21.join(os10.homedir(), ".olam", "host-cp.token");
27931
+ if (!fs17.existsSync(tp)) return { token: null };
27932
+ return { token: fs17.readFileSync(tp, "utf-8").trim() };
28033
27933
  } catch {
28034
27934
  return { token: null };
28035
27935
  }
@@ -28309,8 +28209,8 @@ function createServer3(ctx, initError) {
28309
28209
  }
28310
28210
 
28311
28211
  // ../core/dist/config/loader.js
28312
- import * as fs10 from "node:fs";
28313
- import * as path13 from "node:path";
28212
+ import * as fs9 from "node:fs";
28213
+ import * as path12 from "node:path";
28314
28214
  import { parse as parseYaml2 } from "yaml";
28315
28215
 
28316
28216
  // ../core/dist/config/schema.js
@@ -28455,19 +28355,69 @@ var AuthConfigSchema = external_exports.object({
28455
28355
  mode: authModeSchema.default("oauth"),
28456
28356
  autoInject: external_exports.boolean().default(true).describe("Copy host credentials into world at creation. Set false to use browser OAuth instead.")
28457
28357
  });
28358
+ var DevboxRegistryProviderSchema = external_exports.enum(["ghcr", "gar", "dockerhub"]);
28359
+ function inferRegistryProvider(prefix) {
28360
+ if (!prefix)
28361
+ return void 0;
28362
+ const head = prefix.split("/")[0] ?? "";
28363
+ if (!head.includes(".") && !head.includes(":"))
28364
+ return "dockerhub";
28365
+ if (head === "ghcr.io")
28366
+ return "ghcr";
28367
+ if (head === "docker.io")
28368
+ return "dockerhub";
28369
+ if (head === "gcr.io" || head.endsWith("-docker.pkg.dev") || head.endsWith(".pkg.dev")) {
28370
+ return "gar";
28371
+ }
28372
+ return void 0;
28373
+ }
28458
28374
  var DevboxRegistrySchema = external_exports.object({
28459
28375
  /**
28460
28376
  * Fully-qualified registry prefix (no trailing slash), e.g.
28461
- * "ghcr.io/<org>/olam-devbox". When set without per-tag overrides, ALL
28462
- * `olam-devbox:*` lookups are rewritten to `<prefix>:<tag>`.
28377
+ * "ghcr.io/<org>/olam-devbox" or
28378
+ * "us-central1-docker.pkg.dev/<gcp-project>/<repo>/olam-devbox".
28379
+ * When set without per-tag overrides, ALL `olam-devbox:*` lookups are
28380
+ * rewritten to `<prefix>:<tag>`.
28463
28381
  */
28464
28382
  prefix: external_exports.string().optional(),
28383
+ /**
28384
+ * Registry provider. Optional — inferred from `prefix` hostname when
28385
+ * omitted. Set explicitly to assert which provider the consumer intends
28386
+ * (a mismatch with `prefix` is a config error, not silent acceptance).
28387
+ */
28388
+ provider: DevboxRegistryProviderSchema.optional(),
28465
28389
  /**
28466
28390
  * Per-tag overrides. Wins over `prefix` when both are set. Use this when
28467
28391
  * different image tags live in different registries, or when a few tags
28468
28392
  * are local-only.
28469
28393
  */
28470
28394
  tags: external_exports.record(external_exports.string(), external_exports.string()).optional().default({})
28395
+ }).superRefine((reg, ctx) => {
28396
+ if (reg.provider && !reg.prefix) {
28397
+ ctx.addIssue({
28398
+ code: external_exports.ZodIssueCode.custom,
28399
+ path: ["prefix"],
28400
+ message: `devbox.registry.provider was set to "${reg.provider}" but no prefix was declared. Either drop the provider field or add a prefix like "<host>/<owner>/olam-devbox".`
28401
+ });
28402
+ return;
28403
+ }
28404
+ if (!reg.prefix)
28405
+ return;
28406
+ const inferred = inferRegistryProvider(reg.prefix);
28407
+ if (reg.provider && inferred && reg.provider !== inferred) {
28408
+ ctx.addIssue({
28409
+ code: external_exports.ZodIssueCode.custom,
28410
+ path: ["provider"],
28411
+ message: `devbox.registry.provider "${reg.provider}" does not match prefix "${reg.prefix}" (inferred "${inferred}" from hostname). Fix the prefix host or drop the provider field.`
28412
+ });
28413
+ }
28414
+ if (reg.provider && !inferred) {
28415
+ ctx.addIssue({
28416
+ code: external_exports.ZodIssueCode.custom,
28417
+ path: ["prefix"],
28418
+ message: `devbox.registry.prefix "${reg.prefix}" hostname is not recognised \u2014 provider "${reg.provider}" cannot be cross-checked. Recognised hosts: ghcr.io, *-docker.pkg.dev, gcr.io, docker.io, or a bare "owner/repo" (Docker Hub default).`
28419
+ });
28420
+ }
28471
28421
  });
28472
28422
  var DevboxImageSelectorSchema = external_exports.object({
28473
28423
  /** Bare tag the resolver feeds to the registry (e.g. "rails-monorepo"). */
@@ -28640,11 +28590,11 @@ function substituteEnvVars(obj) {
28640
28590
  }
28641
28591
 
28642
28592
  // ../core/dist/config/dotenv.js
28643
- import * as fs9 from "node:fs";
28593
+ import * as fs8 from "node:fs";
28644
28594
  function loadDotEnv(envPath) {
28645
- if (!fs9.existsSync(envPath))
28595
+ if (!fs8.existsSync(envPath))
28646
28596
  return;
28647
- const content = fs9.readFileSync(envPath, "utf-8");
28597
+ const content = fs8.readFileSync(envPath, "utf-8");
28648
28598
  for (const line of content.split("\n")) {
28649
28599
  const trimmed = line.trim();
28650
28600
  if (!trimmed || trimmed.startsWith("#"))
@@ -28663,18 +28613,18 @@ function loadDotEnv(envPath) {
28663
28613
  // ../core/dist/config/loader.js
28664
28614
  function findConfigFile(startDir) {
28665
28615
  const searched = [];
28666
- let current = path13.resolve(startDir);
28616
+ let current = path12.resolve(startDir);
28667
28617
  while (true) {
28668
- const newLayout = path13.join(current, CONFIG_DIR_NAME, CONFIG_FILENAME);
28669
- const legacyLayout = path13.join(current, LEGACY_CONFIG_FILENAME);
28618
+ const newLayout = path12.join(current, CONFIG_DIR_NAME, CONFIG_FILENAME);
28619
+ const legacyLayout = path12.join(current, LEGACY_CONFIG_FILENAME);
28670
28620
  searched.push(newLayout, legacyLayout);
28671
- if (fs10.existsSync(newLayout)) {
28621
+ if (fs9.existsSync(newLayout)) {
28672
28622
  return { path: newLayout, isLegacy: false };
28673
28623
  }
28674
- if (fs10.existsSync(legacyLayout)) {
28624
+ if (fs9.existsSync(legacyLayout)) {
28675
28625
  return { path: legacyLayout, isLegacy: true };
28676
28626
  }
28677
- const parent = path13.dirname(current);
28627
+ const parent = path12.dirname(current);
28678
28628
  if (parent === current)
28679
28629
  break;
28680
28630
  current = parent;
@@ -28689,12 +28639,12 @@ function loadConfig(startDir) {
28689
28639
  Run /olam:init to migrate to .olam/config.yaml
28690
28640
  `);
28691
28641
  } else {
28692
- const envPath = path13.join(path13.dirname(found.path), ".env");
28642
+ const envPath = path12.join(path12.dirname(found.path), ".env");
28693
28643
  loadDotEnv(envPath);
28694
28644
  }
28695
28645
  let rawContent;
28696
28646
  try {
28697
- rawContent = fs10.readFileSync(found.path, "utf-8");
28647
+ rawContent = fs9.readFileSync(found.path, "utf-8");
28698
28648
  } catch (err) {
28699
28649
  throw new Error(`Failed to read ${found.path}: ${err instanceof Error ? err.message : String(err)}`);
28700
28650
  }
@@ -28724,11 +28674,11 @@ function loadConfig(startDir) {
28724
28674
  }
28725
28675
 
28726
28676
  // ../core/dist/world/manager.js
28727
- import * as crypto5 from "node:crypto";
28677
+ import * as crypto4 from "node:crypto";
28728
28678
  import { execSync as execSync4 } from "node:child_process";
28729
- import * as fs15 from "node:fs";
28679
+ import * as fs14 from "node:fs";
28730
28680
  import * as os8 from "node:os";
28731
- import * as path19 from "node:path";
28681
+ import * as path18 from "node:path";
28732
28682
 
28733
28683
  // ../core/dist/world/state.js
28734
28684
  var VALID_TRANSITIONS = {
@@ -28810,8 +28760,8 @@ function resolveDevboxImage(config2, tag) {
28810
28760
 
28811
28761
  // ../core/dist/world/worktree.js
28812
28762
  import { execFileSync as execFileSync2 } from "node:child_process";
28813
- import * as fs11 from "node:fs";
28814
- import * as path14 from "node:path";
28763
+ import * as fs10 from "node:fs";
28764
+ import * as path13 from "node:path";
28815
28765
  function resolveGitDir(repo) {
28816
28766
  if (repo.path) {
28817
28767
  return repo.path;
@@ -28821,11 +28771,11 @@ function resolveGitDir(repo) {
28821
28771
  async function createWorktrees(repos, worldId, workspacePath, branch) {
28822
28772
  const created = [];
28823
28773
  for (const repo of repos) {
28824
- const worktreePath = path14.join(workspacePath, repo.name);
28774
+ const worktreePath = path13.join(workspacePath, repo.name);
28825
28775
  const gitDir = resolveGitDir(repo);
28826
28776
  const branchName = branch || `olam/${worldId}`;
28827
28777
  try {
28828
- fs11.mkdirSync(path14.dirname(worktreePath), { recursive: true });
28778
+ fs10.mkdirSync(path13.dirname(worktreePath), { recursive: true });
28829
28779
  execFileSync2("git", ["worktree", "add", worktreePath, "-b", branchName], {
28830
28780
  cwd: gitDir,
28831
28781
  stdio: "pipe"
@@ -28858,7 +28808,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
28858
28808
  }
28859
28809
  async function removeWorktrees(repos, workspacePath) {
28860
28810
  for (const repo of repos) {
28861
- const worktreePath = path14.join(workspacePath, repo.name);
28811
+ const worktreePath = path13.join(workspacePath, repo.name);
28862
28812
  let gitDir;
28863
28813
  try {
28864
28814
  gitDir = resolveGitDir(repo);
@@ -28933,9 +28883,9 @@ function removeBranch(repo, branch) {
28933
28883
 
28934
28884
  // ../core/dist/world/baseline-diff.js
28935
28885
  import { execFileSync as execFileSync3 } from "node:child_process";
28936
- import * as fs12 from "node:fs";
28886
+ import * as fs11 from "node:fs";
28937
28887
  import * as os7 from "node:os";
28938
- import * as path15 from "node:path";
28888
+ import * as path14 from "node:path";
28939
28889
  var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
28940
28890
  function expandHome(p, homedir11) {
28941
28891
  return p.replace(/^~(?=$|\/|\\)/, homedir11());
@@ -28962,9 +28912,9 @@ ${stderr}`;
28962
28912
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
28963
28913
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
28964
28914
  const homedir11 = deps.homedir ?? (() => os7.homedir());
28965
- const baselineDir = path15.join(workspacePath, ".olam", "baseline");
28915
+ const baselineDir = path14.join(workspacePath, ".olam", "baseline");
28966
28916
  try {
28967
- fs12.mkdirSync(baselineDir, { recursive: true });
28917
+ fs11.mkdirSync(baselineDir, { recursive: true });
28968
28918
  } catch (err) {
28969
28919
  const msg = err instanceof Error ? err.message : String(err);
28970
28920
  console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
@@ -28976,9 +28926,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
28976
28926
  if (!repo.path)
28977
28927
  continue;
28978
28928
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
28979
- const outPath = path15.join(baselineDir, filename);
28929
+ const outPath = path14.join(baselineDir, filename);
28980
28930
  const repoPath = expandHome(repo.path, homedir11);
28981
- if (!fs12.existsSync(repoPath)) {
28931
+ if (!fs11.existsSync(repoPath)) {
28982
28932
  writeBaselineFile(outPath, `# repo: ${repo.name}
28983
28933
  # (skipped: path ${repoPath} does not exist)
28984
28934
  `);
@@ -29045,7 +28995,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
29045
28995
  }
29046
28996
  function writeBaselineFile(outPath, content) {
29047
28997
  try {
29048
- fs12.writeFileSync(outPath, content);
28998
+ fs11.writeFileSync(outPath, content);
29049
28999
  } catch (err) {
29050
29000
  const msg = err instanceof Error ? err.message : String(err);
29051
29001
  console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
@@ -29053,8 +29003,8 @@ function writeBaselineFile(outPath, content) {
29053
29003
  }
29054
29004
  function stripWorktreeEdits(repos, workspacePath) {
29055
29005
  for (const repo of repos) {
29056
- const worktreePath = path15.join(workspacePath, repo.name);
29057
- if (!fs12.existsSync(worktreePath))
29006
+ const worktreePath = path14.join(workspacePath, repo.name);
29007
+ if (!fs11.existsSync(worktreePath))
29058
29008
  continue;
29059
29009
  try {
29060
29010
  execFileSync3("git", ["checkout", "--", "."], {
@@ -29084,12 +29034,12 @@ function formatBaselineSummary(result) {
29084
29034
  }
29085
29035
 
29086
29036
  // ../core/dist/world/context-injection.js
29087
- import * as fs13 from "node:fs";
29088
- import * as path16 from "node:path";
29037
+ import * as fs12 from "node:fs";
29038
+ import * as path15 from "node:path";
29089
29039
  function injectWorldContext(opts) {
29090
29040
  const { world, task, linearTicketId, claudeMdExtra, taskContext, services, pleriPlaneUrl } = opts;
29091
- const claudeDir = path16.join(world.workspacePath, ".claude");
29092
- fs13.mkdirSync(claudeDir, { recursive: true });
29041
+ const claudeDir = path15.join(world.workspacePath, ".claude");
29042
+ fs12.mkdirSync(claudeDir, { recursive: true });
29093
29043
  const sections = [];
29094
29044
  sections.push(`# Olam World: ${world.name}`);
29095
29045
  sections.push("");
@@ -29250,7 +29200,7 @@ function injectWorldContext(opts) {
29250
29200
  sections.push("");
29251
29201
  }
29252
29202
  const content = sections.join("\n");
29253
- fs13.writeFileSync(path16.join(claudeDir, "CLAUDE.md"), content);
29203
+ fs12.writeFileSync(path15.join(claudeDir, "CLAUDE.md"), content);
29254
29204
  }
29255
29205
  function formatTaskSource(ctx) {
29256
29206
  if (ctx.source === "linear" && ctx.ticketId) {
@@ -29264,9 +29214,9 @@ function formatTaskSource(ctx) {
29264
29214
  function hasPlanFile(world) {
29265
29215
  if (world.repos.length === 0)
29266
29216
  return false;
29267
- const plansDir = path16.join(world.workspacePath, world.repos[0], "docs", "plans");
29217
+ const plansDir = path15.join(world.workspacePath, world.repos[0], "docs", "plans");
29268
29218
  try {
29269
- return fs13.existsSync(plansDir) && fs13.readdirSync(plansDir).length > 0;
29219
+ return fs12.existsSync(plansDir) && fs12.readdirSync(plansDir).length > 0;
29270
29220
  } catch {
29271
29221
  return false;
29272
29222
  }
@@ -29493,7 +29443,7 @@ async function installStack(exec, repos, stacks) {
29493
29443
 
29494
29444
  // ../core/dist/world/stack-image.js
29495
29445
  import { execSync as execSync2 } from "node:child_process";
29496
- import * as crypto4 from "node:crypto";
29446
+ import * as crypto3 from "node:crypto";
29497
29447
  var BASE_IMAGE = "olam-devbox";
29498
29448
  var LABEL_PREFIX = "olam.stack-image";
29499
29449
  var MAX_TAG_LENGTH = 128;
@@ -29547,14 +29497,14 @@ function getBaseImageDigest() {
29547
29497
  cachedBaseDigest = digest.replace("sha256:", "").slice(0, 16);
29548
29498
  return cachedBaseDigest;
29549
29499
  } catch {
29550
- cachedBaseDigest = crypto4.createHash("sha256").update("unknown").digest("hex").slice(0, 16);
29500
+ cachedBaseDigest = crypto3.createHash("sha256").update("unknown").digest("hex").slice(0, 16);
29551
29501
  return cachedBaseDigest;
29552
29502
  }
29553
29503
  }
29554
29504
  function sanitizeTag(raw) {
29555
29505
  let tag = raw.toLowerCase().replace(/[^a-z0-9._-]/g, "-");
29556
29506
  if (tag.length > MAX_TAG_LENGTH) {
29557
- const hash = crypto4.createHash("sha256").update(raw).digest("hex").slice(0, 12);
29507
+ const hash = crypto3.createHash("sha256").update(raw).digest("hex").slice(0, 12);
29558
29508
  tag = tag.slice(0, MAX_TAG_LENGTH - 13) + "_" + hash;
29559
29509
  }
29560
29510
  return tag;
@@ -29932,14 +29882,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
29932
29882
  }
29933
29883
 
29934
29884
  // ../core/dist/world/olam-yaml.js
29935
- import * as path17 from "node:path";
29885
+ import * as path16 from "node:path";
29936
29886
  import YAML2 from "yaml";
29937
29887
  function enrichReposWithManifests(repos, workspacePath) {
29938
29888
  return repos.map((repo) => {
29939
29889
  if (repo.manifest !== void 0 && repo.manifest !== null) {
29940
29890
  return repo;
29941
29891
  }
29942
- const repoDir = path17.join(workspacePath, repo.name);
29892
+ const repoDir = path16.join(workspacePath, repo.name);
29943
29893
  let manifest = null;
29944
29894
  try {
29945
29895
  manifest = loadRepoManifest(repoDir);
@@ -29954,8 +29904,8 @@ function enrichReposWithManifests(repos, workspacePath) {
29954
29904
  }
29955
29905
 
29956
29906
  // ../core/dist/policies/loader.js
29957
- import * as fs14 from "node:fs";
29958
- import * as path18 from "node:path";
29907
+ import * as fs13 from "node:fs";
29908
+ import * as path17 from "node:path";
29959
29909
  import { parse as parseYaml3 } from "yaml";
29960
29910
  function parseFrontmatter(content) {
29961
29911
  const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
@@ -29975,20 +29925,20 @@ function toStringArray(v) {
29975
29925
  return v.filter((x) => typeof x === "string");
29976
29926
  }
29977
29927
  function loadPolicies(workspaceRoot) {
29978
- const policiesDir = path18.join(workspaceRoot, ".olam", "policies");
29979
- if (!fs14.existsSync(policiesDir))
29928
+ const policiesDir = path17.join(workspaceRoot, ".olam", "policies");
29929
+ if (!fs13.existsSync(policiesDir))
29980
29930
  return [];
29981
29931
  let files;
29982
29932
  try {
29983
- files = fs14.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
29933
+ files = fs13.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
29984
29934
  } catch {
29985
29935
  return [];
29986
29936
  }
29987
29937
  const policies = [];
29988
29938
  for (const file of files) {
29989
- const filePath = path18.join(policiesDir, file);
29939
+ const filePath = path17.join(policiesDir, file);
29990
29940
  try {
29991
- const content = fs14.readFileSync(filePath, "utf8");
29941
+ const content = fs13.readFileSync(filePath, "utf8");
29992
29942
  const parsed = parseFrontmatter(content);
29993
29943
  if (!parsed) {
29994
29944
  console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
@@ -30475,15 +30425,6 @@ var WorkspaceNotFoundError = class extends Error {
30475
30425
  this.name = "WorkspaceNotFoundError";
30476
30426
  }
30477
30427
  };
30478
- var RepoSelectionRequiredError = class extends Error {
30479
- availableRepos;
30480
- constructor(availableRepos) {
30481
- const list = availableRepos.length > 0 ? availableRepos.join(", ") : "(none configured)";
30482
- super(`--repos or --workspace is required. Available repos: ${list}. Pick the subset you actually want \u2014 implicit "all repos" was removed to prevent accidental multi-repo bootstraps.`);
30483
- this.availableRepos = availableRepos;
30484
- this.name = "RepoSelectionRequiredError";
30485
- }
30486
- };
30487
30428
  function buildManifestRuntime(worldId, repos) {
30488
30429
  const runtimeRepos = [];
30489
30430
  for (const repo of repos) {
@@ -30536,7 +30477,7 @@ var WorldManager = class {
30536
30477
  }
30537
30478
  }
30538
30479
  const worldId = generateWorldId();
30539
- const workspacePath = path19.join(os8.homedir(), ".olam", "worlds", worldId);
30480
+ const workspacePath = path18.join(os8.homedir(), ".olam", "worlds", worldId);
30540
30481
  const portOffset = this.registry.getNextPortOffset();
30541
30482
  const branch = opts.branchName ?? `olam/${worldId}`;
30542
30483
  const repos = this.resolveReposWithWorkspace(opts);
@@ -30593,37 +30534,37 @@ var WorldManager = class {
30593
30534
  if (!repo.path)
30594
30535
  continue;
30595
30536
  const sourceRoot = repo.path.replace(/^~/, os8.homedir());
30596
- const worktreeRoot = path19.join(workspacePath, repo.name);
30597
- if (!fs15.existsSync(sourceRoot) || !fs15.existsSync(worktreeRoot))
30537
+ const worktreeRoot = path18.join(workspacePath, repo.name);
30538
+ if (!fs14.existsSync(sourceRoot) || !fs14.existsSync(worktreeRoot))
30598
30539
  continue;
30599
30540
  let copied = 0;
30600
30541
  for (const pattern of RUNTIME_FILE_PATTERNS) {
30601
30542
  const matches2 = [];
30602
30543
  if (pattern.includes("*")) {
30603
- const [dir, glob] = [path19.dirname(pattern), path19.basename(pattern)];
30604
- const sourceDir = path19.join(sourceRoot, dir);
30605
- if (fs15.existsSync(sourceDir)) {
30544
+ const [dir, glob] = [path18.dirname(pattern), path18.basename(pattern)];
30545
+ const sourceDir = path18.join(sourceRoot, dir);
30546
+ if (fs14.existsSync(sourceDir)) {
30606
30547
  const ext = glob.replace(/^\*+/, "");
30607
30548
  try {
30608
- for (const entry of fs15.readdirSync(sourceDir)) {
30549
+ for (const entry of fs14.readdirSync(sourceDir)) {
30609
30550
  if (ext === "" || entry.endsWith(ext))
30610
- matches2.push(path19.join(dir, entry));
30551
+ matches2.push(path18.join(dir, entry));
30611
30552
  }
30612
30553
  } catch {
30613
30554
  }
30614
30555
  }
30615
- } else if (fs15.existsSync(path19.join(sourceRoot, pattern))) {
30556
+ } else if (fs14.existsSync(path18.join(sourceRoot, pattern))) {
30616
30557
  matches2.push(pattern);
30617
30558
  }
30618
30559
  for (const rel of matches2) {
30619
- const src = path19.join(sourceRoot, rel);
30620
- const dst = path19.join(worktreeRoot, rel);
30560
+ const src = path18.join(sourceRoot, rel);
30561
+ const dst = path18.join(worktreeRoot, rel);
30621
30562
  try {
30622
- const st = fs15.statSync(src);
30563
+ const st = fs14.statSync(src);
30623
30564
  if (!st.isFile())
30624
30565
  continue;
30625
- fs15.mkdirSync(path19.dirname(dst), { recursive: true });
30626
- fs15.copyFileSync(src, dst);
30566
+ fs14.mkdirSync(path18.dirname(dst), { recursive: true });
30567
+ fs14.copyFileSync(src, dst);
30627
30568
  copied++;
30628
30569
  } catch {
30629
30570
  }
@@ -30723,7 +30664,7 @@ var WorldManager = class {
30723
30664
  try {
30724
30665
  const hostExec = makeHostExecFn();
30725
30666
  for (const repo of repos) {
30726
- const repoDir = path19.join(workspacePath, repo.name);
30667
+ const repoDir = path18.join(workspacePath, repo.name);
30727
30668
  if (repo.stack && Object.keys(repo.stack).length > 0) {
30728
30669
  preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
30729
30670
  } else {
@@ -30780,10 +30721,10 @@ var WorldManager = class {
30780
30721
  const worldEnv = {};
30781
30722
  if (opts.task)
30782
30723
  worldEnv.OLAM_TASK = opts.task;
30783
- const r2CredsPath = path19.join(os8.homedir(), ".olam", "r2-credentials.json");
30784
- if (fs15.existsSync(r2CredsPath)) {
30724
+ const r2CredsPath = path18.join(os8.homedir(), ".olam", "r2-credentials.json");
30725
+ if (fs14.existsSync(r2CredsPath)) {
30785
30726
  try {
30786
- const r2Raw = fs15.readFileSync(r2CredsPath, "utf-8").trim();
30727
+ const r2Raw = fs14.readFileSync(r2CredsPath, "utf-8").trim();
30787
30728
  if (r2Raw.length > 0) {
30788
30729
  const r2 = JSON.parse(r2Raw);
30789
30730
  if (typeof r2.account_id === "string")
@@ -30800,10 +30741,10 @@ var WorldManager = class {
30800
30741
  } catch {
30801
30742
  }
30802
30743
  }
30803
- const keysYamlPath = path19.join(os8.homedir(), ".olam", "keys.yaml");
30804
- if (fs15.existsSync(keysYamlPath)) {
30744
+ const keysYamlPath = path18.join(os8.homedir(), ".olam", "keys.yaml");
30745
+ if (fs14.existsSync(keysYamlPath)) {
30805
30746
  try {
30806
- const keysRaw = fs15.readFileSync(keysYamlPath, "utf-8").trim();
30747
+ const keysRaw = fs14.readFileSync(keysYamlPath, "utf-8").trim();
30807
30748
  if (keysRaw.length > 0) {
30808
30749
  const parsed = YAML3.parse(keysRaw);
30809
30750
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
@@ -30850,10 +30791,10 @@ var WorldManager = class {
30850
30791
  worldEnv[k] = v;
30851
30792
  }
30852
30793
  for (const { repoName, relativePath, content } of fileWrites) {
30853
- const absPath = path19.join(workspacePath, repoName, relativePath);
30794
+ const absPath = path18.join(workspacePath, repoName, relativePath);
30854
30795
  try {
30855
- fs15.mkdirSync(path19.dirname(absPath), { recursive: true });
30856
- fs15.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
30796
+ fs14.mkdirSync(path18.dirname(absPath), { recursive: true });
30797
+ fs14.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
30857
30798
  mode: 384
30858
30799
  });
30859
30800
  console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
@@ -31005,7 +30946,7 @@ var WorldManager = class {
31005
30946
  let taskWithPolicies = opts.task;
31006
30947
  try {
31007
30948
  const allPolicies = repos.flatMap((repo) => {
31008
- const repoWorktree = path19.join(workspacePath, repo.name);
30949
+ const repoWorktree = path18.join(workspacePath, repo.name);
31009
30950
  return loadPolicies(repoWorktree);
31010
30951
  });
31011
30952
  const seen = /* @__PURE__ */ new Set();
@@ -31021,8 +30962,8 @@ var WorldManager = class {
31021
30962
  ${opts.task}`;
31022
30963
  execSync4(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
31023
30964
  for (const repo of repos) {
31024
- const policiesDir = path19.join(workspacePath, repo.name, ".olam", "policies");
31025
- if (fs15.existsSync(policiesDir)) {
30965
+ const policiesDir = path18.join(workspacePath, repo.name, ".olam", "policies");
30966
+ if (fs14.existsSync(policiesDir)) {
31026
30967
  execSync4(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
31027
30968
  }
31028
30969
  }
@@ -31101,8 +31042,8 @@ ${opts.task}`;
31101
31042
  } catch {
31102
31043
  }
31103
31044
  try {
31104
- fs15.rmSync(world.workspacePath, { recursive: true, force: true });
31105
- if (fs15.existsSync(world.workspacePath)) {
31045
+ fs14.rmSync(world.workspacePath, { recursive: true, force: true });
31046
+ if (fs14.existsSync(world.workspacePath)) {
31106
31047
  console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
31107
31048
  }
31108
31049
  } catch (err) {
@@ -31157,10 +31098,7 @@ ${opts.task}`;
31157
31098
  * Resolution precedence (matches the CF worker exactly):
31158
31099
  * 1. inline `opts.repos` names → look up in `config.repos`
31159
31100
  * 2. named `opts.workspace` → load catalog YAML, map via workspaceToRepoConfigs
31160
- * 3. neitherthrow `RepoSelectionRequiredError`. The historical
31161
- * "include every repo in config.yaml" fallback silently fanned a
31162
- * single-repo audit into 7-repo bootstraps and steered
31163
- * `image_selectors` to a wider tag than intended.
31101
+ * 3. fallbackevery repo declared in the project's config.yaml
31164
31102
  */
31165
31103
  resolveReposWithWorkspace(opts) {
31166
31104
  if (opts.repos && opts.repos.length > 0) {
@@ -31172,7 +31110,7 @@ ${opts.task}`;
31172
31110
  throw new WorkspaceNotFoundError(opts.workspace);
31173
31111
  return workspaceToRepoConfigs(ws);
31174
31112
  }
31175
- throw new RepoSelectionRequiredError(this.config.repos.map((r) => r.name));
31113
+ return this.resolveRepos(void 0);
31176
31114
  }
31177
31115
  resolveRepos(repoNames) {
31178
31116
  if (!repoNames || repoNames.length === 0) {
@@ -31190,14 +31128,14 @@ ${opts.task}`;
31190
31128
  return names.map((name) => this.config.repos.find((r) => r.name === name)).filter((r) => r !== void 0);
31191
31129
  }
31192
31130
  transportPlanFile(planFilePath, workspacePath, repoNames) {
31193
- const planContent = fs15.readFileSync(planFilePath, "utf-8");
31194
- const planFileName = path19.basename(planFilePath);
31131
+ const planContent = fs14.readFileSync(planFilePath, "utf-8");
31132
+ const planFileName = path18.basename(planFilePath);
31195
31133
  const targetRepo = repoNames[0];
31196
31134
  if (!targetRepo)
31197
31135
  return;
31198
- const plansDir = path19.join(workspacePath, targetRepo, "docs", "plans");
31199
- fs15.mkdirSync(plansDir, { recursive: true });
31200
- fs15.writeFileSync(path19.join(plansDir, planFileName), planContent);
31136
+ const plansDir = path18.join(workspacePath, targetRepo, "docs", "plans");
31137
+ fs14.mkdirSync(plansDir, { recursive: true });
31138
+ fs14.writeFileSync(path18.join(plansDir, planFileName), planContent);
31201
31139
  }
31202
31140
  resolveServices(repos) {
31203
31141
  const services = [];
@@ -31282,8 +31220,8 @@ import * as http2 from "node:http";
31282
31220
 
31283
31221
  // ../core/dist/dashboard/server.js
31284
31222
  import * as http from "node:http";
31285
- import * as fs16 from "node:fs";
31286
- import * as path20 from "node:path";
31223
+ import * as fs15 from "node:fs";
31224
+ import * as path19 from "node:path";
31287
31225
  import { fileURLToPath as fileURLToPath2 } from "node:url";
31288
31226
 
31289
31227
  // ../core/dist/dashboard/serialize.js
@@ -31618,7 +31556,7 @@ function notFound(res) {
31618
31556
  }
31619
31557
  function openThoughtStore(workspacePath) {
31620
31558
  const dbPath = getWorldDbPath(workspacePath);
31621
- if (!fs16.existsSync(dbPath))
31559
+ if (!fs15.existsSync(dbPath))
31622
31560
  return null;
31623
31561
  return new ThoughtLocalStore(dbPath);
31624
31562
  }
@@ -31789,13 +31727,13 @@ function findSessionInWorld(registry2, sessionId) {
31789
31727
  }
31790
31728
  function createDashboardServer(opts) {
31791
31729
  const { port, registry: registry2 } = opts;
31792
- const thisDir = path20.dirname(fileURLToPath2(import.meta.url));
31793
- const defaultPublicDir = path20.resolve(thisDir, "../../../control-plane/public");
31730
+ const thisDir = path19.dirname(fileURLToPath2(import.meta.url));
31731
+ const defaultPublicDir = path19.resolve(thisDir, "../../../control-plane/public");
31794
31732
  const publicDir = opts.publicDir ?? defaultPublicDir;
31795
- let hasPublicDir = fs16.existsSync(publicDir);
31733
+ let hasPublicDir = fs15.existsSync(publicDir);
31796
31734
  const server = http.createServer((req, res) => {
31797
31735
  if (!hasPublicDir) {
31798
- hasPublicDir = fs16.existsSync(publicDir);
31736
+ hasPublicDir = fs15.existsSync(publicDir);
31799
31737
  }
31800
31738
  const host = req.headers.host ?? `localhost:${port}`;
31801
31739
  const url = new URL(req.url ?? "/", `http://${host}`);
@@ -32069,22 +32007,22 @@ function createDashboardServer(opts) {
32069
32007
  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>`);
32070
32008
  return;
32071
32009
  }
32072
- let filePath = path20.join(publicDir, pathname === "/" ? "index.html" : pathname);
32010
+ let filePath = path19.join(publicDir, pathname === "/" ? "index.html" : pathname);
32073
32011
  if (!filePath.startsWith(publicDir)) {
32074
32012
  notFound(res);
32075
32013
  return;
32076
32014
  }
32077
- if (fs16.existsSync(filePath) && fs16.statSync(filePath).isFile()) {
32078
- const ext = path20.extname(filePath);
32015
+ if (fs15.existsSync(filePath) && fs15.statSync(filePath).isFile()) {
32016
+ const ext = path19.extname(filePath);
32079
32017
  const contentType = MIME[ext] ?? "application/octet-stream";
32080
32018
  res.writeHead(200, { "Content-Type": contentType });
32081
- fs16.createReadStream(filePath).pipe(res);
32019
+ fs15.createReadStream(filePath).pipe(res);
32082
32020
  return;
32083
32021
  }
32084
- filePath = path20.join(publicDir, "index.html");
32085
- if (fs16.existsSync(filePath)) {
32022
+ filePath = path19.join(publicDir, "index.html");
32023
+ if (fs15.existsSync(filePath)) {
32086
32024
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
32087
- fs16.createReadStream(filePath).pipe(res);
32025
+ fs15.createReadStream(filePath).pipe(res);
32088
32026
  return;
32089
32027
  }
32090
32028
  notFound(res);
@@ -32094,17 +32032,17 @@ function createDashboardServer(opts) {
32094
32032
  }
32095
32033
 
32096
32034
  // ../core/dist/dashboard/state.js
32097
- import * as fs17 from "node:fs";
32035
+ import * as fs16 from "node:fs";
32098
32036
  import * as os9 from "node:os";
32099
- import * as path21 from "node:path";
32100
- var STATE_PATH = path21.join(os9.homedir(), ".olam", "dashboard.json");
32037
+ import * as path20 from "node:path";
32038
+ var STATE_PATH = path20.join(os9.homedir(), ".olam", "dashboard.json");
32101
32039
  function saveDashboardState(state) {
32102
- fs17.mkdirSync(path21.dirname(STATE_PATH), { recursive: true });
32103
- fs17.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
32040
+ fs16.mkdirSync(path20.dirname(STATE_PATH), { recursive: true });
32041
+ fs16.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
32104
32042
  }
32105
32043
  function loadDashboardState() {
32106
32044
  try {
32107
- const raw = fs17.readFileSync(STATE_PATH, "utf-8");
32045
+ const raw = fs16.readFileSync(STATE_PATH, "utf-8");
32108
32046
  return JSON.parse(raw);
32109
32047
  } catch {
32110
32048
  return null;
@@ -32112,7 +32050,7 @@ function loadDashboardState() {
32112
32050
  }
32113
32051
  function clearDashboardState() {
32114
32052
  try {
32115
- fs17.unlinkSync(STATE_PATH);
32053
+ fs16.unlinkSync(STATE_PATH);
32116
32054
  } catch {
32117
32055
  }
32118
32056
  }
@@ -32392,8 +32330,8 @@ var PleriClient = class {
32392
32330
  };
32393
32331
 
32394
32332
  // ../mcp-server/src/env-loader.ts
32395
- import { readFileSync as readFileSync15, existsSync as existsSync18, statSync as statSync6 } from "node:fs";
32396
- import { join as join23, dirname as dirname13, resolve as resolve5 } from "node:path";
32333
+ import { readFileSync as readFileSync14, existsSync as existsSync17, statSync as statSync6 } from "node:fs";
32334
+ import { join as join23, dirname as dirname12, resolve as resolve5 } from "node:path";
32397
32335
  var PROJECT_MARKERS = [
32398
32336
  ".olam/config.yaml",
32399
32337
  ".olam/config.yml",
@@ -32405,26 +32343,26 @@ function findProjectRoot2(startDir) {
32405
32343
  const root = resolve5("/");
32406
32344
  while (true) {
32407
32345
  for (const marker of PROJECT_MARKERS) {
32408
- if (existsSync18(join23(dir, marker))) return dir;
32346
+ if (existsSync17(join23(dir, marker))) return dir;
32409
32347
  }
32410
32348
  const pkg = join23(dir, "package.json");
32411
- if (existsSync18(pkg)) {
32349
+ if (existsSync17(pkg)) {
32412
32350
  try {
32413
- const json = JSON.parse(readFileSync15(pkg, "utf8"));
32351
+ const json = JSON.parse(readFileSync14(pkg, "utf8"));
32414
32352
  const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
32415
32353
  const hasOlamDep = json.dependencies && Object.keys(json.dependencies).some((k) => k.startsWith("@olam/")) || json.devDependencies && Object.keys(json.devDependencies).some((k) => k.startsWith("@olam/"));
32416
32354
  if (isOlamWorkspace || hasOlamDep) return dir;
32417
32355
  } catch {
32418
32356
  }
32419
32357
  }
32420
- const parent = dirname13(dir);
32358
+ const parent = dirname12(dir);
32421
32359
  if (parent === dir || parent === root) return null;
32422
32360
  dir = parent;
32423
32361
  }
32424
32362
  }
32425
- function parseEnvFile(path22) {
32363
+ function parseEnvFile(path21) {
32426
32364
  const out = {};
32427
- const raw = readFileSync15(path22, "utf8");
32365
+ const raw = readFileSync14(path21, "utf8");
32428
32366
  for (const line of raw.split(/\r?\n/)) {
32429
32367
  const trimmed = line.trim();
32430
32368
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -32448,7 +32386,7 @@ function loadProjectEnv(startDir = process.cwd()) {
32448
32386
  const merged = {};
32449
32387
  for (const name of [".env", ".env.local"]) {
32450
32388
  const p = join23(root, name);
32451
- if (existsSync18(p) && statSync6(p).isFile()) {
32389
+ if (existsSync17(p) && statSync6(p).isFile()) {
32452
32390
  Object.assign(merged, parseEnvFile(p));
32453
32391
  filesRead.push(p);
32454
32392
  }