@pleri/olam-cli 0.1.158 → 0.1.159

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6392,21 +6392,21 @@ var init_exec = __esm({
6392
6392
  const stream = await exec.start({ Detach: false, Tty: false });
6393
6393
  const timeoutMs = opts?.timeout ? opts.timeout * 1e3 : void 0;
6394
6394
  const outputPromise = demuxStream(stream);
6395
- let output;
6395
+ let output2;
6396
6396
  if (timeoutMs) {
6397
6397
  const timer = new Promise((_, reject) => {
6398
6398
  setTimeout(() => reject(new Error(`Command timed out after ${opts.timeout}s`)), timeoutMs);
6399
6399
  });
6400
- output = await Promise.race([outputPromise, timer]);
6400
+ output2 = await Promise.race([outputPromise, timer]);
6401
6401
  } else {
6402
- output = await outputPromise;
6402
+ output2 = await outputPromise;
6403
6403
  }
6404
6404
  const inspection = await exec.inspect();
6405
6405
  const exitCode = inspection.ExitCode ?? 1;
6406
6406
  return {
6407
6407
  exitCode,
6408
- stdout: output.stdout,
6409
- stderr: output.stderr
6408
+ stdout: output2.stdout,
6409
+ stderr: output2.stderr
6410
6410
  };
6411
6411
  };
6412
6412
  }
@@ -7884,27 +7884,6 @@ function hasImageRef(present, ref) {
7884
7884
  const variants = [`docker.io/library/${ref}`, `docker.io/${ref}`];
7885
7885
  return variants.some((v) => present.has(v));
7886
7886
  }
7887
- function defaultDetectK8sClusterType(kubectlContext) {
7888
- const ctx = kubectlContext ?? readCurrentKubectlContext();
7889
- if (!ctx) return "unknown";
7890
- if (ctx.startsWith("colima")) return "colima";
7891
- if (ctx.startsWith("k3d-")) return "k3d";
7892
- return "unknown";
7893
- }
7894
- function readCurrentKubectlContext() {
7895
- const r = spawnSync3("kubectl", ["config", "current-context"], {
7896
- encoding: "utf-8",
7897
- stdio: ["ignore", "pipe", "pipe"]
7898
- });
7899
- if (r.status !== 0) return void 0;
7900
- return r.stdout?.trim() || void 0;
7901
- }
7902
- function buildDockerSocketRemedy(clusterType) {
7903
- if (clusterType === "colima") {
7904
- return "Recreate the Colima k3s cluster with the docker socket bind-mount:\n colima stop\n colima start --kubernetes \\\n --mount /var/run/docker.sock:/var/run/docker.sock:w \\\n --mount ~/.config/gh:/host/.config/gh:r\nThen run: olam upgrade";
7905
- }
7906
- return "Recreate the k3d cluster with the docker socket bind-mount:\n k3d cluster create olam-host \\\n --volume /var/run/docker.sock:/var/run/docker.sock@server:* \\\n --volume ~/.config/gh:/host/.config/gh \\\n --wait --timeout 90s\nThen run: olam upgrade";
7907
- }
7908
7887
  var HEALTH_TIMEOUT_MS, COLIMA_010_WARN_TEXT, COLIMA_010_RANGE, defaultDockerExec, defaultFetch;
