@pleri/olam-cli 0.1.148 → 0.1.151

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 (86) hide show
  1. package/dist/agent-stream/agent-sdk-to-chunks.js +276 -0
  2. package/dist/agent-stream/agent-stream-launch.js +348 -0
  3. package/dist/agent-stream/chunks-subscriber-transport.js +262 -0
  4. package/dist/agent-stream/codex-runner.js +188 -0
  5. package/dist/agent-stream/driver-runner.js +347 -0
  6. package/dist/agent-stream/operator-subscription.js +179 -0
  7. package/dist/commands/create.d.ts.map +1 -1
  8. package/dist/commands/create.js +39 -0
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/doctor.d.ts +23 -0
  11. package/dist/commands/doctor.d.ts.map +1 -1
  12. package/dist/commands/doctor.js +77 -3
  13. package/dist/commands/doctor.js.map +1 -1
  14. package/dist/commands/init.d.ts +46 -0
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +90 -0
  17. package/dist/commands/init.js.map +1 -1
  18. package/dist/commands/kg-build.d.ts +23 -0
  19. package/dist/commands/kg-build.d.ts.map +1 -1
  20. package/dist/commands/kg-build.js +104 -2
  21. package/dist/commands/kg-build.js.map +1 -1
  22. package/dist/commands/restart.d.ts +18 -0
  23. package/dist/commands/restart.d.ts.map +1 -0
  24. package/dist/commands/restart.js +113 -0
  25. package/dist/commands/restart.js.map +1 -0
  26. package/dist/commands/setup-linux-gate.d.ts +26 -0
  27. package/dist/commands/setup-linux-gate.d.ts.map +1 -0
  28. package/dist/commands/setup-linux-gate.js +42 -0
  29. package/dist/commands/setup-linux-gate.js.map +1 -0
  30. package/dist/commands/setup-metrics.d.ts +26 -0
  31. package/dist/commands/setup-metrics.d.ts.map +1 -0
  32. package/dist/commands/setup-metrics.js +57 -0
  33. package/dist/commands/setup-metrics.js.map +1 -0
  34. package/dist/commands/setup-phase-5a-skill-source.d.ts +68 -0
  35. package/dist/commands/setup-phase-5a-skill-source.d.ts.map +1 -0
  36. package/dist/commands/setup-phase-5a-skill-source.js +196 -0
  37. package/dist/commands/setup-phase-5a-skill-source.js.map +1 -0
  38. package/dist/commands/setup-phase-5b-project-sweep.d.ts +38 -0
  39. package/dist/commands/setup-phase-5b-project-sweep.d.ts.map +1 -0
  40. package/dist/commands/setup-phase-5b-project-sweep.js +175 -0
  41. package/dist/commands/setup-phase-5b-project-sweep.js.map +1 -0
  42. package/dist/commands/setup.d.ts +19 -0
  43. package/dist/commands/setup.d.ts.map +1 -1
  44. package/dist/commands/setup.js +22 -0
  45. package/dist/commands/setup.js.map +1 -1
  46. package/dist/commands/skills-10x.d.ts +23 -0
  47. package/dist/commands/skills-10x.d.ts.map +1 -0
  48. package/dist/commands/skills-10x.js +308 -0
  49. package/dist/commands/skills-10x.js.map +1 -0
  50. package/dist/image-digests.json +7 -7
  51. package/dist/index.js +17878 -15826
  52. package/dist/index.js.map +1 -1
  53. package/dist/lib/build-if-stale.d.ts +33 -0
  54. package/dist/lib/build-if-stale.d.ts.map +1 -0
  55. package/dist/lib/build-if-stale.js +156 -0
  56. package/dist/lib/build-if-stale.js.map +1 -0
  57. package/dist/lib/bundle-freshness.d.ts +57 -0
  58. package/dist/lib/bundle-freshness.d.ts.map +1 -0
  59. package/dist/lib/bundle-freshness.js +223 -0
  60. package/dist/lib/bundle-freshness.js.map +1 -0
  61. package/dist/lib/bundle-source.d.ts +52 -0
  62. package/dist/lib/bundle-source.d.ts.map +1 -0
  63. package/dist/lib/bundle-source.js +83 -0
  64. package/dist/lib/bundle-source.js.map +1 -0
  65. package/dist/lib/manifest-refresh.d.ts +34 -0
  66. package/dist/lib/manifest-refresh.d.ts.map +1 -1
  67. package/dist/lib/manifest-refresh.js +66 -0
  68. package/dist/lib/manifest-refresh.js.map +1 -1
  69. package/dist/lib/upgrade-kubernetes.d.ts +17 -1
  70. package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
  71. package/dist/lib/upgrade-kubernetes.js +125 -1
  72. package/dist/lib/upgrade-kubernetes.js.map +1 -1
  73. package/dist/mcp-server.js +84 -58
  74. package/host-cp/compose.yaml +6 -0
  75. package/host-cp/k8s/manifests/30-configmap.yaml +6 -0
  76. package/host-cp/k8s/manifests/50-deployment.yaml +46 -9
  77. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +7 -4
  78. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
  79. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +7 -4
  80. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +6 -1
  81. package/host-cp/src/agent-runtime-trigger.mjs +7 -5
  82. package/host-cp/src/plan-chat-secret.mjs +13 -2
  83. package/host-cp/src/plan-chat-service.mjs +94 -12
  84. package/host-cp/src/server.mjs +19 -7
  85. package/host-cp/src/upgrade-spawner.mjs +10 -5
  86. package/package.json +4 -2