7909
7888
  var init_health_probes = __esm({
7910
7889
  "src/lib/health-probes.ts"() {
@@ -8475,8 +8454,8 @@ function removeBranch(repo, branch) {
8475
8454
  }
8476
8455
  let localCommitCount = 0;
8477
8456
  try {
8478
- const output = execFileSync2("git", ["rev-list", "--count", branch, "--not", "--remotes"], { cwd: gitDir, stdio: "pipe" }).toString().trim();
8479
- localCommitCount = parseInt(output, 10) || 0;
8457
+ const output2 = execFileSync2("git", ["rev-list", "--count", branch, "--not", "--remotes"], { cwd: gitDir, stdio: "pipe" }).toString().trim();
8458
+ localCommitCount = parseInt(output2, 10) || 0;
8480
8459
  } catch {
8481
8460
  localCommitCount = 1;
8482
8461
  }
@@ -8711,8 +8690,8 @@ function writeStrippedMcpServersSnapshot(homeDir, workspacePath, destClaudeDir)
8711
8690
  ...stripMcpServers(hostMcpServers),
8712
8691
  ...stripMcpServers(projectMcpServers)
8713
8692
  };
8714
- const output = { mcpServers: stripped };
8715
- fs13.writeFileSync(path15.join(destClaudeDir, ".claude.json"), JSON.stringify(output, null, 2), { mode: 384 });
8693
+ const output2 = { mcpServers: stripped };
8694
+ fs13.writeFileSync(path15.join(destClaudeDir, ".claude.json"), JSON.stringify(output2, null, 2), { mode: 384 });
8716
8695
  }
8717
8696
  function writeWorldEntitlementsJson(workspacePath, configCtx) {
8718
8697
  const olamDir = path15.join(workspacePath, ".olam");
@@ -9235,8 +9214,8 @@ import { execFileSync as execFileSync4 } from "node:child_process";
9235
9214
  import * as fs15 from "node:fs";
9236
9215
  import * as os9 from "node:os";
9237
9216
  import * as path17 from "node:path";
9238
- function expandHome2(p, homedir54) {
9239
- return p.replace(/^~(?=$|\/|\\)/, homedir54());
9217
+ function expandHome2(p, homedir55) {
9218
+ return p.replace(/^~(?=$|\/|\\)/, homedir55());
9240
9219
  }
9241
9220
  function sanitizeRepoFilename(name) {
9242
9221
  const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -9259,7 +9238,7 @@ ${stderr}`;
9259
9238
  }
9260
9239
  function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
9261
9240
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
9262
- const homedir54 = deps.homedir ?? (() => os9.homedir());
9241
+ const homedir55 = deps.homedir ?? (() => os9.homedir());
9263
9242
  const baselineDir = path17.join(workspacePath, ".olam", "baseline");
9264
9243
  try {
9265
9244
  fs15.mkdirSync(baselineDir, { recursive: true });
@@ -9275,7 +9254,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
9275
9254
  continue;
9276
9255
  const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
9277
9256
  const outPath = path17.join(baselineDir, filename);
9278
- const repoPath = expandHome2(repo.path, homedir54);
9257
+ const repoPath = expandHome2(repo.path, homedir55);
9279
9258
  if (!fs15.existsSync(repoPath)) {
9280
9259
  writeBaselineFile(outPath, `# repo: ${repo.name}
9281
9260
  # (skipped: path ${repoPath} does not exist)
@@ -9395,7 +9374,7 @@ function extractStderr(err) {
9395
9374
  }
9396
9375
  function carryUncommittedEdits(repos, workspacePath, deps = {}) {
9397
9376
  const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
9398
- const homedir54 = deps.homedir ?? (() => os9.homedir());
9377
+ const homedir55 = deps.homedir ?? (() => os9.homedir());
9399
9378
  const existsSync103 = deps.existsSync ?? ((p) => fs15.existsSync(p));
9400
9379
  const copyFileSync12 = deps.copyFileSync ?? ((src, dest) => fs15.copyFileSync(src, dest));
9401
9380
  const mkdirSync60 = deps.mkdirSync ?? ((dirPath, opts) => {
@@ -9405,7 +9384,7 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
9405
9384
  for (const repo of repos) {
9406
9385
  if (!repo.path)
9407
9386
  continue;
9408
- const repoPath = expandHome2(repo.path, homedir54);
9387
+ const repoPath = expandHome2(repo.path, homedir55);
9409
9388
  const worktreePath = path17.join(workspacePath, repo.name);
9410
9389
  if (!existsSync103(repoPath))
9411
9390
  continue;
@@ -21768,7 +21747,6 @@ import { stringify as yamlStringify2 } from "yaml";
21768
21747
 
21769
21748
  // src/lib/upgrade-kubernetes.ts
21770
21749
  init_output();
21771
- init_health_probes();
21772
21750
  import * as fs32 from "node:fs";
21773
21751
  import "node:os";
21774
21752
  import * as path33 from "node:path";
@@ -22136,7 +22114,7 @@ function appendAuditEntry(entry, auditLogPath, writeFileSyncImpl) {
22136
22114
  async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, peripheral) {
22137
22115
  const auditLogPath = deps.auditLogPath ?? MANIFEST_REFRESH_AUDIT_LOG;
22138
22116
  const readdirSync28 = deps.readdirSync ?? fs31.readdirSync;
22139
- const readFileSync78 = deps.readFileSync ?? fs31.readFileSync;
22117
+ const readFileSync80 = deps.readFileSync ?? fs31.readFileSync;
22140
22118
  const writeFileSyncImpl = deps.writeFileSync ?? fs31.writeFileSync;
22141
22119
  const existsSync103 = deps.existsSync ?? fs31.existsSync;
22142
22120
  const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
@@ -22162,7 +22140,7 @@ async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, per
22162
22140
  const filePath = path32.join(targetDir, file);
22163
22141
  let content;
22164
22142
  try {
22165
- content = readFileSync78(filePath, "utf8");
22143
+ content = readFileSync80(filePath, "utf8");
22166
22144
  } catch {
22167
22145
  continue;
22168
22146
  }
@@ -22531,7 +22509,100 @@ ${a.stderr}
22531
22509
  return { exitCode: 0, result: { applied, skipped, secretResults: results } };
22532
22510
  }
22533
22511
 
22512
+ // src/lib/host-side-proxy.ts
22513
+ import { spawnSync as spawnSync16 } from "node:child_process";
22514
+ function probeDockerCompose(deps) {
22515
+ const spawn13 = deps.spawnSyncImpl ?? spawnSync16;
22516
+ const env = deps.dockerContext !== void 0 ? { ...process.env, DOCKER_CONTEXT: deps.dockerContext } : process.env;
22517
+ const r = spawn13("docker", ["compose", "version"], {
22518
+ env,
22519
+ encoding: "utf8",
22520
+ timeout: 5e3
22521
+ });
22522
+ if (r.error !== void 0 || r.status !== 0) {
22523
+ return {
22524
+ ok: false,
22525
+ reason: "docker compose plugin not found. Install via `brew install docker-compose` or the Docker Desktop installer. The legacy `docker-compose` binary is NOT a substitute \u2014 olam requires `docker compose` (v2 plugin) for the host-side docker-socket-proxy lifecycle on macOS."
22526
+ };
22527
+ }
22528
+ return { ok: true };
22529
+ }
22530
+ function startHostSideProxy(composePath, deps = {}) {
22531
+ const probe2 = probeDockerCompose(deps);
22532
+ if (!probe2.ok) {
22533
+ return probe2;
22534
+ }
22535
+ const spawn13 = deps.spawnSyncImpl ?? spawnSync16;
22536
+ const env = deps.dockerContext !== void 0 ? { ...process.env, DOCKER_CONTEXT: deps.dockerContext } : process.env;
22537
+ const r = spawn13("docker", ["compose", "-f", composePath, "up", "-d"], {
22538
+ env,
22539
+ encoding: "utf8",
22540
+ timeout: 6e4
22541
+ });
22542
+ if (r.error !== void 0) {
22543
+ return { ok: false, reason: `docker compose up failed: ${r.error.message}` };
22544
+ }
22545
+ if (r.status !== 0) {
22546
+ const stderr = (r.stderr ?? "").toString().trim();
22547
+ return {
22548
+ ok: false,
22549
+ reason: `docker compose -f ${composePath} up -d exited ${r.status ?? "null"}: ${stderr || "(no stderr)"}. Check: \`docker context ls\` shows colima active; \`docker info\` succeeds; the compose file exists at the printed path.`
22550
+ };
22551
+ }
22552
+ return { ok: true };
22553
+ }
22554
+ function statusHostSideProxy(composePath, deps = {}) {
22555
+ const probe2 = probeDockerCompose(deps);
22556
+ if (!probe2.ok) {
22557
+ return { ok: false, status: "unknown", reason: probe2.reason };
22558
+ }
22559
+ const spawn13 = deps.spawnSyncImpl ?? spawnSync16;
22560
+ const env = deps.dockerContext !== void 0 ? { ...process.env, DOCKER_CONTEXT: deps.dockerContext } : process.env;
22561
+ const r = spawn13("docker", ["compose", "-f", composePath, "ps", "--format", "json"], {
22562
+ env,
22563
+ encoding: "utf8",
22564
+ timeout: 1e4
22565
+ });
22566
+ if (r.error !== void 0 || r.status !== 0) {
22567
+ return {
22568
+ ok: false,
22569
+ status: "unknown",
22570
+ reason: `docker compose ps failed: ${(r.stderr ?? r.error?.message ?? "(no detail)").toString().trim()}`
22571
+ };
22572
+ }
22573
+ const stdout = (r.stdout ?? "").toString().trim();
22574
+ if (stdout === "" || stdout === "[]") {
22575
+ return { ok: true, status: "stopped" };
22576
+ }
22577
+ try {
22578
+ const parsed = stdout.startsWith("[") ? JSON.parse(stdout) : stdout.split("\n").filter((line) => line.trim() !== "").map((line) => JSON.parse(line));
22579
+ if (!Array.isArray(parsed) || parsed.length === 0) {
22580
+ return { ok: true, status: "stopped" };
22581
+ }
22582
+ const allRunning = parsed.every((entry) => {
22583
+ if (typeof entry !== "object" || entry === null) {
22584
+ return false;
22585
+ }
22586
+ const state = entry.State;
22587
+ return typeof state === "string" && state.toLowerCase() === "running";
22588
+ });
22589
+ return { ok: true, status: allRunning ? "running" : "stopped" };
22590
+ } catch {
22591
+ return {
22592
+ ok: false,
22593
+ status: "unknown",
22594
+ reason: "docker compose ps emitted unparseable JSON; check `docker compose version`."
22595
+ };
22596
+ }
22597
+ }
22598
+
22534
22599
  // src/lib/upgrade-kubernetes.ts
22600
+ function resolveHostSideProxyComposePath() {
22601
+ const root = resolveK8sAssetsRoot();
22602
+ if (root === null) return null;
22603
+ const candidate = path33.join(root, "host-side", "docker-socket-proxy.compose.yaml");
22604
+ return fs32.existsSync(candidate) ? candidate : null;
22605
+ }
22535
22606
  var OLAM_K8S_MANIFESTS_DIR = path33.join(OLAM_HOME, "k8s", "manifests");
22536
22607
  var K8S_NAMESPACE3 = "olam";
22537
22608
  var HOST_CP_SECRET_NAME = "olam-host-cp-secret";
@@ -22597,28 +22668,6 @@ async function detectManagedK8sProvider(deps) {
22597
22668
  }
22598
22669
  return null;
22599
22670
  }
22600
- async function checkDockerSocketAccessible(context, deps) {
22601
- if (deps.checkDockerSocketImpl) {
22602
- return deps.checkDockerSocketImpl(context);
22603
- }
22604
- const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
22605
- const result = await wrap(
22606
- [
22607
- "--context",
22608
- context,
22609
- "exec",
22610
- "deploy/olam-host-cp",
22611
- "-n",
22612
- "olam",
22613
- "--",
22614
- "test",
22615
- "-S",
22616
- "/var/run/docker.sock"
22617
- ],
22618
- { timeout: 1e4 }
22619
- );
22620
- return result.ok;
22621
- }
22622
22671
  async function probeKubernetesApiReachable(context, deps) {
22623
22672
  const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
22624
22673
  const result = await wrap(
@@ -22672,11 +22721,11 @@ async function checkSecretPreCondition(context, deps) {
22672
22721
  }
22673
22722
  async function applyConfigMapSubstitution(context, manifestsDir, deps) {
22674
22723
  const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
22675
- const readFileSync78 = deps.readFileSyncImpl ?? fs32.readFileSync;
22724
+ const readFileSync80 = deps.readFileSyncImpl ?? fs32.readFileSync;
22676
22725
  const configMapPath = path33.join(manifestsDir, "30-configmap.yaml");
22677
22726
  let rawYaml;
22678
22727
  try {
22679
- rawYaml = readFileSync78(configMapPath, "utf8");
22728
+ rawYaml = readFileSync80(configMapPath, "utf8");
22680
22729
  } catch (err) {
22681
22730
  return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
22682
22731
  }
@@ -22818,48 +22867,6 @@ async function createGhcrPullSecret(context, deps, stderr) {
22818
22867
  }
22819
22868
  return { skipped: false };
22820
22869
  }
22821
- var K3D_NODE_CONTAINER = "k3d-olam-host-server-0";
22822
- async function defaultCheckK3dNodeMounts() {
22823
- const { execFile } = await import("node:child_process");
22824
- const { promisify } = await import("node:util");
22825
- const execFileAsync = promisify(execFile);
22826
- try {
22827
- const { stdout } = await execFileAsync(
22828
- "docker",
22829
- ["inspect", K3D_NODE_CONTAINER, "--format", "{{json .HostConfig.Binds}}"],
22830
- { timeout: 8e3 }
22831
- );
22832
- const binds = JSON.parse(stdout.trim());
22833
- if (!Array.isArray(binds)) return "none";
22834
- if (binds.some((b) => b.includes("/host-colima/"))) return "new-form";
22835
- if (binds.some((b) => b.startsWith("/var/run/docker.sock:"))) return "old-form";
22836
- return "none";
22837
- } catch {
22838
- return "none";
22839
- }
22840
- }
22841
- async function preflightK3dNodeMounts(deps, stderr) {
22842
- const check = deps.checkK3dNodeMountsImpl ?? defaultCheckK3dNodeMounts;
22843
- const form = await check();
22844
- if (form === "new-form") {
22845
- return null;
22846
- }
22847
- if (form === "old-form") {
22848
- return `Your k3d cluster was created with the old --volume form which fails on colima.
22849
- Recreate the cluster with:
22850
- k3d cluster delete olam-host
22851
- k3d cluster create olam-host --volume "$HOME/.colima/default/:/host-colima/@server:*"
22852
- Then re-run olam upgrade.`;
22853
- }
22854
- stderr.write(
22855
- `${pc9.yellow("[warn]")} step 0.5: k3d node container "${K3D_NODE_CONTAINER}" not found or bind form undetectable.
22856
- This is expected on non-k3d clusters (bare k3s, minikube). Continuing.
22857
- On colima+k3d: ensure the cluster was created with:
22858
- k3d cluster create olam-host --volume "$HOME/.colima/default/:/host-colima/@server:*"
22859
- `
22860
- );
22861
- return null;
22862
- }
22863
22870
  async function runUpgradeKubernetes(opts = {}, deps = {}) {
22864
22871
  const stdout = deps.stdout ?? process.stdout;
22865
22872
  const stderr = deps.stderr ?? process.stderr;
@@ -22877,14 +22884,6 @@ async function runUpgradeKubernetes(opts = {}, deps = {}) {
22877
22884
  return { exitCode: 1, summary: "manifest seed failed" };
22878
22885
  }
22879
22886
  }
22880
- {
22881
- const step05Error = await preflightK3dNodeMounts(deps, stderr);
22882
- if (step05Error !== null) {
22883
- stderr.write(`${pc9.red("error:")} ${step05Error}
22884
- `);
22885
- return { exitCode: 1, summary: "k3d node bind-mount preflight failed (Decision #11)" };
22886
- }
22887
- }
22888
22887
  const resolved = resolveKubectlContext(deps.configPath);
22889
22888
  if (resolved.error !== void 0) {
22890
22889
  stderr.write(`${pc9.red("error:")} ${resolved.error}
@@ -22911,22 +22910,6 @@ async function runUpgradeKubernetes(opts = {}, deps = {}) {
22911
22910
  return { exitCode: 1, summary: "managed-k8s context detected (Decision #18 retraction)" };
22912
22911
  }
22913
22912
  }
22914
- {
22915
- const socketAccessible = await checkDockerSocketAccessible(pinnedContext, deps);
22916
- if (!socketAccessible) {
22917
- const clusterType = defaultDetectK8sClusterType(pinnedContext);
22918
- const remedyText = buildDockerSocketRemedy(clusterType).split("\n").map((line) => ` ${line}`).join("\n");
22919
- stderr.write(
22920
- `${pc9.yellow("[WARN]")} docker socket not accessible at /var/run/docker.sock inside the host-cp pod.
22921
- This means the cluster was not created with the docker socket bind-mount,
22922
- or host-cp is not yet deployed (first install \u2014 this warning is expected).
22923
- For subsequent upgrades:
22924
- ${remedyText}
22925
- Run olam doctor to check probe 28 (probeDockerSocketBindMount).
22926
- `
22927
- );
22928
- }
22929
- }
22930
22913
  const step0Spinner = ora3("Probing Kubernetes API reachability").start();
22931
22914
  const reachable = await probeKubernetesApiReachable(pinnedContext, deps);
22932
22915
  if (!reachable) {
@@ -22979,6 +22962,27 @@ ${remedyText}
22979
22962
  step06Spinner.succeed("ghcr-pull imagePullSecret created/updated");
22980
22963
  }
22981
22964
  }
22965
+ if (process.platform === "darwin") {
22966
+ const step07Spinner = ora3("Starting host-side docker-socket-proxy (R4-W2-F)").start();
22967
+ const composePath = resolveHostSideProxyComposePath();
22968
+ if (composePath === null) {
22969
+ step07Spinner.warn("host-side docker-socket-proxy compose yaml not found (bundle layout?)");
22970
+ stderr.write(
22971
+ `${pc9.yellow("[warn]")} could not locate docker-socket-proxy.compose.yaml in the bundled k8s assets.
22972
+ This is a packaging bug \u2014 please report. Continuing without auto-start.
22973
+ `
22974
+ );
22975
+ } else {
22976
+ const startResult = startHostSideProxy(composePath);
22977
+ if (!startResult.ok) {
22978
+ step07Spinner.warn(`host-side docker-socket-proxy start failed (continuing): ${startResult.reason ?? "unknown"}`);
22979
+ stderr.write(`${pc9.yellow("[warn]")} ${startResult.reason ?? "unknown error"}
22980
+ `);
22981
+ } else {
22982
+ step07Spinner.succeed("docker-socket-proxy ready on host");
22983
+ }
22984
+ }
22985
+ }
22982
22986
  const step1Spinner = ora3("Verifying kubectl context (D10)").start();
22983
22987
  if (!isContextAllowed(pinnedContext)) {
22984
22988
  step1Spinner.fail("Context disallowed");
@@ -23464,7 +23468,7 @@ ${pc11.dim("Next: olam create --name my-world")}`);
23464
23468
 
23465
23469
  // src/commands/create.ts
23466
23470
  init_manager();
23467
- import { spawnSync as spawnSync18 } from "node:child_process";
23471
+ import { spawnSync as spawnSync19 } from "node:child_process";
23468
23472
  import { existsSync as existsSync38 } from "node:fs";
23469
23473
  import { dirname as dirname27, resolve as resolve14 } from "node:path";
23470
23474
  import ora5 from "ora";
@@ -23702,9 +23706,9 @@ init_output();
23702
23706
  init_host_cp();
23703
23707
 
23704
23708
  // src/lib/world-mcp-register.ts
23705
- import { spawnSync as spawnSync16 } from "node:child_process";
23709
+ import { spawnSync as spawnSync17 } from "node:child_process";
23706
23710
  var DEFAULT_DOCKER_EXEC_DEPS = {
23707
- spawn: spawnSync16,
23711
+ spawn: spawnSync17,
23708
23712
  log: (msg) => console.log(msg)
23709
23713
  };
23710
23714
  var MCP_NAME = "agentmemory";
@@ -23769,7 +23773,7 @@ function registerAgentMemoryMcp(opts, deps = DEFAULT_DOCKER_EXEC_DEPS) {
23769
23773
  init_install_root();
23770
23774
  import * as fs34 from "node:fs";
23771
23775
  import * as path35 from "node:path";
23772
- import { spawnSync as spawnSync17 } from "node:child_process";
23776
+ import { spawnSync as spawnSync18 } from "node:child_process";
23773
23777
  import ora4 from "ora";
23774
23778
 
23775
23779
  // src/lib/bundle-source.ts
@@ -23892,7 +23896,7 @@ function buildIfStale(repoRoot, env = process.env) {
23892
23896
  }
23893
23897
  const reason = distMtime === 0 ? "dist is absent" : `source newer by ${Math.round((srcMtime - distMtime) / 1e3)}s`;
23894
23898
  const spinner = ora4(`Rebuilding agent-stream bundle\u2026 (${reason})`).start();
23895
- const result = spawnSync17(
23899
+ const result = spawnSync18(
23896
23900
  "npm",
23897
23901
  ["run", "build", "--workspace=@olam/intelligence"],
23898
23902
  {
@@ -23956,7 +23960,7 @@ function registerCreate(program2) {
23956
23960
  if (decision.stderrLine) {
23957
23961
  process.stderr.write(decision.stderrLine + "\n");
23958
23962
  }
23959
- spawnSync18("docker", ["pull", overrideRef], { stdio: "pipe" });
23963
+ spawnSync19("docker", ["pull", overrideRef], { stdio: "pipe" });
23960
23964
  const { inspectImageProtocolVersions: inspectImageProtocolVersions2, checkProtocolOverlap: checkProtocolOverlap2 } = await Promise.resolve().then(() => (init_protocol_version(), protocol_version_exports));
23961
23965
  const inspect = inspectImageProtocolVersions2(overrideRef);
23962
23966
  if (inspect.inspectFailed) {
@@ -24073,7 +24077,7 @@ function registerCreate(program2) {
24073
24077
  throw err;
24074
24078
  }
24075
24079
  const spinner2 = ora5("Rebuilding olam-devbox:latest\u2026").start();
24076
- const rebuild = spawnSync18(
24080
+ const rebuild = spawnSync19(
24077
24081
  "bash",
24078
24082
  [buildScript],
24079
24083
  { cwd: repoRoot, stdio: "inherit" }
@@ -30331,7 +30335,7 @@ init_output();
30331
30335
  init_host_cp();
30332
30336
  import * as fs42 from "node:fs";
30333
30337
  import * as path44 from "node:path";
30334
- import { spawnSync as spawnSync20 } from "node:child_process";
30338
+ import { spawnSync as spawnSync21 } from "node:child_process";
30335
30339
  import ora9 from "ora";
30336
30340
  import pc20 from "picocolors";
30337
30341
 
@@ -30339,7 +30343,7 @@ import pc20 from "picocolors";
30339
30343
  import * as fs40 from "node:fs";
30340
30344
  import * as os21 from "node:os";
30341
30345
  import * as path42 from "node:path";
30342
- import { spawnSync as spawnSync19 } from "node:child_process";
30346
+ import { spawnSync as spawnSync20 } from "node:child_process";
30343
30347
  var LOCK_FILE_PATH = path42.join(os21.homedir(), ".olam", ".upgrade.lock");
30344
30348
  var STALE_LOCK_TIMEOUT_MS = 5 * 60 * 1e3;
30345
30349
  function readLockFile(lockPath) {
@@ -30364,7 +30368,7 @@ function isPidAlive2(pid) {
30364
30368
  }
30365
30369
  var PS_UNAVAILABLE = "__ps_unavailable__";
30366
30370
  function getPidCommand(pid) {
30367
- const result = spawnSync19("ps", ["-p", String(pid), "-o", "comm="], {
30371
+ const result = spawnSync20("ps", ["-p", String(pid), "-o", "comm="], {
30368
30372
  encoding: "utf-8",
30369
30373
  stdio: ["ignore", "pipe", "ignore"]
30370
30374
  });
@@ -30625,7 +30629,7 @@ function extractBundleHash(indexHtml) {
30625
30629
  function runStep2(label, cmd, args, opts = {}) {
30626
30630
  const start = Date.now();
30627
30631
  process.stdout.write(` ${pc20.dim(label.padEnd(34))}`);
30628
- const result = spawnSync20(cmd, [...args], {
30632
+ const result = spawnSync21(cmd, [...args], {
30629
30633
  encoding: "utf-8",
30630
30634
  stdio: ["ignore", "pipe", "pipe"],
30631
30635
  cwd: opts.cwd ?? process.cwd(),
@@ -30644,7 +30648,7 @@ function runStep2(label, cmd, args, opts = {}) {
30644
30648
  };
30645
30649
  }
30646
30650
  function isGitDirty(cwd) {
30647
- const result = spawnSync20("git", ["status", "--porcelain"], {
30651
+ const result = spawnSync21("git", ["status", "--porcelain"], {
30648
30652
  encoding: "utf-8",
30649
30653
  stdio: ["ignore", "pipe", "pipe"],
30650
30654
  cwd
@@ -30652,7 +30656,7 @@ function isGitDirty(cwd) {
30652
30656
  return (result.stdout ?? "").trim().length > 0;
30653
30657
  }
30654
30658
  function hasGitUpstream(cwd) {
30655
- const result = spawnSync20("git", ["rev-parse", "--abbrev-ref", "@{u}"], {
30659
+ const result = spawnSync21("git", ["rev-parse", "--abbrev-ref", "@{u}"], {
30656
30660
  encoding: "utf-8",
30657
30661
  stdio: ["ignore", "pipe", "pipe"],
30658
30662
  cwd
@@ -30660,7 +30664,7 @@ function hasGitUpstream(cwd) {
30660
30664
  return result.status === 0;
30661
30665
  }
30662
30666
  function captureHeadSha(cwd) {
30663
- const result = spawnSync20("git", ["rev-parse", "HEAD"], {
30667
+ const result = spawnSync21("git", ["rev-parse", "HEAD"], {
30664
30668
  encoding: "utf-8",
30665
30669
  stdio: ["ignore", "pipe", "pipe"],
30666
30670
  cwd
@@ -30675,7 +30679,7 @@ function abbreviateSha(sha) {
30675
30679
  }
30676
30680
  function imageExists(tag) {
30677
30681
  try {
30678
- const result = spawnSync20("docker", ["image", "inspect", "--format", "{{.Id}}", tag], {
30682
+ const result = spawnSync21("docker", ["image", "inspect", "--format", "{{.Id}}", tag], {
30679
30683
  encoding: "utf-8",
30680
30684
  stdio: ["ignore", "pipe", "ignore"]
30681
30685
  });
@@ -30691,7 +30695,7 @@ function checkRollbackSetExists(plan) {
30691
30695
  }
30692
30696
  var SMOKE_DOCKER_TIMEOUT_MS = 3e4;
30693
30697
  function smokeImage(image, targetSha) {
30694
- const createResult = spawnSync20("docker", ["create", "--name", `olam-smoke-${Date.now()}`, image], {
30698
+ const createResult = spawnSync21("docker", ["create", "--name", `olam-smoke-${Date.now()}`, image], {
30695
30699
  encoding: "utf-8",
30696
30700
  stdio: ["ignore", "pipe", "pipe"],
30697
30701
  timeout: SMOKE_DOCKER_TIMEOUT_MS
@@ -30705,7 +30709,7 @@ function smokeImage(image, targetSha) {
30705
30709
  };
30706
30710
  }
30707
30711
  const containerId = (createResult.stdout ?? "").trim();
30708
- const inspectResult = spawnSync20(
30712
+ const inspectResult = spawnSync21(
30709
30713
  "docker",
30710
30714
  ["inspect", "--format", '{{index .Config.Labels "olam.build.sha"}}', image],
30711
30715
  {
@@ -30715,7 +30719,7 @@ function smokeImage(image, targetSha) {
30715
30719
  }
30716
30720
  );
30717
30721
  if (containerId.length > 0) {
30718
- spawnSync20("docker", ["rm", "-f", containerId], {
30722
+ spawnSync21("docker", ["rm", "-f", containerId], {
30719
30723
  encoding: "utf-8",
30720
30724
  stdio: ["ignore", "ignore", "ignore"],
30721
30725
  timeout: SMOKE_DOCKER_TIMEOUT_MS
@@ -30757,7 +30761,7 @@ var PRODUCTION_SWAP_PLAN = [
30757
30761
  ];
30758
30762
  function dockerTag(source, dest) {
30759
30763
  try {
30760
- const result = spawnSync20("docker", ["tag", source, dest], {
30764
+ const result = spawnSync21("docker", ["tag", source, dest], {
30761
30765
  encoding: "utf-8",
30762
30766
  stdio: ["ignore", "ignore", "pipe"]
30763
30767
  });
@@ -30921,11 +30925,11 @@ async function waitForAuthHealthLocal(timeoutMs = AUTH_HEALTH_TIMEOUT_MS) {
30921
30925
  async function recreateAuthService() {
30922
30926
  const start = Date.now();
30923
30927
  try {
30924
- spawnSync20("docker", ["stop", "olam-auth"], {
30928
+ spawnSync21("docker", ["stop", "olam-auth"], {
30925
30929
  encoding: "utf-8",
30926
30930
  stdio: ["ignore", "ignore", "ignore"]
30927
30931
  });
30928
- spawnSync20("docker", ["rm", "olam-auth"], {
30932
+ spawnSync21("docker", ["rm", "olam-auth"], {
30929
30933
  encoding: "utf-8",
30930
30934
  stdio: ["ignore", "ignore", "ignore"]
30931
30935
  });
@@ -31223,11 +31227,11 @@ async function defaultRecreateMcpAuthForUpgrade() {
31223
31227
  }
31224
31228
  async function defaultRecreateAuthForUpgrade() {
31225
31229
  try {
31226
- spawnSync20("docker", ["stop", "olam-auth"], {
31230
+ spawnSync21("docker", ["stop", "olam-auth"], {
31227
31231
  encoding: "utf-8",
31228
31232
  stdio: ["ignore", "ignore", "ignore"]
31229
31233
  });
31230
- spawnSync20("docker", ["rm", "olam-auth"], {
31234
+ spawnSync21("docker", ["rm", "olam-auth"], {
31231
31235
  encoding: "utf-8",
31232
31236
  stdio: ["ignore", "ignore", "ignore"]
31233
31237
  });
@@ -31249,7 +31253,7 @@ async function defaultRecreateAuthForUpgrade() {
31249
31253
  }
31250
31254
  }
31251
31255
  function defaultInspectContainerLabels(containerName) {
31252
- const result = spawnSync20(
31256
+ const result = spawnSync21(
31253
31257
  "docker",
31254
31258
  [
31255
31259
  "inspect",
@@ -31273,7 +31277,7 @@ function defaultInspectContainerLabels(containerName) {
31273
31277
  return { ok: false, exists: false, project: "", service: "", stderr };
31274
31278
  }
31275
31279
  function defaultRemoveContainer(containerName) {
31276
- const result = spawnSync20("docker", ["rm", "-f", containerName], {
31280
+ const result = spawnSync21("docker", ["rm", "-f", containerName], {
31277
31281
  encoding: "utf-8",
31278
31282
  stdio: ["ignore", "pipe", "pipe"]
31279
31283
  });
@@ -31604,7 +31608,7 @@ ${spaResult.stderr}`);
31604
31608
  process.stdout.write(` ${pc20.dim(step.label.padEnd(34))}
31605
31609
  `);
31606
31610
  const start = Date.now();
31607
- const result = spawnSync20("bash", [scriptPath], {
31611
+ const result = spawnSync21("bash", [scriptPath], {
31608
31612
  stdio: "inherit",
31609
31613
  cwd,
31610
31614
  env: { ...process.env, ...olamTagEnv }
@@ -31960,7 +31964,7 @@ function registerLogs(program2) {
31960
31964
  init_context();
31961
31965
  init_output();
31962
31966
  import pc22 from "picocolors";
31963
- import { spawnSync as spawnSync21 } from "node:child_process";
31967
+ import { spawnSync as spawnSync22 } from "node:child_process";
31964
31968
  var SAFE_IDENT4 = /^[a-z0-9][a-z0-9-]{0,63}$/;
31965
31969
  function parseDockerTop(stdout) {
31966
31970
  const trimmed = stdout.trim();
@@ -32060,7 +32064,7 @@ function registerPs(program2) {
32060
32064
  const containerName = `olam-${worldId}-devbox`;
32061
32065
  let watchInterval;
32062
32066
  function fetchAndPrint() {
32063
- const result = spawnSync21(
32067
+ const result = spawnSync22(
32064
32068
  "docker",
32065
32069
  ["top", containerName, "pid", "user", "pcpu", "pmem", "stime", "stat", "cmd"],
32066
32070
  { encoding: "utf-8", timeout: 3e3 }
@@ -32553,7 +32557,7 @@ init_output();
32553
32557
  import * as fs46 from "node:fs";
32554
32558
  import * as os24 from "node:os";
32555
32559
  import * as path48 from "node:path";
32556
- import { spawnSync as spawnSync22 } from "node:child_process";
32560
+ import { spawnSync as spawnSync23 } from "node:child_process";
32557
32561
  import ora10 from "ora";
32558
32562
 
32559
32563
  // src/commands/refresh-helpers.ts
@@ -32597,7 +32601,7 @@ var RESTART_TIMEOUT_S = 30;
32597
32601
  var HEALTH_POLL_MS = 500;
32598
32602
  var HEALTH_TIMEOUT_MS2 = 3e4;
32599
32603
  function docker(args) {
32600
- const result = spawnSync22("docker", args, {
32604
+ const result = spawnSync23("docker", args, {
32601
32605
  encoding: "utf-8",
32602
32606
  stdio: ["ignore", "pipe", "pipe"]
32603
32607
  });
@@ -32784,10 +32788,10 @@ init_context();
32784
32788
  init_output();
32785
32789
  import { existsSync as existsSync53 } from "node:fs";
32786
32790
  import { dirname as dirname32, resolve as resolve15 } from "node:path";
32787
- import { spawnSync as spawnSync23 } from "node:child_process";
32791
+ import { spawnSync as spawnSync24 } from "node:child_process";
32788
32792
  var RESTART_TIMEOUT_S2 = 30;
32789
32793
  function docker2(args) {
32790
- const result = spawnSync23("docker", args, {
32794
+ const result = spawnSync24("docker", args, {
32791
32795
  encoding: "utf-8",
32792
32796
  stdio: ["ignore", "pipe", "pipe"]
32793
32797
  });
@@ -33308,9 +33312,9 @@ async function runDoctor(opts, deps = {}) {
33308
33312
  const nodeMemResult = probeNodeMemory(dockerExec, k8sCtx);
33309
33313
  rows.push({ name: "node memory", result: nodeMemResult, position: 27 });
33310
33314
  const socketCheckImpl = deps.dockerSocketCheckImpl;
33311
- const detectClusterTypeImpl = deps.detectK8sClusterTypeImpl;
33312
- const socketResult = await probeDockerSocketBindMount(k8sCtx, wrapImpl, socketCheckImpl, detectClusterTypeImpl);
33313
- rows.push({ name: "docker socket bind-mount", result: socketResult, position: 28 });
33315
+ const composePath = deps.hostSideProxyComposePathOverride !== void 0 ? deps.hostSideProxyComposePathOverride : defaultResolveHostSideProxyComposePath();
33316
+ const socketResult = await probeHostSideProxyReachability(composePath, socketCheckImpl);
33317
+ rows.push({ name: "host-side proxy", result: socketResult, position: 28 });
33314
33318
  } else {
33315
33319
  const bundleResult = await probeBundleFreshness({
33316
33320
  dockerExec,
@@ -33530,36 +33534,50 @@ function probeNodeMemory(dockerExec, kubectlContext) {
33530
33534
  message: `node free RAM ${freeGiB.toFixed(1)} GiB (\u2265${WARN_THRESHOLD_GIB} GiB threshold)`
33531
33535
  };
33532
33536
  }
33533
- async function defaultDockerSocketCheck(kubectlContext, wrapImpl) {
33534
- const ctxArgs = kubectlContext ? ["--context", kubectlContext] : [];
33535
- const result = await wrapImpl(
33536
- [
33537
- ...ctxArgs,
33538
- "exec",
33539
- "deploy/olam-host-cp",
33540
- "-n",
33541
- "olam",
33542
- "--",
33543
- "test",
33544
- "-S",
33545
- "/var/run/docker.sock"
33546
- ],
33547
- { timeout: 1e4 }
33548
- );
33549
- return result.ok;
33537
+ function defaultResolveHostSideProxyComposePath() {
33538
+ const root = resolveK8sAssetsRoot();
33539
+ if (root === null) return null;
33540
+ const candidate = path51.join(root, "host-side", "docker-socket-proxy.compose.yaml");
33541
+ return fs49.existsSync(candidate) ? candidate : null;
33550
33542
  }
33551
- async function probeDockerSocketBindMount(kubectlContext, wrapImpl, checkImpl, detectClusterTypeImpl) {
33543
+ async function defaultDockerSocketCheck(composePath) {
33544
+ const result = statusHostSideProxy(composePath);
33545
+ return result.status;
33546
+ }
33547
+ async function probeHostSideProxyReachability(composePath, checkImpl) {
33548
+ if (composePath === null) {
33549
+ return {
33550
+ ok: true,
33551
+ warn: true,
33552
+ message: "host-side proxy compose yaml not found in CLI bundle",
33553
+ remedy: "The bundled `docker-socket-proxy.compose.yaml` could not be resolved.\nThis is a packaging issue \u2014 try `npm install -g @pleri/olam-cli@latest`\nto restore the bundled k8s assets."
33554
+ };
33555
+ }
33552
33556
  const check = checkImpl ?? defaultDockerSocketCheck;
33553
- const accessible = await check(kubectlContext, wrapImpl);
33554
- if (accessible) {
33555
- return { ok: true, message: "docker socket accessible at /var/run/docker.sock" };
33557
+ const status2 = await check(composePath);
33558
+ if (status2 === "running") {
33559
+ return {
33560
+ ok: true,
33561
+ message: "host-side docker-socket-proxy running on operator docker daemon"
33562
+ };
33563
+ }
33564
+ if (status2 === "stopped") {
33565
+ return {
33566
+ ok: true,
33567
+ warn: true,
33568
+ message: "host-side docker-socket-proxy not running",
33569
+ remedy: `Start the proxy on the operator host:
33570
+ - macOS: re-run \`olam upgrade\` (Step 0.7 auto-starts the proxy)
33571
+ - Linux: \`docker compose -f ${composePath} up -d\`
33572
+ host-cp connects to docker through this proxy via the in-cluster
33573
+ ExternalName Service \`docker-socket-proxy.olam.svc.cluster.local:2375\`.`
33574
+ };
33556
33575
  }
33557
- const clusterType = (detectClusterTypeImpl ?? defaultDetectK8sClusterType)(kubectlContext);
33558
33576
  return {
33559
33577
  ok: true,
33560
33578
  warn: true,
33561
- message: "docker socket not accessible at /var/run/docker.sock",
33562
- remedy: buildDockerSocketRemedy(clusterType)
33579
+ message: "host-side docker-socket-proxy status unknown",
33580
+ remedy: "Probe failed before reaching the docker daemon. Check:\n - `docker compose version` succeeds (compose v2 plugin installed)\n - `docker context ls` shows your active context (colima for macOS)\n - `docker info` succeeds against that context"
33563
33581
  };
33564
33582
  }
33565
33583
  async function runK8sPreflight(opts, deps = {}) {
@@ -33971,6 +33989,345 @@ function registerSubstrate(program2) {
33971
33989
  registerSubstrateAuditLog(sub);
33972
33990
  }
33973
33991
 
33992
+ // ../cli-plugin-tasks/dist/client.js
33993
+ import { readFileSync as readFileSync45 } from "node:fs";
33994
+ import { homedir as homedir28 } from "node:os";
33995
+ import { join as join59 } from "node:path";
33996
+ var TasksClient = class {
33997
+ baseUrl;
33998
+ token;
33999
+ olamNodeId;
34000
+ sessionId;
34001
+ constructor(opts) {
34002
+ this.baseUrl = (opts.hostCpUrl ?? process.env.OLAM_HOST_CP_URL ?? "http://localhost:19000").replace(/\/$/, "");
34003
+ const tokenPath2 = opts.tokenPath ?? join59(homedir28(), ".olam", "host-cp.token");
34004
+ try {
34005
+ this.token = readFileSync45(tokenPath2, "utf8").trim();
34006
+ } catch (e) {
34007
+ throw new Error(`cli-plugin-tasks: cannot read host-cp token at ${tokenPath2} (${e instanceof Error ? e.message : "unknown"}). Bootstrap host-cp first.`);
34008
+ }
34009
+ this.olamNodeId = opts.olamNodeId;
34010
+ this.sessionId = opts.sessionId;
34011
+ }
34012
+ async call(method, path91, scopes, body, query) {
34013
+ const qs = query ? "?" + new URLSearchParams(Object.entries(query).filter(([, v]) => v !== void 0)).toString() : "";
34014
+ const url2 = `${this.baseUrl}${path91}${qs}`;
34015
+ const res = await fetch(url2, {
34016
+ method,
34017
+ headers: {
34018
+ "Content-Type": "application/json",
34019
+ Authorization: `Bearer ${this.token}`,
34020
+ "X-Olam-Node-Id": this.olamNodeId,
34021
+ "X-Olam-Session-Id": this.sessionId,
34022
+ "X-Olam-Tasks-Scopes": scopes.join(",")
34023
+ },
34024
+ body: body && method === "POST" ? JSON.stringify(body) : void 0
34025
+ });
34026
+ const envelope = await res.json().catch(() => ({ success: false, data: null, error: "invalid JSON response" }));
34027
+ return { status: res.status, envelope };
34028
+ }
34029
+ };
34030
+
34031
+ // ../cli-plugin-tasks/dist/tracker-parser.js
34032
+ import { readFileSync as readFileSync46 } from "node:fs";
34033
+ import { createHash as createHash6 } from "node:crypto";
34034
+ function contentHash(parts) {
34035
+ const normalized = parts.map((p) => (p ?? "").trim()).join("|");
34036
+ const h = createHash6("sha256").update(normalized).digest("hex");
34037
+ return `sha256-${h.slice(0, 16)}`;
34038
+ }
34039
+ function parseFrontmatter2(raw) {
34040
+ if (!raw.startsWith("---\n"))
34041
+ return { frontmatter: {}, body: raw };
34042
+ const end = raw.indexOf("\n---\n", 4);
34043
+ if (end === -1)
34044
+ return { frontmatter: {}, body: raw };
34045
+ const yaml = raw.slice(4, end);
34046
+ const body = raw.slice(end + 5);
34047
+ const fm = {};
34048
+ for (const line of yaml.split("\n")) {
34049
+ const m = /^(\w+):\s*(.+?)\s*$/.exec(line);
34050
+ if (!m)
34051
+ continue;
34052
+ const key = m[1] ?? "";
34053
+ const value = m[2] ?? "";
34054
+ if (key === "feature")
34055
+ fm.feature = value;
34056
+ else if (key === "phase")
34057
+ fm.phase = value;
34058
+ else if (key === "tier")
34059
+ fm.tier = value;
34060
+ else if (key === "autonomous")
34061
+ fm.autonomous = value === "true";
34062
+ }
34063
+ return { frontmatter: fm, body };
34064
+ }
34065
+ function parseTracker(path91) {
34066
+ const raw = readFileSync46(path91, "utf8");
34067
+ const { frontmatter, body } = parseFrontmatter2(raw);
34068
+ const lines = body.split("\n");
34069
+ const tasks = [];
34070
+ let current = null;
34071
+ let currentGoal = null;
34072
+ const flush = () => {
34073
+ if (!current)
34074
+ return;
34075
+ tasks.push({
34076
+ taskId: contentHash([current.title, currentGoal ?? "", frontmatter.feature ?? ""]),
34077
+ rawId: current.rawId,
34078
+ title: current.title,
34079
+ feature: frontmatter.feature ?? null,
34080
+ phase: frontmatter.phase ?? null,
34081
+ goal: currentGoal
34082
+ });
34083
+ current = null;
34084
+ currentGoal = null;
34085
+ };
34086
+ for (let i = 0; i < lines.length; i++) {
34087
+ const line = lines[i];
34088
+ const headerMatch = line ? /^### ([A-Za-z]+\d+(?:\.\d+)*) — (.+?)\s*$/.exec(line) : null;
34089
+ if (headerMatch) {
34090
+ flush();
34091
+ current = { rawId: headerMatch[1] ?? "", title: headerMatch[2] ?? "", lineNo: i };
34092
+ continue;
34093
+ }
34094
+ if (current && !currentGoal && line) {
34095
+ const goalMatch = /^> \*\*Goal\*\*:\s*(.+?)\s*$/.exec(line);
34096
+ if (goalMatch)
34097
+ currentGoal = goalMatch[1] ?? null;
34098
+ }
34099
+ }
34100
+ flush();
34101
+ return { frontmatter, tasks };
34102
+ }
34103
+
34104
+ // ../cli-plugin-tasks/dist/commands/workers.js
34105
+ import { randomUUID as randomUUID2 } from "node:crypto";
34106
+ var SUBSTRATES = ["mac-mini", "cloudflare-container", "gcp-vm"];
34107
+ function generateProvisionPlan(opts) {
34108
+ const workerId = opts.workerId ?? `worker-${randomUUID2().slice(0, 8)}`;
34109
+ const hostCpUrl = opts.hostCpUrl ?? "http://localhost:19000";
34110
+ const nodeId = opts.olamNodeId ?? `<OLAM_NODE_ID>`;
34111
+ const sessionId = opts.sessionId ?? `<OLAM_SESSION_ID>`;
34112
+ const tokenPlaceholder = `<TASK_TOKEN_FROM_AUTH_SERVICE>`;
34113
+ let lines;
34114
+ switch (opts.substrate) {
34115
+ case "mac-mini":
34116
+ lines = [
34117
+ `# 1. Issue task-token from auth-service:`,
34118
+ `# curl -X POST $AUTH_SERVICE_URL/credentials/issue-task-token \\`,
34119
+ `# -d '{"sub":"${workerId}","scopes":["tasks-claim","tasks-state-update"]}'`,
34120
+ `# 2. Install launchd plist:`,
34121
+ `cd packages/worker-runner/profiles/mac-mini && bash install.sh \\`,
34122
+ ` --worker-id "${workerId}" \\`,
34123
+ ` --host-cp-url "${hostCpUrl}" \\`,
34124
+ ` --olam-node-id "${nodeId}" \\`,
34125
+ ` --session-id "${sessionId}" \\`,
34126
+ ` --task-token "${tokenPlaceholder}"`,
34127
+ `# 3. Verify: launchctl list | grep com.olam.worker-runner`
34128
+ ];
34129
+ break;
34130
+ case "cloudflare-container":
34131
+ lines = [
34132
+ `# 1. Issue task-token (same as mac-mini above)`,
34133
+ `# 2. Deploy Cloudflare Container:`,
34134
+ `cd packages/worker-runner/profiles/cloudflare-container`,
34135
+ `wrangler secret put OLAM_TASK_TOKEN # paste ${tokenPlaceholder}`,
34136
+ `wrangler secret put OLAM_NODE_ID # paste ${nodeId}`,
34137
+ `wrangler secret put OLAM_HOST_CP_URL # paste ${hostCpUrl}`,
34138
+ `wrangler deploy`,
34139
+ `# 3. Verify: wrangler tail (watch worker logs)`
34140
+ ];
34141
+ break;
34142
+ case "gcp-vm":
34143
+ lines = [
34144
+ `# 1. Issue task-token (same as mac-mini above)`,
34145
+ `# 2. Provision GCP VM with workload-identity-federation:`,
34146
+ `cd packages/worker-runner/profiles/gcp-vm`,
34147
+ `terraform apply -var="worker_id=${workerId}"`,
34148
+ `gcloud compute instances create olam-worker-${workerId} \\`,
34149
+ ` --metadata-from-file startup-script=startup-script.sh \\`,
34150
+ ` --metadata olam-host-cp-url=${hostCpUrl},olam-node-id=${nodeId}`,
34151
+ `# 3. Verify: gcloud compute ssh olam-worker-${workerId} -- systemctl status olam-worker-runner`
34152
+ ];
34153
+ break;
34154
+ default: {
34155
+ const _exhaustive = opts.substrate;
34156
+ throw new Error(`Unknown substrate: ${_exhaustive}`);
34157
+ }
34158
+ }
34159
+ return {
34160
+ substrate: opts.substrate,
34161
+ workerId,
34162
+ taskTokenPlaceholder: tokenPlaceholder,
34163
+ installLines: lines
34164
+ };
34165
+ }
34166
+ function registerWorkers(program2) {
34167
+ const workers = program2.command("workers").description("Manage multi-substrate workers (B4.6; provision/list/revoke task-tokens for mac-mini/cloudflare-container/gcp-vm deploy profiles)");
34168
+ workers.command("provision <substrate>").description(`Generate substrate-specific install lines + token-issuance instructions. substrate: ${SUBSTRATES.join(" | ")}`).option("--worker-id <id>", "Worker identifier (default: random uuid-prefix)").option("--host-cp-url <url>", "host-cp URL (default: http://localhost:19000)").option("--node-id <uuid>", "Olam node ID this worker reports as (default: env OLAM_NODE_ID)").option("--session-id <uuid>", "Session ID this worker uses for claims (default: env OLAM_SESSION_ID)").option("--json", "Output structured JSON instead of operator-friendly lines").action((substrate, opts) => {
34169
+ if (!SUBSTRATES.includes(substrate)) {
34170
+ process.stderr.write(`Error: substrate must be one of: ${SUBSTRATES.join(", ")}
34171
+ `);
34172
+ process.exitCode = 1;
34173
+ return;
34174
+ }
34175
+ const plan = generateProvisionPlan({
34176
+ substrate,
34177
+ workerId: opts.workerId,
34178
+ hostCpUrl: opts.hostCpUrl,
34179
+ olamNodeId: opts.nodeId ?? process.env.OLAM_NODE_ID,
34180
+ sessionId: opts.sessionId ?? process.env.OLAM_SESSION_ID
34181
+ });
34182
+ if (opts.json) {
34183
+ process.stdout.write(JSON.stringify(plan, null, 2) + "\n");
34184
+ } else {
34185
+ process.stdout.write(`# olam workers provision: ${plan.substrate} substrate (worker-id=${plan.workerId})
34186
+
34187
+ `);
34188
+ for (const line of plan.installLines)
34189
+ process.stdout.write(line + "\n");
34190
+ }
34191
+ });
34192
+ workers.command("list").description("List active task-tokens (calls auth-service /credentials/list-task-tokens; B4.5-HTTP follow-up)").option("--json", "Output structured JSON").action((opts) => {
34193
+ const message = "olam workers list: auth-service HTTP wrap not yet shipped (B4.5-HTTP follow-up). For v1: inspect TaskTokenService blocklist via auth-service in-process surface.";
34194
+ if (opts.json) {
34195
+ process.stdout.write(JSON.stringify({ status: "pending-http-wrap", message }, null, 2) + "\n");
34196
+ } else {
34197
+ process.stderr.write(`${message}
34198
+ `);
34199
+ }
34200
+ process.exitCode = 1;
34201
+ });
34202
+ workers.command("revoke <token-or-worker-id>").description("Revoke a task-token (calls auth-service /credentials/revoke-task-token; B4.5-HTTP follow-up)").action((_target) => {
34203
+ const message = "olam workers revoke: auth-service HTTP wrap not yet shipped (B4.5-HTTP follow-up). For v1: call TaskTokenService.revoke() directly from auth-service process.";
34204
+ process.stderr.write(`${message}
34205
+ `);
34206
+ process.exitCode = 1;
34207
+ });
34208
+ }
34209
+
34210
+ // ../cli-plugin-tasks/dist/index.js
34211
+ function makeClient(opts) {
34212
+ const olamNodeId = opts.nodeId ?? process.env.OLAM_NODE_ID;
34213
+ const sessionId = opts.sessionId ?? process.env.OLAM_SESSION_ID;
34214
+ if (!olamNodeId)
34215
+ throw new Error("olam tasks: --node-id <uuid> or OLAM_NODE_ID env required");
34216
+ if (!sessionId)
34217
+ throw new Error("olam tasks: --session-id <uuid> or OLAM_SESSION_ID env required");
34218
+ return new TasksClient({ olamNodeId, sessionId });
34219
+ }
34220
+ function output(envelope, status2, json) {
34221
+ if (json) {
34222
+ process.stdout.write(JSON.stringify({ status: status2, envelope }, null, 2) + "\n");
34223
+ return;
34224
+ }
34225
+ if (status2 >= 200 && status2 < 300) {
34226
+ process.stdout.write(JSON.stringify(envelope, null, 2) + "\n");
34227
+ } else {
34228
+ process.stderr.write(`[${status2}] ${JSON.stringify(envelope, null, 2)}
34229
+ `);
34230
+ process.exitCode = 1;
34231
+ }
34232
+ }
34233
+ function registerTasks(program2) {
34234
+ const tasks = program2.command("tasks").description("Manage @olam/tasks substrate (per-node task tracking with multi-tenant compound PK + RLS)");
34235
+ tasks.command("new <title>").description("Create a new task (POST /api/tasks)").option("--feature <slug>", "Feature slug").option("--phase <letter>", "Phase letter").option("--priority <n>", "Priority 0-10", (v) => parseInt(v, 10)).option("--node-id <uuid>", "Olam node ID (or OLAM_NODE_ID env)").option("--session-id <uuid>", "Session ID (or OLAM_SESSION_ID env)").option("--json", "Output raw JSON envelope").action(async (title, opts) => {
34236
+ const client = makeClient(opts);
34237
+ const body = { title, feature: opts.feature, phase: opts.phase, priority: opts.priority };
34238
+ const { status: status2, envelope } = await client.call("POST", "/api/tasks", ["tasks-create"], body);
34239
+ output(envelope, status2, !!opts.json);
34240
+ });
34241
+ tasks.command("list").description("List tasks (GET /api/tasks)").option("--feature <slug>", "Filter by feature").option("--state <state>", "Filter by state (open|claimed|done|cancelled|blocked)").option("--limit <n>", "Max rows", (v) => parseInt(v, 10)).option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--json", "Output raw JSON envelope").action(async (opts) => {
34242
+ const client = makeClient(opts);
34243
+ const query = {
34244
+ feature: opts.feature,
34245
+ state: opts.state,
34246
+ limit: opts.limit ? String(opts.limit) : void 0
34247
+ };
34248
+ const { status: status2, envelope } = await client.call("GET", "/api/tasks", ["tasks-query"], void 0, query);
34249
+ output(envelope, status2, !!opts.json);
34250
+ });
34251
+ tasks.command("claim").description("Claim the next open task (POST /api/tasks/claim)").option("--feature <slug>", "Filter by feature").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--json", "Output raw JSON envelope").action(async (opts) => {
34252
+ const client = makeClient(opts);
34253
+ const body = opts.feature ? { filter: { feature: opts.feature } } : {};
34254
+ const { status: status2, envelope } = await client.call("POST", "/api/tasks/claim", ["tasks-claim"], body);
34255
+ output(envelope, status2, !!opts.json);
34256
+ });
34257
+ tasks.command("heartbeat <task-id>").description("Heartbeat an active claim (POST /api/tasks/:id/heartbeat)").requiredOption("--creator-node-id <uuid>", "Task creator olam node ID").requiredOption("--claim-token <token>", "Claim token from `olam tasks claim`").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--json", "Output raw JSON envelope").action(async (taskId, opts) => {
34258
+ const client = makeClient(opts);
34259
+ const body = { creatorOlamNodeId: opts.creatorNodeId, claimToken: opts.claimToken };
34260
+ const { status: status2, envelope } = await client.call("POST", `/api/tasks/${taskId}/heartbeat`, ["tasks-state-update"], body);
34261
+ output(envelope, status2, !!opts.json);
34262
+ });
34263
+ tasks.command("done <task-id>").description("Complete a claimed task (POST /api/tasks/:id/complete)").requiredOption("--creator-node-id <uuid>", "Task creator olam node ID").requiredOption("--claim-token <token>", "Claim token from `olam tasks claim`").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--json", "Output raw JSON envelope").action(async (taskId, opts) => {
34264
+ const client = makeClient(opts);
34265
+ const body = { creatorOlamNodeId: opts.creatorNodeId, claimToken: opts.claimToken };
34266
+ const { status: status2, envelope } = await client.call("POST", `/api/tasks/${taskId}/complete`, ["tasks-state-update"], body);
34267
+ output(envelope, status2, !!opts.json);
34268
+ });
34269
+ tasks.command("update <task-id>").description("Update task fields (POST /api/tasks/:id/update)").requiredOption("--creator-node-id <uuid>", "Task creator olam node ID").option("--priority <n>", "New priority 0-10", (v) => parseInt(v, 10)).option("--feature <slug>", "New feature slug").option("--phase <letter>", "New phase letter").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--json", "Output raw JSON envelope").action(async (taskId, opts) => {
34270
+ const client = makeClient(opts);
34271
+ const body = { creatorOlamNodeId: opts.creatorNodeId };
34272
+ if (opts.priority !== void 0)
34273
+ body.priority = opts.priority;
34274
+ if (opts.feature)
34275
+ body.feature = opts.feature;
34276
+ if (opts.phase)
34277
+ body.phase = opts.phase;
34278
+ const { status: status2, envelope } = await client.call("POST", `/api/tasks/${taskId}/update`, ["tasks-state-update"], body);
34279
+ output(envelope, status2, !!opts.json);
34280
+ });
34281
+ tasks.command("pickup").description("B2.5 execute-workflow convenience: claim next + emit parseable claim-token + creator-node-id for downstream heartbeat/done").option("--feature <slug>", "Filter to a specific feature").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--json", "Output raw JSON envelope").action(async (opts) => {
34282
+ const client = makeClient(opts);
34283
+ const body = opts.feature ? { filter: { feature: opts.feature } } : {};
34284
+ const { status: status2, envelope } = await client.call("POST", "/api/tasks/claim", ["tasks-claim"], body);
34285
+ if (status2 !== 200 || !envelope.success || !envelope.data) {
34286
+ output(envelope, status2, !!opts.json);
34287
+ return;
34288
+ }
34289
+ const task = envelope.data;
34290
+ if (opts.json) {
34291
+ process.stdout.write(JSON.stringify({ status: status2, envelope, exports: { OLAM_TASK_ID: task.id, OLAM_TASK_CREATOR: task.creatorOlamNodeId } }, null, 2) + "\n");
34292
+ } else {
34293
+ process.stdout.write(`# olam tasks pickup: claimed ${task.id}
34294
+ `);
34295
+ process.stdout.write(`export OLAM_TASK_ID="${task.id}"
34296
+ `);
34297
+ process.stdout.write(`export OLAM_TASK_CREATOR="${task.creatorOlamNodeId}"
34298
+ `);
34299
+ process.stdout.write(`# eval "$(olam tasks pickup --feature B2)" # exports vars; downstream uses them for heartbeat / done
34300
+ `);
34301
+ }
34302
+ });
34303
+ tasks.command("sync-tracker <path>").description("Parse /10x:commit-plan tracker.md + upsert each task via POST /api/tasks (B2.4; dual-emit pattern, olam-side per cross-ownership decoupling)").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--dry-run", "Parse + print task records; do not POST").option("--json", "Output raw JSON envelope").action(async (path91, opts) => {
34304
+ const parsed = parseTracker(path91);
34305
+ if (opts.dryRun) {
34306
+ process.stdout.write(JSON.stringify(parsed, null, 2) + "\n");
34307
+ return;
34308
+ }
34309
+ const client = makeClient(opts);
34310
+ const results = [];
34311
+ for (const task of parsed.tasks) {
34312
+ const body = {
34313
+ title: task.title,
34314
+ feature: task.feature ?? void 0,
34315
+ phase: task.phase ?? void 0
34316
+ };
34317
+ const { status: status2, envelope } = await client.call("POST", "/api/tasks", ["tasks-create"], body);
34318
+ results.push({ rawId: task.rawId, taskId: task.taskId, status: status2, success: envelope.success, error: envelope.error });
34319
+ }
34320
+ output({ total: parsed.tasks.length, results }, 200, !!opts.json);
34321
+ });
34322
+ tasks.command("distill").description("Cross-cutting distillation query (GET /api/tasks/distill) \u2014 B2.7 scope").option("--query <name>", "Query name (per-phase-complexity-drift | contested-tasks | prior-art-pull)").option("--corpus <type>", "local | team", "local").option("--keyword <str>", "Keyword for prior-art-pull").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--json", "Output raw JSON envelope").action(async (opts) => {
34323
+ const client = makeClient(opts);
34324
+ const query = { query: opts.query, corpus: opts.corpus, keyword: opts.keyword };
34325
+ const scopes = opts.corpus === "team" ? ["tasks-query"] : ["tasks-query"];
34326
+ const { status: status2, envelope } = await client.call("GET", "/api/tasks/distill", scopes, void 0, query);
34327
+ output(envelope, status2, !!opts.json);
34328
+ });
34329
+ }
34330
+
33974
34331
  // src/lib/completion-generator.ts
33975
34332
  var UnsupportedShellError = class extends Error {
33976
34333
  constructor(shell) {
@@ -34081,8 +34438,8 @@ function registerCompletion(program2) {
34081
34438
  ).argument("<shell>", "zsh | bash").action((shell) => {
34082
34439
  const tree = program2.parent ?? program2;
34083
34440
  try {
34084
- const output = generateCompletion(tree, shell);
34085
- process.stdout.write(output);
34441
+ const output2 = generateCompletion(tree, shell);
34442
+ process.stdout.write(output2);
34086
34443
  } catch (err) {
34087
34444
  if (err instanceof UnsupportedShellError) {
34088
34445
  process.stderr.write(`${err.message}
@@ -34100,19 +34457,19 @@ init_cli_version();
34100
34457
  init_health_probes();
34101
34458
  import { spawn as spawn7 } from "node:child_process";
34102
34459
  import { existsSync as existsSync80 } from "node:fs";
34103
- import { homedir as homedir41 } from "node:os";
34460
+ import { homedir as homedir42 } from "node:os";
34104
34461
  import path72 from "node:path";
34105
34462
  import { createInterface as createInterface3 } from "node:readline";
34106
34463
 
34107
34464
  // src/lib/shell-rc.ts
34108
- import { copyFileSync as copyFileSync5, existsSync as existsSync59, readFileSync as readFileSync45, renameSync as renameSync8, writeFileSync as writeFileSync28 } from "node:fs";
34465
+ import { copyFileSync as copyFileSync5, existsSync as existsSync59, readFileSync as readFileSync47, renameSync as renameSync8, writeFileSync as writeFileSync28 } from "node:fs";
34109
34466
  import path52 from "node:path";
34110
34467
  function appendIdempotent(opts) {
34111
34468
  const { rcPath, marker, contentLine, clock = () => /* @__PURE__ */ new Date() } = opts;
34112
34469
  if (!existsSync59(rcPath)) {
34113
34470
  return { status: "no-rc-file", backupPath: null };
34114
34471
  }
34115
- const content = readFileSync45(rcPath, "utf-8");
34472
+ const content = readFileSync47(rcPath, "utf-8");
34116
34473
  if (content.includes(marker)) {
34117
34474
  return { status: "already-present", backupPath: null };
34118
34475
  }
@@ -34290,7 +34647,7 @@ async function pickSkillSourcePhase(opts, deps) {
34290
34647
  }
34291
34648
 
34292
34649
  // src/commands/setup-phase-5b-project-sweep.ts
34293
- import { homedir as homedir40 } from "node:os";
34650
+ import { homedir as homedir41 } from "node:os";
34294
34651
  import * as path71 from "node:path";
34295
34652
  import * as fs71 from "node:fs";
34296
34653
  async function loadWalkFn() {
@@ -34323,7 +34680,7 @@ async function runProjectSweepPhase(opts, deps, sweepDeps = {}) {
34323
34680
  if (opts.skipProjectSweep) {
34324
34681
  return { ok: true, skipped: true, message: "skipped via --skip-project-sweep" };
34325
34682
  }
34326
- const home = deps.home ?? homedir40();
34683
+ const home = deps.home ?? homedir41();
34327
34684
  const projectsRoot = opts.projects ?? path71.join(home, "Projects");
34328
34685
  const existsSyncFn = sweepDeps.existsSync ?? fs71.existsSync;
34329
34686
  if (!existsSyncFn(projectsRoot)) {
@@ -34522,7 +34879,7 @@ async function phase4ShellInit(opts, deps) {
34522
34879
  if (opts.skipShellInit) {
34523
34880
  return { ok: true, skipped: true, message: "skipped via --skip-shell-init" };
34524
34881
  }
34525
- const home = deps.home ?? homedir41();
34882
+ const home = deps.home ?? homedir42();
34526
34883
  const shellEnv = deps.shellEnv ?? process.env.SHELL;
34527
34884
  const rcPath = resolveShellRc(home, shellEnv);
34528
34885
  if (rcPath === null) {
@@ -37546,9 +37903,9 @@ function registerMcpServe(cmd) {
37546
37903
  init_output();
37547
37904
 
37548
37905
  // src/commands/mcp/install-shared.ts
37549
- import { spawnSync as spawnSync25 } from "node:child_process";
37906
+ import { spawnSync as spawnSync26 } from "node:child_process";
37550
37907
  var DEFAULT_CLAUDE_SHELL_DEPS = {
37551
- spawn: spawnSync25,
37908
+ spawn: spawnSync26,
37552
37909
  log: (msg) => console.log(msg)
37553
37910
  };
37554
37911
  function isOnPath(deps, bin) {
@@ -38265,27 +38622,27 @@ function registerMcp(program2) {
38265
38622
  init_output();
38266
38623
 
38267
38624
  // src/lib/memory-host-process-migration.ts
38268
- import { existsSync as existsSync94, readFileSync as readFileSync71, unlinkSync as unlinkSync23 } from "node:fs";
38269
- import { spawnSync as spawnSync26 } from "node:child_process";
38625
+ import { existsSync as existsSync94, readFileSync as readFileSync73, unlinkSync as unlinkSync23 } from "node:fs";
38626
+ import { spawnSync as spawnSync27 } from "node:child_process";
38270
38627
 
38271
38628
  // src/commands/memory/_paths.ts
38272
- import { homedir as homedir46 } from "node:os";
38273
- import { join as join86, dirname as dirname53 } from "node:path";
38629
+ import { homedir as homedir47 } from "node:os";
38630
+ import { join as join87, dirname as dirname53 } from "node:path";
38274
38631
  import { fileURLToPath as fileURLToPath8 } from "node:url";
38275
- var OLAM_HOME3 = join86(homedir46(), ".olam");
38276
- var MEMORY_PID_PATH = join86(OLAM_HOME3, "memory.pid");
38277
- var MEMORY_LOG_PATH = join86(OLAM_HOME3, "memory-service.log");
38278
- var MEMORY_DATA_DIR = join86(OLAM_HOME3, "memory-data");
38632
+ var OLAM_HOME3 = join87(homedir47(), ".olam");
38633
+ var MEMORY_PID_PATH = join87(OLAM_HOME3, "memory.pid");
38634
+ var MEMORY_LOG_PATH = join87(OLAM_HOME3, "memory-service.log");
38635
+ var MEMORY_DATA_DIR = join87(OLAM_HOME3, "memory-data");
38279
38636
  var MEMORY_REST_PORT = 3111;
38280
38637
  var MEMORY_LIVEZ_URL = `http://localhost:${MEMORY_REST_PORT}/agentmemory/livez`;
38281
38638
  var here2 = dirname53(fileURLToPath8(import.meta.url));
38282
38639
  var candidates = [
38283
38640
  // 1. Workspace dev (built): packages/cli/dist/commands/memory/_paths.js → packages/cli → packages/memory-service
38284
- join86(here2, "..", "..", "..", "..", "memory-service"),
38641
+ join87(here2, "..", "..", "..", "..", "memory-service"),
38285
38642
  // 2. Workspace bundled: packages/cli/dist/index.js → packages/cli → packages/memory-service
38286
- join86(here2, "..", "..", "memory-service"),
38643
+ join87(here2, "..", "..", "memory-service"),
38287
38644
  // 3. CWD fallback
38288
- join86(process.cwd(), "packages", "memory-service")
38645
+ join87(process.cwd(), "packages", "memory-service")
38289
38646
  ];
38290
38647
  var MEMORY_SERVICE_CANDIDATES = candidates;
38291
38648
 
@@ -38334,7 +38691,7 @@ function migrateFromHostProcess(opts = {}) {
38334
38691
  }
38335
38692
  function readPidFromFile(pidPath2) {
38336
38693
  try {
38337
- const raw = readFileSync71(pidPath2, "utf8").trim();
38694
+ const raw = readFileSync73(pidPath2, "utf8").trim();
38338
38695
  const pid = parseInt(raw, 10);
38339
38696
  if (!Number.isFinite(pid) || pid <= 0) return null;
38340
38697
  return pid;
@@ -38351,7 +38708,7 @@ function isProcessAlive(pid) {
38351
38708
  }
38352
38709
  }
38353
38710
  function processCommName(pid) {
38354
- const r = spawnSync26("ps", ["-p", String(pid), "-o", "comm="], { encoding: "utf-8" });
38711
+ const r = spawnSync27("ps", ["-p", String(pid), "-o", "comm="], { encoding: "utf-8" });
38355
38712
  if (r.status !== 0) return null;
38356
38713
  const comm = r.stdout.trim();
38357
38714
  return comm.split("/").pop() ?? null;
@@ -38365,7 +38722,7 @@ function terminateProcess(pid) {
38365
38722
  const deadline = Date.now() + KILL_TIMEOUT_MS;
38366
38723
  while (Date.now() < deadline) {
38367
38724
  if (!isProcessAlive(pid)) return true;
38368
- spawnSync26("sleep", ["0.1"]);
38725
+ spawnSync27("sleep", ["0.1"]);
38369
38726
  }
38370
38727
  try {
38371
38728
  process.kill(pid, "SIGKILL");
@@ -38767,13 +39124,13 @@ function registerMemoryUninstall(cmd) {
38767
39124
  // src/commands/memory/mode.ts
38768
39125
  init_schema2();
38769
39126
  init_output();
38770
- import { existsSync as existsSync97, readFileSync as readFileSync72, writeFileSync as writeFileSync45 } from "node:fs";
38771
- import { join as join87 } from "node:path";
39127
+ import { existsSync as existsSync97, readFileSync as readFileSync74, writeFileSync as writeFileSync45 } from "node:fs";
39128
+ import { join as join88 } from "node:path";
38772
39129
  import * as readline6 from "node:readline/promises";
38773
39130
  import { parse as parseYaml7, stringify as stringifyYaml6 } from "yaml";
38774
39131
  var CONFIG_REL = ".olam/config.yaml";
38775
39132
  function locateConfig(cwd) {
38776
- const absPath = join87(cwd, CONFIG_REL);
39133
+ const absPath = join88(cwd, CONFIG_REL);
38777
39134
  if (!existsSync97(absPath)) {
38778
39135
  throw new Error(
38779
39136
  `No ${CONFIG_REL} at ${cwd}. Run \`olam init\` in your workspace root first.`
@@ -38782,7 +39139,7 @@ function locateConfig(cwd) {
38782
39139
  return { absPath };
38783
39140
  }
38784
39141
  function readConfigYaml(absPath) {
38785
- const raw = readFileSync72(absPath, "utf-8");
39142
+ const raw = readFileSync74(absPath, "utf-8");
38786
39143
  const parsed = parseYaml7(raw) ?? {};
38787
39144
  if (typeof parsed !== "object" || parsed === null) {
38788
39145
  throw new Error(`${absPath} is not a YAML object`);
@@ -38911,7 +39268,7 @@ function registerMemoryMode(cmd) {
38911
39268
  init_output();
38912
39269
  import { spawn as spawn11 } from "node:child_process";
38913
39270
  import { existsSync as existsSync98 } from "node:fs";
38914
- import { join as join88 } from "node:path";
39271
+ import { join as join89 } from "node:path";
38915
39272
  var DEFAULT_PORT2 = 8788;
38916
39273
  function resolveMemoryServiceDir() {
38917
39274
  for (const c of MEMORY_SERVICE_CANDIDATES) {
@@ -38922,7 +39279,7 @@ function resolveMemoryServiceDir() {
38922
39279
  );
38923
39280
  }
38924
39281
  function resolveLocalBridgeScript(serviceDir) {
38925
- const path91 = join88(serviceDir, "scripts", "local-bridge-server.mjs");
39282
+ const path91 = join89(serviceDir, "scripts", "local-bridge-server.mjs");
38926
39283
  if (!existsSync98(path91)) {
38927
39284
  throw new Error(
38928
39285
  `Could not find local-bridge-server.mjs at ${path91}. Verify packages/memory-service ships the scripts/ directory.`
@@ -39384,10 +39741,10 @@ init_workspace_name();
39384
39741
  init_kg_caps();
39385
39742
  init_output();
39386
39743
  import fs85 from "node:fs";
39387
- import { homedir as homedir47 } from "node:os";
39744
+ import { homedir as homedir48 } from "node:os";
39388
39745
  import path84 from "node:path";
39389
39746
  function olamHome4() {
39390
- return process.env.OLAM_HOME ?? path84.join(homedir47(), ".olam");
39747
+ return process.env.OLAM_HOME ?? path84.join(homedir48(), ".olam");
39391
39748
  }
39392
39749
  function kgRoot2() {
39393
39750
  return path84.join(olamHome4(), "kg");
@@ -40497,16 +40854,16 @@ function registerKg(program2) {
40497
40854
  // src/commands/flywheel/emit-breadcrumb.ts
40498
40855
  init_file_lock();
40499
40856
  import { mkdirSync as mkdirSync57, appendFileSync as appendFileSync6 } from "node:fs";
40500
- import { homedir as homedir51 } from "node:os";
40501
- import { dirname as dirname56, join as join92 } from "node:path";
40502
- import { randomUUID as randomUUID2 } from "node:crypto";
40857
+ import { homedir as homedir52 } from "node:os";
40858
+ import { dirname as dirname56, join as join93 } from "node:path";
40859
+ import { randomUUID as randomUUID3 } from "node:crypto";
40503
40860
  var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info", "warn"]);
40504
40861
  var PROMPT_FEEDING_FIELDS = ["extracted_pattern", "severity", "affected_persona", "proposed_edit"];
40505
- var BREADCRUMBS_BASE = join92(homedir51(), ".local", "share", "claude", "breadcrumbs");
40862
+ var BREADCRUMBS_BASE = join93(homedir52(), ".local", "share", "claude", "breadcrumbs");
40506
40863
  var LOCK_FILENAME = ".flywheel-emit.lock";
40507
40864
  function buildRecord(opts) {
40508
40865
  const rec = {
40509
- breadcrumb_id: randomUUID2().replace(/-/g, ""),
40866
+ breadcrumb_id: randomUUID3().replace(/-/g, ""),
40510
40867
  emitted_at: (/* @__PURE__ */ new Date()).toISOString(),
40511
40868
  emitted_by_skill: opts.skill,
40512
40869
  pass_number: opts.pass !== void 0 ? Number.parseInt(opts.pass, 10) : 0,
@@ -40549,7 +40906,7 @@ function validatePromptFeeding(rec) {
40549
40906
  }
40550
40907
  function destPath(projectSlug) {
40551
40908
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
40552
- return join92(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
40909
+ return join93(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
40553
40910
  }
40554
40911
  async function emitBreadcrumb(opts) {
40555
40912
  if (!VALID_SEVERITIES.has(opts.severity)) {
@@ -40650,7 +41007,7 @@ function registerFlywheelK5Score(parent) {
40650
41007
  }
40651
41008
 
40652
41009
  // src/commands/flywheel/k5-validate.ts
40653
- import { readFileSync as readFileSync76, statSync as statSync24 } from "node:fs";
41010
+ import { readFileSync as readFileSync78, statSync as statSync24 } from "node:fs";
40654
41011
  import { parse as parseYAML } from "yaml";
40655
41012
  var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
40656
41013
  var MAX_PLAN_BYTES = 1048576;
@@ -40720,7 +41077,7 @@ function validatePlan(path91) {
40720
41077
  }
40721
41078
  let text;
40722
41079
  try {
40723
- text = readFileSync76(path91, "utf8");
41080
+ text = readFileSync78(path91, "utf8");
40724
41081
  } catch (err) {
40725
41082
  return { ok: false, message: `FAIL cannot read ${path91}: ${err instanceof Error ? err.message : "unknown"}` };
40726
41083
  }
@@ -40845,8 +41202,8 @@ function registerFlywheelDiversityCheck(parent) {
40845
41202
 
40846
41203
  // src/commands/flywheel/ping.ts
40847
41204
  import { mkdirSync as mkdirSync58, writeFileSync as writeFileSync49 } from "node:fs";
40848
- import { homedir as homedir52 } from "node:os";
40849
- import { dirname as dirname57, join as join93 } from "node:path";
41205
+ import { homedir as homedir53 } from "node:os";
41206
+ import { dirname as dirname57, join as join94 } from "node:path";
40850
41207
  var COLD_START_BUDGET_GOOD_MS = 200;
40851
41208
  var COLD_START_BUDGET_FAIR_MS = 500;
40852
41209
  function classifyColdStart(coldStartMs) {
@@ -40862,7 +41219,7 @@ function readOlamVersion() {
40862
41219
  }
40863
41220
  }
40864
41221
  function writeBaseline(record) {
40865
- const baselinePath = join93(homedir52(), ".local", "share", "olam", "flywheel-baseline.json");
41222
+ const baselinePath = join94(homedir53(), ".local", "share", "olam", "flywheel-baseline.json");
40866
41223
  mkdirSync58(dirname57(baselinePath), { recursive: true });
40867
41224
  writeFileSync49(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
40868
41225
  return baselinePath;
@@ -40926,7 +41283,7 @@ function registerFlywheel(program2) {
40926
41283
 
40927
41284
  // src/commands/seed.ts
40928
41285
  init_output();
40929
- import { spawnSync as spawnSync27, spawn as spawnAsync2 } from "node:child_process";
41286
+ import { spawnSync as spawnSync28, spawn as spawnAsync2 } from "node:child_process";
40930
41287
  var DEFAULT_SINGLETON_CONTAINER = "olam-postgres";
40931
41288
  var DEFAULT_SINGLETON_USER = "development";
40932
41289
  function assertValidSeedName(name) {
@@ -40937,7 +41294,7 @@ function assertValidSeedName(name) {
40937
41294
  }
40938
41295
  }
40939
41296
  function singletonDocker(container, user, args, stdin) {
40940
- return spawnSync27(
41297
+ return spawnSync28(
40941
41298
  "docker",
40942
41299
  ["exec", "-i", container, "psql", "-U", user, ...args],
40943
41300
  { encoding: "utf-8", input: stdin }
@@ -40992,7 +41349,7 @@ async function handleBake(opts) {
40992
41349
  if (sources.length > 1) {
40993
41350
  throw new Error("multiple sources specified \u2014 pass exactly one of --source-container, --source-url, --source-local");
40994
41351
  }
40995
- const ping = spawnSync27("docker", ["inspect", "--format", "{{.State.Status}}", singleton], { encoding: "utf-8" });
41352
+ const ping = spawnSync28("docker", ["inspect", "--format", "{{.State.Status}}", singleton], { encoding: "utf-8" });
40996
41353
  if (ping.status !== 0 || (ping.stdout || "").trim() !== "running") {
40997
41354
  throw new Error(`singleton container "${singleton}" not running \u2014 run \`olam bootstrap\` first`);
40998
41355
  }
@@ -41381,6 +41738,8 @@ registerBootstrap(program);
41381
41738
  registerDiagnose(program);
41382
41739
  registerDoctor(program);
41383
41740
  registerSubstrate(program);
41741
+ registerTasks(program);
41742
+ registerWorkers(program);
41384
41743
  registerCompletion(program);
41385
41744
  registerSetup(program);
41386
41745
  registerSetupMetrics(program);