@@ -7090,7 +7090,7 @@ var require_compile = __commonJS({
7090
7090
  const schOrFunc = root.refs[ref];
7091
7091
  if (schOrFunc)
7092
7092
  return schOrFunc;
7093
- let _sch = resolve12.call(this, root, ref);
7093
+ let _sch = resolve13.call(this, root, ref);
7094
7094
  if (_sch === void 0) {
7095
7095
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
7096
7096
  const { schemaId } = this.opts;
@@ -7117,7 +7117,7 @@ var require_compile = __commonJS({
7117
7117
  function sameSchemaEnv(s1, s2) {
7118
7118
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
7119
7119
  }
7120
- function resolve12(root, ref) {
7120
+ function resolve13(root, ref) {
7121
7121
  let sch;
7122
7122
  while (typeof (sch = this.refs[ref]) == "string")
7123
7123
  ref = sch;
@@ -7692,7 +7692,7 @@ var require_fast_uri = __commonJS({
7692
7692
  }
7693
7693
  return uri;
7694
7694
  }
7695
- function resolve12(baseURI, relativeURI, options) {
7695
+ function resolve13(baseURI, relativeURI, options) {
7696
7696
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
7697
7697
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
7698
7698
  schemelessOptions.skipEscape = true;
@@ -7919,7 +7919,7 @@ var require_fast_uri = __commonJS({
7919
7919
  var fastUri = {
7920
7920
  SCHEMES,
7921
7921
  normalize,
7922
- resolve: resolve12,
7922
+ resolve: resolve13,
7923
7923
  resolveComponent,
7924
7924
  equal,
7925
7925
  serialize,
@@ -12417,7 +12417,9 @@ var init_trust_audit_log = __esm({
12417
12417
  "auto-rejected",
12418
12418
  "failed",
12419
12419
  "removed",
12420
- "meta-hook-stripped"
12420
+ "meta-hook-stripped",
12421
+ "setup-skill-source-picked",
12422
+ "setup-project-sweep-completed"
12421
12423
  ]);
12422
12424
  TrustMethodSchema = external_exports.enum(["flag", "interactive", "auto-reject-tty", "none"]);
12423
12425
  TrustAuditEntrySchema = external_exports.object({
@@ -13797,7 +13799,7 @@ function defaultIsPidAlive(pid) {
13797
13799
  }
13798
13800
  }
13799
13801
  function sleep3(ms) {
13800
- return new Promise((resolve12) => setTimeout(resolve12, ms));
13802
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
13801
13803
  }
13802
13804
  function readLockMeta(lockPath) {
13803
13805
  try {
@@ -13928,7 +13930,7 @@ function defaultIsPidAlive2(pid) {
13928
13930
  }
13929
13931
  }
13930
13932
  function sleep4(ms) {
13931
- return new Promise((resolve12) => setTimeout(resolve12, ms));
13933
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
13932
13934
  }
13933
13935
  function readLockMeta2(lockPath) {
13934
13936
  try {
@@ -22075,12 +22077,12 @@ var StdioServerTransport = class {
22075
22077
  this.onclose?.();
22076
22078
  }
22077
22079
  send(message) {
22078
- return new Promise((resolve12) => {
22080
+ return new Promise((resolve13) => {
22079
22081
  const json = serializeMessage(message);
22080
22082
  if (this._stdout.write(json)) {
22081
- resolve12();
22083
+ resolve13();
22082
22084
  } else {
22083
- this._stdout.once("drain", resolve12);
22085
+ this._stdout.once("drain", resolve13);
22084
22086
  }
22085
22087
  });
22086
22088
  }
@@ -24117,7 +24119,7 @@ var Protocol = class {
24117
24119
  return;
24118
24120
  }
24119
24121
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
24120
- await new Promise((resolve12) => setTimeout(resolve12, pollInterval));
24122
+ await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
24121
24123
  options?.signal?.throwIfAborted();
24122
24124
  }
24123
24125
  } catch (error2) {
@@ -24134,7 +24136,7 @@ var Protocol = class {
24134
24136
  */
24135
24137
  request(request2, resultSchema, options) {
24136
24138
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
24137
- return new Promise((resolve12, reject2) => {
24139
+ return new Promise((resolve13, reject2) => {
24138
24140
  const earlyReject = (error2) => {
24139
24141
  reject2(error2);
24140
24142
  };
@@ -24212,7 +24214,7 @@ var Protocol = class {
24212
24214
  if (!parseResult.success) {
24213
24215
  reject2(parseResult.error);
24214
24216
  } else {
24215
- resolve12(parseResult.data);
24217
+ resolve13(parseResult.data);
24216
24218
  }
24217
24219
  } catch (error2) {
24218
24220
  reject2(error2);
@@ -24473,12 +24475,12 @@ var Protocol = class {
24473
24475
  }
24474
24476
  } catch {
24475
24477
  }
24476
- return new Promise((resolve12, reject2) => {
24478
+ return new Promise((resolve13, reject2) => {
24477
24479
  if (signal.aborted) {
24478
24480
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
24479
24481
  return;
24480
24482
  }
24481
- const timeoutId = setTimeout(resolve12, interval);
24483
+ const timeoutId = setTimeout(resolve13, interval);
24482
24484
  signal.addEventListener("abort", () => {
24483
24485
  clearTimeout(timeoutId);
24484
24486
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -25578,7 +25580,7 @@ var McpServer = class {
25578
25580
  let task = createTaskResult.task;
25579
25581
  const pollInterval = task.pollInterval ?? 5e3;
25580
25582
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
25581
- await new Promise((resolve12) => setTimeout(resolve12, pollInterval));
25583
+ await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
25582
25584
  const updatedTask = await extra.taskStore.getTask(taskId);
25583
25585
  if (!updatedTask) {
25584
25586
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -26543,7 +26545,7 @@ async function safeText(res) {
26543
26545
  }
26544
26546
  }
26545
26547
  function sleep(ms) {
26546
- return new Promise((resolve12) => setTimeout(resolve12, ms));
26548
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
26547
26549
  }
26548
26550
 
26549
26551
  // ../core/dist/auth/container.js
@@ -26675,7 +26677,7 @@ function resolveAuthServicePath() {
26675
26677
  return path3.join(pkgsDir, "auth-service");
26676
26678
  }
26677
26679
  function sleep2(ms) {
26678
- return new Promise((resolve12) => setTimeout(resolve12, ms));
26680
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
26679
26681
  }
26680
26682
 
26681
26683
  // ../core/dist/auth/preflight.js
@@ -27862,6 +27864,7 @@ import Dockerode from "dockerode";
27862
27864
  import * as fs7 from "node:fs";
27863
27865
  import * as os5 from "node:os";
27864
27866
  import * as path8 from "node:path";
27867
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
27865
27868
 
27866
27869
  // ../adapters/dist/docker/network.js
27867
27870
  var NETWORK_PREFIX = "olam-";
@@ -27919,7 +27922,7 @@ var realDocker = {
27919
27922
  }
27920
27923
  };
27921
27924
  function spawnAsync(cmd, args, opts = {}) {
27922
- return new Promise((resolve12) => {
27925
+ return new Promise((resolve13) => {
27923
27926
  const child = spawn(cmd, [...args], {
27924
27927
  stdio: ["ignore", "pipe", "pipe"],
27925
27928
  signal: opts.signal
@@ -27933,10 +27936,10 @@ function spawnAsync(cmd, args, opts = {}) {
27933
27936
  stderr += chunk.toString();
27934
27937
  });
27935
27938
  child.on("error", (err) => {
27936
- resolve12({ exitCode: -1, stdout, stderr: stderr + err.message });
27939
+ resolve13({ exitCode: -1, stdout, stderr: stderr + err.message });
27937
27940
  });
27938
27941
  child.on("close", (code) => {
27939
- resolve12({ exitCode: code ?? -1, stdout, stderr });
27942
+ resolve13({ exitCode: code ?? -1, stdout, stderr });
27940
27943
  });
27941
27944
  });
27942
27945
  }
@@ -28066,6 +28069,19 @@ function resolveMemoryEnv() {
28066
28069
  return null;
28067
28070
  return { url: AGENTMEMORY_HOST_INTERNAL_URL, secret };
28068
28071
  }
28072
+ function resolveAgentStreamDistPath() {
28073
+ if (process.env["OLAM_DEV"] !== "1")
28074
+ return null;
28075
+ const here = fileURLToPath2(import.meta.url);
28076
+ const repoRoot = path8.resolve(path8.dirname(here), "..", "..", "..", "..");
28077
+ if (!fs7.existsSync(path8.join(repoRoot, "packages")) || !fs7.existsSync(path8.join(repoRoot, "package.json"))) {
28078
+ return null;
28079
+ }
28080
+ const distPath = path8.join(repoRoot, "packages", "intelligence", "dist", "agent-stream");
28081
+ if (!fs7.existsSync(distPath))
28082
+ return null;
28083
+ return distPath;
28084
+ }
28069
28085
  function sanitizeContainerName(name) {
28070
28086
  return name.replace(/[^a-zA-Z0-9_.-]/g, "-");
28071
28087
  }
@@ -28191,7 +28207,7 @@ async function auditPortsForZombies(docker, hostPorts) {
28191
28207
  }
28192
28208
  }
28193
28209
  }
28194
- var createWorldContainer = async (docker, worldId, worldName, image, env, resources, workspacePath, portOffset, appPorts, cacheArch, tmpfsMounts) => {
28210
+ var createWorldContainer = async (docker, worldId, worldName, image, env, resources, workspacePath, portOffset, appPorts, cacheArch, tmpfsMounts, agentStreamDistPath) => {
28195
28211
  const labels = olamLabels(worldId, worldName);
28196
28212
  const authSecret = readAuthSecret();
28197
28213
  const hostCpToken = readHostCpToken();
@@ -28238,6 +28254,10 @@ var createWorldContainer = async (docker, worldId, worldName, image, env, resour
28238
28254
  // OLAM_WORKSPACES KV; docker's is this tmpfs mount.
28239
28255
  `${hostWorkspacesDir}:/host-workspaces:ro`
28240
28256
  ];
28257
+ const resolvedAgentStreamPath = agentStreamDistPath ?? resolveAgentStreamDistPath();
28258
+ if (resolvedAgentStreamPath) {
28259
+ binds.push(`${resolvedAgentStreamPath}:/opt/olam/agent-stream/dist:ro`);
28260
+ }
28241
28261
  binds.push(...buildPackageManagerCacheBinds(olamHomeDir));
28242
28262
  if (workspacePath) {
28243
28263
  binds.push(`${workspacePath}:/home/olam/workspace:rw`);
@@ -28358,7 +28378,7 @@ var stopAndRemove = async (container) => {
28358
28378
 
28359
28379
  // ../adapters/dist/docker/exec.js
28360
28380
  import { PassThrough } from "node:stream";
28361
- var demuxStream = (stream) => new Promise((resolve12, reject2) => {
28381
+ var demuxStream = (stream) => new Promise((resolve13, reject2) => {
28362
28382
  const stdoutChunks = [];
28363
28383
  const stderrChunks = [];
28364
28384
  const stdout = new PassThrough();
@@ -28372,7 +28392,7 @@ var demuxStream = (stream) => new Promise((resolve12, reject2) => {
28372
28392
  stream.pipe(stdout);
28373
28393
  }
28374
28394
  stream.on("end", () => {
28375
- resolve12({
28395
+ resolve13({
28376
28396
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
28377
28397
  stderr: Buffer.concat(stderrChunks).toString("utf-8")
28378
28398
  });
@@ -28561,7 +28581,7 @@ var DockerProvider = class extends ComputeProvider {
28561
28581
  }
28562
28582
  }
28563
28583
  const mergedEnv = { ...serviceEnv, ...config2.env };
28564
- const container = await createWorldContainer(this.docker, id, name, config2.image, mergedEnv, config2.resources, config2.workspacePath, config2.portOffset, config2.appPorts, config2.cacheArch, config2.tmpfsMounts);
28584
+ const container = await createWorldContainer(this.docker, id, name, config2.image, mergedEnv, config2.resources, config2.workspacePath, config2.portOffset, config2.appPorts, config2.cacheArch, config2.tmpfsMounts, config2.agentStreamDistPath);
28565
28585
  for (const networkName3 of config2.extraNetworks ?? []) {
28566
28586
  try {
28567
28587
  const network = this.docker.getNetwork(networkName3);
@@ -28745,7 +28765,7 @@ var SSHConnectionPool = class {
28745
28765
  // -----------------------------------------------------------------------
28746
28766
  async exec(host, command) {
28747
28767
  const client = await this.getConnection(host);
28748
- return new Promise((resolve12, reject2) => {
28768
+ return new Promise((resolve13, reject2) => {
28749
28769
  client.exec(command, (err, stream) => {
28750
28770
  if (err) {
28751
28771
  reject2(new Error(`SSH exec failed on ${host}: ${err.message}`));
@@ -28760,7 +28780,7 @@ var SSHConnectionPool = class {
28760
28780
  stderr += data.toString();
28761
28781
  });
28762
28782
  stream.on("close", (code) => {
28763
- resolve12({
28783
+ resolve13({
28764
28784
  exitCode: code ?? 0,
28765
28785
  stdout: stdout.trimEnd(),
28766
28786
  stderr: stderr.trimEnd()
@@ -28791,10 +28811,10 @@ var SSHConnectionPool = class {
28791
28811
  throw new Error(`No SSH configuration found for host: ${host}`);
28792
28812
  }
28793
28813
  const client = new SSHClient();
28794
- return new Promise((resolve12, reject2) => {
28814
+ return new Promise((resolve13, reject2) => {
28795
28815
  client.on("ready", () => {
28796
28816
  this.connections.set(host, client);
28797
- resolve12(client);
28817
+ resolve13(client);
28798
28818
  }).on("error", (err) => {
28799
28819
  this.connections.delete(host);
28800
28820
  reject2(new Error(`SSH connection to ${host} failed: ${err.message}`));
@@ -29774,7 +29794,7 @@ function register6(server, ctx, initError) {
29774
29794
  }
29775
29795
  } catch {
29776
29796
  }
29777
- await new Promise((resolve12) => setTimeout(resolve12, POLL_INTERVAL_MS));
29797
+ await new Promise((resolve13) => setTimeout(resolve13, POLL_INTERVAL_MS));
29778
29798
  }
29779
29799
  }
29780
29800
  if (authenticated) {
@@ -31675,7 +31695,7 @@ import { createServer as createServer2 } from "node:http";
31675
31695
  import { request as httpRequest } from "node:http";
31676
31696
  import { request as httpsRequest } from "node:https";
31677
31697
  import { connect as netConnect } from "node:net";
31678
- import { dirname as dirname7 } from "node:path";
31698
+ import { dirname as dirname8 } from "node:path";
31679
31699
  import { userInfo } from "node:os";
31680
31700
 
31681
31701
  // ../mcp-server/src/tools/_capture/token.ts
@@ -32026,15 +32046,15 @@ ${JSON.stringify({ error: reason })}`
32026
32046
  unlinkSync2(udsPath);
32027
32047
  } catch {
32028
32048
  }
32029
- await new Promise((resolve12, reject2) => {
32030
- server.listen(udsPath, () => resolve12());
32049
+ await new Promise((resolve13, reject2) => {
32050
+ server.listen(udsPath, () => resolve13());
32031
32051
  server.once("error", reject2);
32032
32052
  });
32033
32053
  chmodSync3(udsPath, 384);
32034
32054
  port2 = 0;
32035
32055
  } else {
32036
- await new Promise((resolve12, reject2) => {
32037
- server.listen(opts.port ?? 0, "127.0.0.1", () => resolve12());
32056
+ await new Promise((resolve13, reject2) => {
32057
+ server.listen(opts.port ?? 0, "127.0.0.1", () => resolve13());
32038
32058
  server.once("error", reject2);
32039
32059
  });
32040
32060
  const addr = server.address();
@@ -32050,10 +32070,10 @@ ${JSON.stringify({ error: reason })}`
32050
32070
  } catch {
32051
32071
  }
32052
32072
  await Promise.race([
32053
- new Promise((resolve12, reject2) => {
32054
- server.close((err) => err ? reject2(err) : resolve12());
32073
+ new Promise((resolve13, reject2) => {
32074
+ server.close((err) => err ? reject2(err) : resolve13());
32055
32075
  }),
32056
- new Promise((resolve12) => setTimeout(resolve12, 5e3))
32076
+ new Promise((resolve13) => setTimeout(resolve13, 5e3))
32057
32077
  ]);
32058
32078
  if (udsPath) {
32059
32079
  try {
@@ -32077,7 +32097,7 @@ ${JSON.stringify({ error: reason })}`
32077
32097
  };
32078
32098
  }
32079
32099
  function ensureUdsParentDirSafe(udsPath) {
32080
- const parent = dirname7(udsPath);
32100
+ const parent = dirname8(udsPath);
32081
32101
  if (!parent || parent === udsPath || parent === ".") {
32082
32102
  throw new Error(
32083
32103
  `uds_parent_path_invalid: bindUdsPath "${udsPath}" has no manageable parent directory`
@@ -32385,10 +32405,10 @@ async function acquireLaunchSlot() {
32385
32405
  _inFlightLaunches++;
32386
32406
  return releaseLaunchSlot;
32387
32407
  }
32388
- return new Promise((resolve12) => {
32408
+ return new Promise((resolve13) => {
32389
32409
  _launchQueue.push(() => {
32390
32410
  _inFlightLaunches++;
32391
- resolve12(releaseLaunchSlot);
32411
+ resolve13(releaseLaunchSlot);
32392
32412
  });
32393
32413
  });
32394
32414
  }
@@ -34923,7 +34943,7 @@ import * as path35 from "node:path";
34923
34943
 
34924
34944
  // ../core/dist/kg/storage-paths.js
34925
34945
  import { homedir as homedir22 } from "node:os";
34926
- import { join as join35, resolve as resolve7 } from "node:path";
34946
+ import { join as join35, resolve as resolve8 } from "node:path";
34927
34947
 
34928
34948
  // ../core/dist/world/workspace-name.js
34929
34949
  var InvalidWorkspaceNameError = class extends Error {
@@ -34960,7 +34980,7 @@ function assertWithinPrefix(path46, prefix, label) {
34960
34980
  function kgPristinePath(workspace) {
34961
34981
  validateWorkspaceName(workspace);
34962
34982
  const root = kgRoot();
34963
- const path46 = resolve7(join35(root, workspace));
34983
+ const path46 = resolve8(join35(root, workspace));
34964
34984
  assertWithinPrefix(path46, root, "kgPristinePath");
34965
34985
  return path46;
34966
34986
  }
@@ -35346,7 +35366,7 @@ import * as path37 from "node:path";
35346
35366
  // ../core/dist/world/templates/_generated.js
35347
35367
  var GH_PR_CREATE = '# Creating PRs from inside an Olam world\n\n## The problem\n\nCalling `gh pr create` directly inside an Olam container **hangs forever** on a\nTTY confirmation prompt that the agent cannot answer. This is a known, reproduced issue.\n\n## The fix\n\nAlways use this exact pattern:\n\n```bash\necho y | timeout 30 gh pr create \\\n --base main \\\n --head <branch> \\\n --title "<title>" \\\n --body-file /tmp/pr-body.md\n```\n\n## Why each part matters\n\n- **`echo y |`** \u2014 answers the "Submit?" confirmation prompt up front so `gh` never pauses.\n- **`timeout 30`** \u2014 hard deadline. If `gh` hangs anyway, the command exits non-zero so the\n agent can react instead of stalling the world indefinitely.\n- **`--body-file /tmp/pr-body.md`** \u2014 write the PR body to a temp file first. Avoids\n shell-escaping bugs that occur with `--body "..."` for long or multi-line bodies.\n- **`--head` and `--base` explicitly** \u2014 removes all interactive prompts; `gh` has nothing to ask.\n\n## Troubleshooting\n\n**"no commits" or "branch not found" error:**\n\n```bash\ngit push -u origin <branch>\n# then retry:\necho y | timeout 30 gh pr create --base main --head <branch> --title "..." --body-file /tmp/pr-body.md\n```\n\n**Timeout exceeded (command exits 124):**\n\n- Check if the branch was pushed: `git log origin/<branch> --oneline -1`\n- Check GitHub CLI auth: `gh auth status`\n- Retry once; if it hangs again, open the PR via the GitHub web UI.\n';
35348
35368
  var LANE_ORCHESTRATION = '# Lane Orchestration\n\nOlam worlds support parallel work via **lanes** \u2014 independent Claude Code sessions\nrunning in isolated git worktrees inside the same container.\n\nUse lanes when a task has 2+ independent scopes that can work simultaneously\nwithout file conflicts.\n\n## Container API\n\nBase URL: `http://localhost:8080`\n\n### Create a lane\n\n```bash\ncurl -s -X POST \\\n -H \'Content-Type: application/json\' \\\n -d \'{"name":"auth-fix","task":"Fix auth bugs","scope":["src/auth/**"],"avoids":["tests/**"]}\' \\\n http://localhost:8080/lanes/create\n```\n\n### List lanes\n\n```bash\ncurl -s http://localhost:8080/lanes\n```\n\n### Dispatch a prompt to a lane\n\n```bash\ncurl -s -X POST \\\n -H \'Content-Type: application/json\' \\\n -d \'{"prompt":"Start by reviewing..."}\' \\\n http://localhost:8080/lanes/auth-fix/dispatch\n```\n\n### Check lane status\n\n```bash\ncurl -s http://localhost:8080/lanes/auth-fix\n```\n\n### Merge a lane\n\n```bash\ncurl -s -X POST http://localhost:8080/lanes/auth-fix/merge\n```\n\n### Destroy a lane\n\n```bash\ncurl -s -X DELETE http://localhost:8080/lanes/auth-fix\n```\n\n## When to use lanes\n\n- Task has 2+ independent scopes (different directories/modules)\n- Work can be done simultaneously without file conflicts\n- Estimated effort > ~30 tool calls per scope\n\n## When NOT to use lanes\n\n- Simple tasks touching few files\n- Sequential work where each step depends on the previous\n- Everything is in one directory\n\n## Orchestration workflow\n\n1. Analyze the task \u2014 identify independent work streams\n2. Create lanes with non-overlapping scope globs\n3. Dispatch initial prompts to each lane\n4. **Monitor progress** \u2014 poll lane status every 30 seconds:\n ```bash\n while true; do\n STATUS=$(curl -s http://localhost:8080/lanes)\n RUNNING=$(echo "$STATUS" | jq \'[.lanes[] | select(.status == "running")] | length\')\n echo "Running lanes: $RUNNING"\n if [ "$RUNNING" = "0" ]; then echo "All lanes complete!"; break; fi\n sleep 30\n done\n ```\n5. **When a lane completes** (status is "completed" or no longer "running"):\n - Check its output: `curl -s http://localhost:8080/lanes/<name>`\n - If satisfactory, merge it: `curl -s -X POST http://localhost:8080/lanes/<name>/merge`\n - The merge automatically triggers a Codex adversarial review\n6. **After ALL lanes are merged**:\n - Run tests: `npm test` or equivalent\n - Review combined changes: `git diff main...HEAD --stat`\n - Create a PR: see `~/.olam/docs/gh-pr-create.md`\n7. Clean up: `curl -s -X DELETE http://localhost:8080/lanes/<name>`\n\n## Act on completion immediately\n\nWhen all lanes are done, immediately start merging and creating the PR.\nDo not wait for the user to tell you to merge. The workflow is:\n**lanes complete \u2192 merge each \u2192 run tests \u2192 create PR \u2192 report to user.**\n';
35349
- var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Environment\n- World ID: {{worldId}}\n- Branch: {{branch}}{{servicesLine}}{{pleriPlaneLine}}\n\n## Repos in this World\n{{reposList}}\n\n{{planFileBlock}}## Instructions\n1. Work on the task described above\n2. Write tests first (TDD)\n3. Commit frequently to the world branch\n4. When done, push and the work will be available for review\n5. Your `AskUserQuestion` calls are intercepted and surfaced to the operator\'s host CP automatically. The operator answers in the SPA; claude resumes when keys are injected.\n\n## Sandbox & network \u2014 what is actually true\n\nThe olam-devbox container has FULL outbound internet. Confirm any time:\n\n```bash\ncurl -sI https://registry.npmjs.org/ # \u2192 HTTP 200\ncurl -sI https://github.com/ # \u2192 HTTP 200\n```\n\nRules:\n\n- **Never claim "the sandbox blocks X" without proving it.** Capture the actual `npm install` / `curl` error verbatim. A flaky postinstall is not a network block.\n- **Retry transient failures at least once** before falling back to a manual workaround. `npm install <pkg>` flakes happen; one retry catches >90%.\n- **If you genuinely need a workaround**, say so explicitly with the error message and the retry count, NOT "sandbox network blocked it." Truthful attribution = trustable telemetry.\n- **Playwright `chromium` downloads ~140 MB** from playwright.azureedge.net. Disk-space failures (not network) are the usual cause. Check `df -h` before blaming the network.\n\n## Halt semantics \u2014 when to stop and surface\n\nStop and call `AskUserQuestion` (which surfaces in the host CP) when you hit:\n\n- **Halt-N (new pattern)**: a new dep family, framework, or architectural pattern not in the existing codebase. Don\'t silently adopt it \u2014 surface the choice.\n- **Halt-B (business deal-breaker)**: a breaking constraint that makes the task\'s goal unsatisfiable as stated. Surface the conflict; let the operator re-scope.\n- **Halt-C (complexity blowup)**: the diff is exceeding 1.5x of what the task implied. Surface for re-scoping before continuing.\n\nDon\'t halt on every uncertainty \u2014 only on these three classes. Style/naming/error-handling choices are non-load-bearing; pick the simplest option that works and continue.\n\n## Lane Orchestration (advanced \u2014 read on demand)\n\nThis world supports parallel work lanes via the container API at http://localhost:8080.\nUse only when the task has 2+ independent scopes that can run simultaneously.\n\n**Full lane API + workflow**: see `~/.olam/docs/lane-orchestration.md` (mounted into the world).\n\n## Creating PRs from inside this world\n\n`gh pr create` hangs on a TTY prompt inside the container. Always use:\n\n```bash\necho y | timeout 30 gh pr create --base main --head <branch> --title "..." --body-file /tmp/pr-body.md\n```\n\n**Why + full troubleshooting**: see `~/.olam/docs/gh-pr-create.md`.\n\n## Available Skills & Plugins\n\nYour Claude Code session includes the invoker\'s plugins, rules, and skills.\nThese are copied from the host at world creation time.\nUse `/codex:review` or `/codex:adversarial-review` for code reviews.\nUse `/codex:rescue` to delegate tasks to Codex.\n{{extraContextBlock}}';
35369
+ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Environment\n- World ID: {{worldId}}\n- Branch: {{branch}}{{servicesLine}}{{pleriPlaneLine}}\n\n## Repos in this World\n{{reposList}}\n\n{{planFileBlock}}## Instructions\n1. Work on the task described above\n2. Write tests first (TDD)\n3. Commit frequently to the world branch\n4. When done, push and the work will be available for review\n5. Your `AskUserQuestion` calls are intercepted and surfaced to the operator\'s host CP automatically. The operator answers in the SPA; claude resumes when keys are injected.\n\n## Sandbox & network \u2014 what is actually true\n\nThe olam-devbox container has FULL outbound internet. Confirm any time:\n\n```bash\ncurl -sI https://registry.npmjs.org/ # \u2192 HTTP 200\ncurl -sI https://github.com/ # \u2192 HTTP 200\n```\n\nRules:\n\n- **Never claim "the sandbox blocks X" without proving it.** Capture the actual `npm install` / `curl` error verbatim. A flaky postinstall is not a network block.\n- **Retry transient failures at least once** before falling back to a manual workaround. `npm install <pkg>` flakes happen; one retry catches >90%.\n- **If you genuinely need a workaround**, say so explicitly with the error message and the retry count, NOT "sandbox network blocked it." Truthful attribution = trustable telemetry.\n- **Playwright `chromium` downloads ~140 MB** from playwright.azureedge.net. Disk-space failures (not network) are the usual cause. Check `df -h` before blaming the network.\n\n## Halt semantics \u2014 when to stop and surface\n\nStop and call `AskUserQuestion` (which surfaces in the host CP) when you hit:\n\n- **Halt-N (new pattern)**: a new dep family, framework, or architectural pattern not in the existing codebase. Don\'t silently adopt it \u2014 surface the choice.\n- **Halt-B (business deal-breaker)**: a breaking constraint that makes the task\'s goal unsatisfiable as stated. Surface the conflict; let the operator re-scope.\n- **Halt-C (complexity blowup)**: the diff is exceeding 1.5x of what the task implied. Surface for re-scoping before continuing.\n\nDon\'t halt on every uncertainty \u2014 only on these three classes. Style/naming/error-handling choices are non-load-bearing; pick the simplest option that works and continue.\n\n## Session continuation discipline\n\n**Never ask the operator to sleep, pause, take a break, stop, or close out a\nsession.** Session continuity \u2014 fatigue, time-of-day, when-to-rest \u2014 is managed\noutside the agent. It is not the agent\'s call. No "this might be a good\nstopping point", no "want to pick this up tomorrow", no "you\'ve been at this a\nwhile" framings, no fatigue-flavoured suggestions.\n\n**Respect autonomous / auto-advancing intent at all times.** When the operator\nsays "continue", "push on", "autonomous", "keep going", or has set\n`autonomous: true` on a plan, honour it without re-prompting for confirmation\ngates. Push hard until the work is done OR a real concern surfaces \u2014 do not\nsilently raise the bar for "real concern" to manufacture a pause.\n\n**Real concerns are technical, not energy/time-based.** Surface Halt-N, Halt-B,\nHalt-C (above), or a load-bearing blocker requiring operator decision\n(credentials, ambiguous intent, external-system failure, contradictory\nrequirements). Frame each surfacing in terms of the technical issue. Never in\nterms of the operator\'s energy, attention, or available time.\n\n## Lane Orchestration (advanced \u2014 read on demand)\n\nThis world supports parallel work lanes via the container API at http://localhost:8080.\nUse only when the task has 2+ independent scopes that can run simultaneously.\n\n**Full lane API + workflow**: see `~/.olam/docs/lane-orchestration.md` (mounted into the world).\n\n## Creating PRs from inside this world\n\n`gh pr create` hangs on a TTY prompt inside the container. Always use:\n\n```bash\necho y | timeout 30 gh pr create --base main --head <branch> --title "..." --body-file /tmp/pr-body.md\n```\n\n**Why + full troubleshooting**: see `~/.olam/docs/gh-pr-create.md`.\n\n## Available Skills & Plugins\n\nYour Claude Code session includes the invoker\'s plugins, rules, and skills.\nThese are copied from the host at world creation time.\nUse `/codex:review` or `/codex:adversarial-review` for code reviews.\nUse `/codex:rescue` to delegate tasks to Codex.\n{{extraContextBlock}}';
35350
35370
 
35351
35371
  // ../core/dist/world/context-injection.js
35352
35372
  function injectWorldContext(opts) {
@@ -36688,7 +36708,7 @@ var TaskDispatchError = class extends Error {
36688
36708
  this.name = "TaskDispatchError";
36689
36709
  }
36690
36710
  };
36691
- var DEFAULT_SLEEP = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
36711
+ var DEFAULT_SLEEP = (ms) => new Promise((resolve13) => setTimeout(resolve13, ms));
36692
36712
  async function probeHealth(containerName, dockerExec, budgetMs, sleep5) {
36693
36713
  const deadline = Date.now() + budgetMs;
36694
36714
  const cadenceMs = 100;
@@ -37892,7 +37912,13 @@ ${detail}`);
37892
37912
  // also pin the mise-cache to x64 so the amd64 container doesn't
37893
37913
  // mount the host's arm64 cache. undefined => provider keys by
37894
37914
  // host process.arch (the pre-existing default).
37895
- ...cacheArchOverride ? { cacheArch: cacheArchOverride } : {}
37915
+ ...cacheArchOverride ? { cacheArch: cacheArchOverride } : {},
37916
+ // Phase C C2 (olam-world-bundle-freshness): thread the CLI-resolved
37917
+ // agent-stream dist path into WorldConfig so the docker provider's
37918
+ // createWorldContainer uses it directly instead of re-deriving it
37919
+ // internally. Undefined = container.ts falls back to Phase B's
37920
+ // internal source-mode detection (backward compat).
37921
+ ...opts.agentStreamDistPath ? { agentStreamDistPath: opts.agentStreamDistPath } : {}
37896
37922
  });
37897
37923
  } catch (err) {
37898
37924
  try {
@@ -38767,7 +38793,7 @@ import * as http2 from "node:http";
38767
38793
  import * as http from "node:http";
38768
38794
  import * as fs44 from "node:fs";
38769
38795
  import * as path44 from "node:path";
38770
- import { fileURLToPath as fileURLToPath2 } from "node:url";
38796
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
38771
38797
 
38772
38798
  // ../core/dist/dashboard/serialize.js
38773
38799
  function serializeTokenUsage(usage) {
@@ -39272,7 +39298,7 @@ function findSessionInWorld(registry2, sessionId) {
39272
39298
  }
39273
39299
  function createDashboardServer(opts) {
39274
39300
  const { port: port2, registry: registry2 } = opts;
39275
- const thisDir = path44.dirname(fileURLToPath2(import.meta.url));
39301
+ const thisDir = path44.dirname(fileURLToPath3(import.meta.url));
39276
39302
  const defaultPublicDir = path44.resolve(thisDir, "../../../control-plane/public");
39277
39303
  const publicDir = opts.publicDir ?? defaultPublicDir;
39278
39304
  let hasPublicDir = fs44.existsSync(publicDir);
@@ -39624,7 +39650,7 @@ function isCloudflaredAvailable() {
39624
39650
  }
39625
39651
  }
39626
39652
  function startTunnel(port2) {
39627
- return new Promise((resolve12, reject2) => {
39653
+ return new Promise((resolve13, reject2) => {
39628
39654
  const child = spawn3("cloudflared", ["tunnel", "--url", `http://localhost:${port2}`], {
39629
39655
  stdio: ["ignore", "pipe", "pipe"],
39630
39656
  detached: false
@@ -39646,7 +39672,7 @@ function startTunnel(port2) {
39646
39672
  if (match) {
39647
39673
  resolved = true;
39648
39674
  clearTimeout(timeout);
39649
- resolve12(match[0]);
39675
+ resolve13(match[0]);
39650
39676
  }
39651
39677
  }
39652
39678
  child.stdout?.on("data", scan);
@@ -39714,8 +39740,8 @@ var DashboardManager = class {
39714
39740
  }
39715
39741
  throw err;
39716
39742
  }
39717
- await new Promise((resolve12, reject2) => {
39718
- this.server.on("listening", resolve12);
39743
+ await new Promise((resolve13, reject2) => {
39744
+ this.server.on("listening", resolve13);
39719
39745
  this.server.on("error", reject2);
39720
39746
  });
39721
39747
  this.info = { localUrl: `http://localhost:${port2}` };
@@ -39761,8 +39787,8 @@ var DashboardManager = class {
39761
39787
  async stop() {
39762
39788
  stopTunnel();
39763
39789
  if (this.server) {
39764
- await new Promise((resolve12) => {
39765
- this.server.close(() => resolve12());
39790
+ await new Promise((resolve13) => {
39791
+ this.server.close(() => resolve13());
39766
39792
  });
39767
39793
  this.server = null;
39768
39794
  }
@@ -39876,7 +39902,7 @@ var PleriClient = class {
39876
39902
 
39877
39903
  // ../mcp-server/src/env-loader.ts
39878
39904
  import { readFileSync as readFileSync33, existsSync as existsSync42, statSync as statSync12 } from "node:fs";
39879
- import { join as join46, dirname as dirname27, resolve as resolve11 } from "node:path";
39905
+ import { join as join46, dirname as dirname28, resolve as resolve12 } from "node:path";
39880
39906
  var PROJECT_MARKERS = [
39881
39907
  ".olam/config.yaml",
39882
39908
  ".olam/config.yml",
@@ -39884,8 +39910,8 @@ var PROJECT_MARKERS = [
39884
39910
  "olam.yml"
39885
39911
  ];
39886
39912
  function findProjectRoot2(startDir) {
39887
- let dir = resolve11(startDir);
39888
- const root = resolve11("/");
39913
+ let dir = resolve12(startDir);
39914
+ const root = resolve12("/");
39889
39915
  while (true) {
39890
39916
  for (const marker of PROJECT_MARKERS) {
39891
39917
  if (existsSync42(join46(dir, marker))) return dir;
@@ -39900,7 +39926,7 @@ function findProjectRoot2(startDir) {
39900
39926
  } catch {
39901
39927
  }
39902
39928
  }
39903
- const parent = dirname27(dir);
39929
+ const parent = dirname28(dir);
39904
39930
  if (parent === dir || parent === root) return null;
39905
39931
  dir = parent;
39906
39932
  }
@@ -139,6 +139,12 @@ services:
139
139
  # Pointing to /data/ routes all writes through the bind-mount to the host.
140
140
  OLAM_PLAN_DB_PATH: "/data/plan.db"
141
141
  OLAM_PLAN_DIR: "/data/plan"
142
+ # Same /root vs /data bind-mount issue applies to the plan-chat bearer
143
+ # gateway. Without this override, plan-chat-secret.mjs reads from
144
+ # /root/.olam/plan-chat-secret (container ephemeral, missing) and
145
+ # /agent-runtime/trigger answers HTTP 500. Routing through /data
146
+ # surfaces the on-disk bearer created by ensureSecret() on host FS.
147
+ OLAM_PLAN_CHAT_SECRET_PATH: "/data/plan-chat-secret"
142
148
  volumes:
143
149
  # ~/.olam/ from operator's home → /data/ inside container. B4
144
150
  # writes the startup token here (chmod 600). B6 reads workspaces
@@ -24,6 +24,12 @@ data:
24
24
  OLAM_WORLDS_DB: "/data/worlds.db"
25
25
  OLAM_PLAN_DB_PATH: "/data/plan.db"
26
26
  OLAM_PLAN_DIR: "/data/plan"
27
+ # Same /data routing for the plan-chat bearer gateway. K8s pod runs as
28
+ # UID 1000 with readOnlyRootFilesystem: true, so the bearer file CAN
29
+ # NEVER be created under /home/node/.olam even with mkdir-recursive —
30
+ # the env override is mandatory here, not optional. Bind-mounted /data
31
+ # is the writable PVC.
32
+ OLAM_PLAN_CHAT_SECRET_PATH: "/data/plan-chat-secret"
27
33
  # Tunable defaults.
28
34
  OLAM_SECRET_CACHE_TTL_SEC: "300"
29
35
  OLAM_PR_POLL_INTERVAL_MS: "300000"
@@ -18,20 +18,30 @@
18
18
  # before the main container starts, granting UID-1000 write access on the
19
19
  # freshly-provisioned PV. fsGroup alone is insufficient for hostPath volumes.
20
20
  #
21
- # gh-config (/gh-config) and operator-repo (/operator-repo) remain hostPath
22
- # volumes that resolve to paths inside the k3d node container.
23
- # OPERATORS MUST pass these volume mounts when creating the k3d cluster:
21
+ # docker-sock (/var/run/docker.sock): hostPath volume — the operator must
22
+ # bind the host docker socket into the k3d node container when creating
23
+ # the cluster (Decision #3 direct hostPath mount, not docker-socket-proxy):
24
24
  #
25
25
  # k3d cluster create olam-host \
26
+ # --volume /var/run/docker.sock:/var/run/docker.sock@server:* \
26
27
  # --volume ~/.config/gh:/host/.config/gh \
27
28
  # --volume <olam-repo-root>:/host/olam \
28
29
  # --wait --timeout 90s
29
30
  #
30
- # Without these flags the gh-config and operator-repo mounts will be empty
31
- # (the paths exist inside the node container but contain no data from the
32
- # operator's host). The pod will still start — features that depend on GitHub
33
- # auth or the operator repo will fail gracefully. The Phase D install guide
34
- # surfaces this requirement prominently.
31
+ # An init container (socket-perm) runs `chmod 666 /var/run/docker.sock` as
32
+ # root BEFORE the main container starts. This grants the non-root main
33
+ # container (UID 1000) read+write access to the daemon socket.
34
+ # Deliberate platform-permission concession see Decision #15:
35
+ # init container as root is the only way to grant non-root main container
36
+ # socket access without bake-time UID alignment on a single-tenant machine.
37
+ #
38
+ # gh-config (/gh-config) and operator-repo (/operator-repo) remain hostPath
39
+ # volumes that resolve to paths inside the k3d node container.
40
+ # OPERATORS MUST pass these volume mounts when creating the k3d cluster (see
41
+ # the k3d command above). Without these flags the gh-config and operator-repo
42
+ # mounts will be empty. The pod will still start — features that depend on
43
+ # GitHub auth or the operator repo will fail gracefully. The Phase D install
44
+ # guide surfaces this requirement prominently.
35
45
  apiVersion: apps/v1
36
46
  kind: Deployment
37
47
  metadata:
@@ -78,9 +88,26 @@ spec:
78
88
  volumeMounts:
79
89
  - name: olam-home
80
90
  mountPath: /data
91
+ - name: socket-perm
92
+ # busybox:1.36 — same sha256-pinned image as chown-data above.
93
+ # Deliberate platform-permission concession — see Decision #15.
94
+ # Runs as root to chmod the docker socket before the non-root main
95
+ # container starts. 666 (world-rw) is intentional on a single-tenant
96
+ # operator machine: UID 1000 must write to a root-owned socket without
97
+ # UID alignment at image build time.
98
+ image: busybox@sha256:73aaf090f3d85aa34ee199857f03fa3a95c8ede2ffd4cc2cdb5b94e566b11662
99
+ imagePullPolicy: IfNotPresent
100
+ securityContext:
101
+ runAsUser: 0
102
+ runAsNonRoot: false
103
+ allowPrivilegeEscalation: false
104
+ command: ["sh", "-c", "chmod 666 /var/run/docker.sock"]
105
+ volumeMounts:
106
+ - name: docker-sock
107
+ mountPath: /var/run/docker.sock
81
108
  containers:
82
109
  - name: olam-host-cp
83
- image: ghcr.io/pleri/olam-host-cp@sha256:513b16e1c36c96f4a03b431445da45cabf83c85b5761d1c93fab684a13c7354b
110
+ image: ghcr.io/pleri/olam-host-cp@sha256:fb5af6e69c63ac1d2a20d6a070e5eae534e948ec2502e5fd3d24640197952208
84
111
  imagePullPolicy: IfNotPresent
85
112
  securityContext:
86
113
  runAsNonRoot: true
@@ -109,6 +136,8 @@ spec:
109
136
  readOnly: true
110
137
  - name: tmp
111
138
  mountPath: /tmp
139
+ - name: docker-sock
140
+ mountPath: /var/run/docker.sock
112
141
  readinessProbe:
113
142
  httpGet:
114
143
  path: /api/version/status
@@ -146,3 +175,11 @@ spec:
146
175
  type: DirectoryOrCreate
147
176
  - name: tmp
148
177
  emptyDir: {}
178
+ - name: docker-sock
179
+ # D4 — Direct hostPath docker socket mount (Decision #3, architecture a2).
180
+ # The operator must bind the host docker socket into the k3d node when
181
+ # creating the cluster: --volume /var/run/docker.sock:/var/run/docker.sock@server:*
182
+ # Without this bind-mount the socket path exists inside the node but is empty.
183
+ hostPath:
184
+ path: /var/run/docker.sock
185
+ type: Socket
@@ -1,12 +1,15 @@
1
1
  # Deployment for olam-auth-service.
2
2
  #
3
3
  # Image: pinned to sha256 digest (not :latest or named tag) per T4 threat model.
4
- # Digest resolves to ghcr.io/pleri/olam-auth-service:0.1.0 (multi-arch index).
4
+ # Digest resolves to ghcr.io/pleri/olam-auth:latest (multi-arch index).
5
+ # NOTE (B1): image name is olam-auth (NOT olam-auth-service) — matches the
6
+ # actual GHCR package name published by release.yml publish-auth job.
5
7
  # To update: resolve the new tag's digest via:
6
- # TOKEN=$(curl -s "https://ghcr.io/token?scope=repository:pleri/olam-auth-service:pull&service=ghcr.io" | jq -r .token)
8
+ # TOKEN=$(curl -s "https://ghcr.io/token?scope=repository:pleri/olam-auth:pull&service=ghcr.io" | jq -r .token)
7
9
  # curl -sI -H "Authorization: Bearer $TOKEN" \
8
10
  # -H "Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json" \
9
- # https://ghcr.io/v2/pleri/olam-auth-service/manifests/<tag> | grep docker-content-digest
11
+ # https://ghcr.io/v2/pleri/olam-auth/manifests/<tag> | grep docker-content-digest
12
+ # Or use: node scripts/refresh-manifest-digests.mjs
10
13
  #
11
14
  # securityContext: conservative defaults per T6/T7 threat model (runAsNonRoot,
12
15
  # readOnlyRootFilesystem). /tmp backed by emptyDir for transient write needs.
@@ -60,7 +63,7 @@ spec:
60
63
  mountPath: /data
61
64
  containers:
62
65
  - name: olam-auth-service
63
- image: ghcr.io/pleri/olam-auth-service@sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
66
+ image: ghcr.io/pleri/olam-auth@sha256:25c8dc7b8725f699c54897423970df4e33b16a31b6f5d2769216fa488db2396c
64
67
  imagePullPolicy: IfNotPresent
65
68
  securityContext:
66
69
  runAsNonRoot: true
@@ -54,7 +54,7 @@ spec:
54
54
  mountPath: /data
55
55
  containers:
56
56
  - name: olam-kg-service
57
- image: ghcr.io/pleri/olam-kg-service@sha256:c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
57
+ image: ghcr.io/pleri/olam-kg-service@sha256:2874c019a45e8771ffa07f55150482a75b75a8df02f72cd32084d2cc80f5c5f9
58
58
  imagePullPolicy: IfNotPresent
59
59
  securityContext:
60
60
  runAsNonRoot: true