@pleri/olam-cli 0.1.201 → 0.1.205
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/README.md +102 -169
- package/dist/agent-stream/agent-sdk-to-chunks.js +1 -1
- package/dist/agent-stream/driver-runner.js +73 -7
- package/dist/agent-stream/host-driver-launch.js +14 -1
- package/dist/agent-stream/prototype-gen-launch.js +113 -0
- package/dist/agent-stream/question-broker-bridge.js +335 -0
- package/dist/agent-stream/sdk-env-merge.demo.js +35 -0
- package/dist/agent-stream/sdk-env-merge.js +98 -0
- package/dist/image-digests.json +8 -8
- package/dist/index.js +9533 -6258
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.js +24721 -12934
- package/hermes-bundle/version.json +1 -1
- package/hooks/__tests__/_loader.py +26 -0
- package/hooks/__tests__/prompts.py +63 -0
- package/hooks/__tests__/test_classify_bench.py +94 -0
- package/hooks/__tests__/test_classify_pins.py +78 -0
- package/hooks/model-router.py +17 -4
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/host-cp/src/op-side-longpoll.mjs +212 -0
- package/host-cp/src/plan-chat-proxy-headers.mjs +53 -0
- package/host-cp/src/plan-chat-service.mjs +100 -0
- package/host-cp/src/plan-orchestrator.mjs +100 -6
- package/host-cp/src/server.mjs +607 -45
- package/memory-hooks/agentmemory-classify-queue.mjs +363 -0
- package/memory-hooks/agentmemory-recall-trigger.mjs +233 -0
- package/memory-hooks/agentmemory-reflect-cite.mjs +332 -0
- package/memory-hooks/agentmemory-session-recall.js +332 -0
- package/memory-hooks/recall-log.mjs +185 -0
- package/package.json +9 -4
- package/dist/ask/checkout.d.ts +0 -19
- package/dist/ask/checkout.d.ts.map +0 -1
- package/dist/ask/checkout.js +0 -40
- package/dist/ask/checkout.js.map +0 -1
- package/dist/ask/knowledge-pack-builder.d.ts +0 -72
- package/dist/ask/knowledge-pack-builder.d.ts.map +0 -1
- package/dist/ask/knowledge-pack-builder.js +0 -96
- package/dist/ask/knowledge-pack-builder.js.map +0 -1
- package/dist/ask/knowledge-pack.generated.d.ts +0 -8
- package/dist/ask/knowledge-pack.generated.d.ts.map +0 -1
- package/dist/ask/knowledge-pack.generated.js +0 -2362
- package/dist/ask/knowledge-pack.generated.js.map +0 -1
- package/dist/ask/one-shot.d.ts +0 -21
- package/dist/ask/one-shot.d.ts.map +0 -1
- package/dist/ask/one-shot.js +0 -50
- package/dist/ask/one-shot.js.map +0 -1
- package/dist/ask/repl.d.ts +0 -30
- package/dist/ask/repl.d.ts.map +0 -1
- package/dist/ask/repl.js +0 -109
- package/dist/ask/repl.js.map +0 -1
- package/dist/ask/sdk-client.d.ts +0 -87
- package/dist/ask/sdk-client.d.ts.map +0 -1
- package/dist/ask/sdk-client.js +0 -118
- package/dist/ask/sdk-client.js.map +0 -1
- package/dist/ask/system-prompt.d.ts +0 -30
- package/dist/ask/system-prompt.d.ts.map +0 -1
- package/dist/ask/system-prompt.js +0 -31
- package/dist/ask/system-prompt.js.map +0 -1
- package/dist/cli-version.d.ts +0 -16
- package/dist/cli-version.d.ts.map +0 -1
- package/dist/cli-version.js +0 -39
- package/dist/cli-version.js.map +0 -1
- package/dist/commands/ask.d.ts +0 -27
- package/dist/commands/ask.d.ts.map +0 -1
- package/dist/commands/ask.js +0 -63
- package/dist/commands/ask.js.map +0 -1
- package/dist/commands/auth-list-json.d.ts +0 -87
- package/dist/commands/auth-list-json.d.ts.map +0 -1
- package/dist/commands/auth-list-json.js +0 -71
- package/dist/commands/auth-list-json.js.map +0 -1
- package/dist/commands/auth-migrate.d.ts +0 -212
- package/dist/commands/auth-migrate.d.ts.map +0 -1
- package/dist/commands/auth-migrate.js +0 -465
- package/dist/commands/auth-migrate.js.map +0 -1
- package/dist/commands/auth-status.d.ts +0 -51
- package/dist/commands/auth-status.d.ts.map +0 -1
- package/dist/commands/auth-status.js +0 -250
- package/dist/commands/auth-status.js.map +0 -1
- package/dist/commands/auth-upgrade.d.ts +0 -88
- package/dist/commands/auth-upgrade.d.ts.map +0 -1
- package/dist/commands/auth-upgrade.js +0 -431
- package/dist/commands/auth-upgrade.js.map +0 -1
- package/dist/commands/auth.d.ts +0 -31
- package/dist/commands/auth.d.ts.map +0 -1
- package/dist/commands/auth.js +0 -784
- package/dist/commands/auth.js.map +0 -1
- package/dist/commands/begin.d.ts +0 -27
- package/dist/commands/begin.d.ts.map +0 -1
- package/dist/commands/begin.js +0 -45
- package/dist/commands/begin.js.map +0 -1
- package/dist/commands/bootstrap.d.ts +0 -111
- package/dist/commands/bootstrap.d.ts.map +0 -1
- package/dist/commands/bootstrap.js +0 -485
- package/dist/commands/bootstrap.js.map +0 -1
- package/dist/commands/clean.d.ts +0 -41
- package/dist/commands/clean.d.ts.map +0 -1
- package/dist/commands/clean.js +0 -382
- package/dist/commands/clean.js.map +0 -1
- package/dist/commands/completion.d.ts +0 -30
- package/dist/commands/completion.d.ts.map +0 -1
- package/dist/commands/completion.js +0 -50
- package/dist/commands/completion.js.map +0 -1
- package/dist/commands/config.d.ts +0 -3
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js +0 -146
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/create.d.ts +0 -8
- package/dist/commands/create.d.ts.map +0 -1
- package/dist/commands/create.js +0 -775
- package/dist/commands/create.js.map +0 -1
- package/dist/commands/crystallize.d.ts +0 -18
- package/dist/commands/crystallize.d.ts.map +0 -1
- package/dist/commands/crystallize.js +0 -123
- package/dist/commands/crystallize.js.map +0 -1
- package/dist/commands/destroy.d.ts +0 -59
- package/dist/commands/destroy.d.ts.map +0 -1
- package/dist/commands/destroy.js +0 -148
- package/dist/commands/destroy.js.map +0 -1
- package/dist/commands/diagnose.d.ts +0 -36
- package/dist/commands/diagnose.d.ts.map +0 -1
- package/dist/commands/diagnose.js +0 -177
- package/dist/commands/diagnose.js.map +0 -1
- package/dist/commands/dispatch-resolve.d.ts +0 -54
- package/dist/commands/dispatch-resolve.d.ts.map +0 -1
- package/dist/commands/dispatch-resolve.js +0 -105
- package/dist/commands/dispatch-resolve.js.map +0 -1
- package/dist/commands/dispatch.d.ts +0 -18
- package/dist/commands/dispatch.d.ts.map +0 -1
- package/dist/commands/dispatch.js +0 -159
- package/dist/commands/dispatch.js.map +0 -1
- package/dist/commands/doctor.d.ts +0 -258
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js +0 -1073
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/enter.d.ts +0 -63
- package/dist/commands/enter.d.ts.map +0 -1
- package/dist/commands/enter.js +0 -230
- package/dist/commands/enter.js.map +0 -1
- package/dist/commands/flywheel/check-persona-skeleton.d.ts +0 -35
- package/dist/commands/flywheel/check-persona-skeleton.d.ts.map +0 -1
- package/dist/commands/flywheel/check-persona-skeleton.js +0 -151
- package/dist/commands/flywheel/check-persona-skeleton.js.map +0 -1
- package/dist/commands/flywheel/diversity-check.d.ts +0 -17
- package/dist/commands/flywheel/diversity-check.d.ts.map +0 -1
- package/dist/commands/flywheel/diversity-check.js +0 -64
- package/dist/commands/flywheel/diversity-check.js.map +0 -1
- package/dist/commands/flywheel/emit-breadcrumb.d.ts +0 -20
- package/dist/commands/flywheel/emit-breadcrumb.d.ts.map +0 -1
- package/dist/commands/flywheel/emit-breadcrumb.js +0 -137
- package/dist/commands/flywheel/emit-breadcrumb.js.map +0 -1
- package/dist/commands/flywheel/index.d.ts +0 -27
- package/dist/commands/flywheel/index.d.ts.map +0 -1
- package/dist/commands/flywheel/index.js +0 -54
- package/dist/commands/flywheel/index.js.map +0 -1
- package/dist/commands/flywheel/install-sessionstart-hook.d.ts +0 -64
- package/dist/commands/flywheel/install-sessionstart-hook.d.ts.map +0 -1
- package/dist/commands/flywheel/install-sessionstart-hook.js +0 -197
- package/dist/commands/flywheel/install-sessionstart-hook.js.map +0 -1
- package/dist/commands/flywheel/install-shims.d.ts +0 -41
- package/dist/commands/flywheel/install-shims.d.ts.map +0 -1
- package/dist/commands/flywheel/install-shims.js +0 -126
- package/dist/commands/flywheel/install-shims.js.map +0 -1
- package/dist/commands/flywheel/k10-measure.d.ts +0 -17
- package/dist/commands/flywheel/k10-measure.d.ts.map +0 -1
- package/dist/commands/flywheel/k10-measure.js +0 -63
- package/dist/commands/flywheel/k10-measure.js.map +0 -1
- package/dist/commands/flywheel/k5-score.d.ts +0 -14
- package/dist/commands/flywheel/k5-score.d.ts.map +0 -1
- package/dist/commands/flywheel/k5-score.js +0 -59
- package/dist/commands/flywheel/k5-score.js.map +0 -1
- package/dist/commands/flywheel/k5-validate.d.ts +0 -46
- package/dist/commands/flywheel/k5-validate.d.ts.map +0 -1
- package/dist/commands/flywheel/k5-validate.js +0 -246
- package/dist/commands/flywheel/k5-validate.js.map +0 -1
- package/dist/commands/flywheel/migrate-overlays.d.ts +0 -116
- package/dist/commands/flywheel/migrate-overlays.d.ts.map +0 -1
- package/dist/commands/flywheel/migrate-overlays.js +0 -792
- package/dist/commands/flywheel/migrate-overlays.js.map +0 -1
- package/dist/commands/flywheel/ping.d.ts +0 -21
- package/dist/commands/flywheel/ping.d.ts.map +0 -1
- package/dist/commands/flywheel/ping.js +0 -79
- package/dist/commands/flywheel/ping.js.map +0 -1
- package/dist/commands/flywheel/sanitize-persona-output.d.ts +0 -38
- package/dist/commands/flywheel/sanitize-persona-output.d.ts.map +0 -1
- package/dist/commands/flywheel/sanitize-persona-output.js +0 -102
- package/dist/commands/flywheel/sanitize-persona-output.js.map +0 -1
- package/dist/commands/flywheel/session-start.d.ts +0 -26
- package/dist/commands/flywheel/session-start.d.ts.map +0 -1
- package/dist/commands/flywheel/session-start.js +0 -119
- package/dist/commands/flywheel/session-start.js.map +0 -1
- package/dist/commands/hermes-kg-hook.d.ts +0 -36
- package/dist/commands/hermes-kg-hook.d.ts.map +0 -1
- package/dist/commands/hermes-kg-hook.js +0 -80
- package/dist/commands/hermes-kg-hook.js.map +0 -1
- package/dist/commands/hermes.d.ts +0 -46
- package/dist/commands/hermes.d.ts.map +0 -1
- package/dist/commands/hermes.js +0 -320
- package/dist/commands/hermes.js.map +0 -1
- package/dist/commands/host-cp.d.ts +0 -216
- package/dist/commands/host-cp.d.ts.map +0 -1
- package/dist/commands/host-cp.js +0 -913
- package/dist/commands/host-cp.js.map +0 -1
- package/dist/commands/implode.d.ts +0 -86
- package/dist/commands/implode.d.ts.map +0 -1
- package/dist/commands/implode.js +0 -468
- package/dist/commands/implode.js.map +0 -1
- package/dist/commands/init.d.ts +0 -86
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -357
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/install.d.ts +0 -22
- package/dist/commands/install.d.ts.map +0 -1
- package/dist/commands/install.js +0 -203
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/keys-list-json.d.ts +0 -55
- package/dist/commands/keys-list-json.d.ts.map +0 -1
- package/dist/commands/keys-list-json.js +0 -54
- package/dist/commands/keys-list-json.js.map +0 -1
- package/dist/commands/keys.d.ts +0 -26
- package/dist/commands/keys.d.ts.map +0 -1
- package/dist/commands/keys.js +0 -157
- package/dist/commands/keys.js.map +0 -1
- package/dist/commands/kg-build.d.ts +0 -80
- package/dist/commands/kg-build.d.ts.map +0 -1
- package/dist/commands/kg-build.js +0 -282
- package/dist/commands/kg-build.js.map +0 -1
- package/dist/commands/kg-classify.d.ts +0 -30
- package/dist/commands/kg-classify.d.ts.map +0 -1
- package/dist/commands/kg-classify.js +0 -88
- package/dist/commands/kg-classify.js.map +0 -1
- package/dist/commands/kg-doctor.d.ts +0 -76
- package/dist/commands/kg-doctor.d.ts.map +0 -1
- package/dist/commands/kg-doctor.js +0 -262
- package/dist/commands/kg-doctor.js.map +0 -1
- package/dist/commands/kg-install-hook.d.ts +0 -20
- package/dist/commands/kg-install-hook.d.ts.map +0 -1
- package/dist/commands/kg-install-hook.js +0 -208
- package/dist/commands/kg-install-hook.js.map +0 -1
- package/dist/commands/kg-mirror.d.ts +0 -72
- package/dist/commands/kg-mirror.d.ts.map +0 -1
- package/dist/commands/kg-mirror.js +0 -397
- package/dist/commands/kg-mirror.js.map +0 -1
- package/dist/commands/kg-savings.d.ts +0 -20
- package/dist/commands/kg-savings.d.ts.map +0 -1
- package/dist/commands/kg-savings.js +0 -77
- package/dist/commands/kg-savings.js.map +0 -1
- package/dist/commands/kg-service-container.d.ts +0 -68
- package/dist/commands/kg-service-container.d.ts.map +0 -1
- package/dist/commands/kg-service-container.js +0 -191
- package/dist/commands/kg-service-container.js.map +0 -1
- package/dist/commands/kg-status.d.ts +0 -59
- package/dist/commands/kg-status.d.ts.map +0 -1
- package/dist/commands/kg-status.js +0 -344
- package/dist/commands/kg-status.js.map +0 -1
- package/dist/commands/kg-uninstall-hook.d.ts +0 -12
- package/dist/commands/kg-uninstall-hook.d.ts.map +0 -1
- package/dist/commands/kg-uninstall-hook.js +0 -121
- package/dist/commands/kg-uninstall-hook.js.map +0 -1
- package/dist/commands/kg-watch.d.ts +0 -49
- package/dist/commands/kg-watch.d.ts.map +0 -1
- package/dist/commands/kg-watch.js +0 -172
- package/dist/commands/kg-watch.js.map +0 -1
- package/dist/commands/lanes-list-json.d.ts +0 -69
- package/dist/commands/lanes-list-json.d.ts.map +0 -1
- package/dist/commands/lanes-list-json.js +0 -42
- package/dist/commands/lanes-list-json.js.map +0 -1
- package/dist/commands/lanes.d.ts +0 -18
- package/dist/commands/lanes.d.ts.map +0 -1
- package/dist/commands/lanes.js +0 -133
- package/dist/commands/lanes.js.map +0 -1
- package/dist/commands/list.d.ts +0 -33
- package/dist/commands/list.d.ts.map +0 -1
- package/dist/commands/list.js +0 -87
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/logs.d.ts +0 -52
- package/dist/commands/logs.d.ts.map +0 -1
- package/dist/commands/logs.js +0 -180
- package/dist/commands/logs.js.map +0 -1
- package/dist/commands/mcp/add.d.ts +0 -9
- package/dist/commands/mcp/add.d.ts.map +0 -1
- package/dist/commands/mcp/add.js +0 -87
- package/dist/commands/mcp/add.js.map +0 -1
- package/dist/commands/mcp/client.d.ts +0 -60
- package/dist/commands/mcp/client.d.ts.map +0 -1
- package/dist/commands/mcp/client.js +0 -70
- package/dist/commands/mcp/client.js.map +0 -1
- package/dist/commands/mcp/complete.d.ts +0 -36
- package/dist/commands/mcp/complete.d.ts.map +0 -1
- package/dist/commands/mcp/complete.js +0 -66
- package/dist/commands/mcp/complete.js.map +0 -1
- package/dist/commands/mcp/import-discovery.d.ts +0 -25
- package/dist/commands/mcp/import-discovery.d.ts.map +0 -1
- package/dist/commands/mcp/import-discovery.js +0 -135
- package/dist/commands/mcp/import-discovery.js.map +0 -1
- package/dist/commands/mcp/import-validate.d.ts +0 -15
- package/dist/commands/mcp/import-validate.d.ts.map +0 -1
- package/dist/commands/mcp/import-validate.js +0 -55
- package/dist/commands/mcp/import-validate.js.map +0 -1
- package/dist/commands/mcp/import.d.ts +0 -12
- package/dist/commands/mcp/import.d.ts.map +0 -1
- package/dist/commands/mcp/import.js +0 -126
- package/dist/commands/mcp/import.js.map +0 -1
- package/dist/commands/mcp/index.d.ts +0 -14
- package/dist/commands/mcp/index.d.ts.map +0 -1
- package/dist/commands/mcp/index.js +0 -39
- package/dist/commands/mcp/index.js.map +0 -1
- package/dist/commands/mcp/install-shared.d.ts +0 -24
- package/dist/commands/mcp/install-shared.d.ts.map +0 -1
- package/dist/commands/mcp/install-shared.js +0 -42
- package/dist/commands/mcp/install-shared.js.map +0 -1
- package/dist/commands/mcp/install.d.ts +0 -20
- package/dist/commands/mcp/install.d.ts.map +0 -1
- package/dist/commands/mcp/install.js +0 -59
- package/dist/commands/mcp/install.js.map +0 -1
- package/dist/commands/mcp/list.d.ts +0 -6
- package/dist/commands/mcp/list.d.ts.map +0 -1
- package/dist/commands/mcp/list.js +0 -56
- package/dist/commands/mcp/list.js.map +0 -1
- package/dist/commands/mcp/login.d.ts +0 -6
- package/dist/commands/mcp/login.d.ts.map +0 -1
- package/dist/commands/mcp/login.js +0 -38
- package/dist/commands/mcp/login.js.map +0 -1
- package/dist/commands/mcp/remove.d.ts +0 -6
- package/dist/commands/mcp/remove.d.ts.map +0 -1
- package/dist/commands/mcp/remove.js +0 -21
- package/dist/commands/mcp/remove.js.map +0 -1
- package/dist/commands/mcp/revoke.d.ts +0 -11
- package/dist/commands/mcp/revoke.d.ts.map +0 -1
- package/dist/commands/mcp/revoke.js +0 -51
- package/dist/commands/mcp/revoke.js.map +0 -1
- package/dist/commands/mcp/serve.d.ts +0 -23
- package/dist/commands/mcp/serve.d.ts.map +0 -1
- package/dist/commands/mcp/serve.js +0 -55
- package/dist/commands/mcp/serve.js.map +0 -1
- package/dist/commands/mcp/status.d.ts +0 -6
- package/dist/commands/mcp/status.d.ts.map +0 -1
- package/dist/commands/mcp/status.js +0 -57
- package/dist/commands/mcp/status.js.map +0 -1
- package/dist/commands/mcp/uninstall.d.ts +0 -20
- package/dist/commands/mcp/uninstall.d.ts.map +0 -1
- package/dist/commands/mcp/uninstall.js +0 -60
- package/dist/commands/mcp/uninstall.js.map +0 -1
- package/dist/commands/memory/_paths.d.ts +0 -25
- package/dist/commands/memory/_paths.d.ts.map +0 -1
- package/dist/commands/memory/_paths.js +0 -57
- package/dist/commands/memory/_paths.js.map +0 -1
- package/dist/commands/memory/bridge.d.ts +0 -57
- package/dist/commands/memory/bridge.d.ts.map +0 -1
- package/dist/commands/memory/bridge.js +0 -152
- package/dist/commands/memory/bridge.js.map +0 -1
- package/dist/commands/memory/index.d.ts +0 -20
- package/dist/commands/memory/index.d.ts.map +0 -1
- package/dist/commands/memory/index.js +0 -47
- package/dist/commands/memory/index.js.map +0 -1
- package/dist/commands/memory/install-hooks.d.ts +0 -22
- package/dist/commands/memory/install-hooks.d.ts.map +0 -1
- package/dist/commands/memory/install-hooks.js +0 -156
- package/dist/commands/memory/install-hooks.js.map +0 -1
- package/dist/commands/memory/install.d.ts +0 -57
- package/dist/commands/memory/install.d.ts.map +0 -1
- package/dist/commands/memory/install.js +0 -114
- package/dist/commands/memory/install.js.map +0 -1
- package/dist/commands/memory/logs.d.ts +0 -19
- package/dist/commands/memory/logs.d.ts.map +0 -1
- package/dist/commands/memory/logs.js +0 -50
- package/dist/commands/memory/logs.js.map +0 -1
- package/dist/commands/memory/mode.d.ts +0 -47
- package/dist/commands/memory/mode.d.ts.map +0 -1
- package/dist/commands/memory/mode.js +0 -185
- package/dist/commands/memory/mode.js.map +0 -1
- package/dist/commands/memory/reclassify.d.ts +0 -56
- package/dist/commands/memory/reclassify.d.ts.map +0 -1
- package/dist/commands/memory/reclassify.js +0 -177
- package/dist/commands/memory/reclassify.js.map +0 -1
- package/dist/commands/memory/secret.d.ts +0 -16
- package/dist/commands/memory/secret.d.ts.map +0 -1
- package/dist/commands/memory/secret.js +0 -80
- package/dist/commands/memory/secret.js.map +0 -1
- package/dist/commands/memory/start.d.ts +0 -25
- package/dist/commands/memory/start.d.ts.map +0 -1
- package/dist/commands/memory/start.js +0 -83
- package/dist/commands/memory/start.js.map +0 -1
- package/dist/commands/memory/stats.d.ts +0 -69
- package/dist/commands/memory/stats.d.ts.map +0 -1
- package/dist/commands/memory/stats.js +0 -164
- package/dist/commands/memory/stats.js.map +0 -1
- package/dist/commands/memory/status.d.ts +0 -45
- package/dist/commands/memory/status.d.ts.map +0 -1
- package/dist/commands/memory/status.js +0 -134
- package/dist/commands/memory/status.js.map +0 -1
- package/dist/commands/memory/stop.d.ts +0 -13
- package/dist/commands/memory/stop.d.ts.map +0 -1
- package/dist/commands/memory/stop.js +0 -52
- package/dist/commands/memory/stop.js.map +0 -1
- package/dist/commands/memory/uninstall.d.ts +0 -19
- package/dist/commands/memory/uninstall.d.ts.map +0 -1
- package/dist/commands/memory/uninstall.js +0 -60
- package/dist/commands/memory/uninstall.js.map +0 -1
- package/dist/commands/memory-service-container.d.ts +0 -130
- package/dist/commands/memory-service-container.d.ts.map +0 -1
- package/dist/commands/memory-service-container.js +0 -251
- package/dist/commands/memory-service-container.js.map +0 -1
- package/dist/commands/observe.d.ts +0 -9
- package/dist/commands/observe.d.ts.map +0 -1
- package/dist/commands/observe.js +0 -42
- package/dist/commands/observe.js.map +0 -1
- package/dist/commands/plans-list-json.d.ts +0 -77
- package/dist/commands/plans-list-json.d.ts.map +0 -1
- package/dist/commands/plans-list-json.js +0 -61
- package/dist/commands/plans-list-json.js.map +0 -1
- package/dist/commands/plans.d.ts +0 -3
- package/dist/commands/plans.d.ts.map +0 -1
- package/dist/commands/plans.js +0 -221
- package/dist/commands/plans.js.map +0 -1
- package/dist/commands/policy-check.d.ts +0 -14
- package/dist/commands/policy-check.d.ts.map +0 -1
- package/dist/commands/policy-check.js +0 -76
- package/dist/commands/policy-check.js.map +0 -1
- package/dist/commands/pr.d.ts +0 -17
- package/dist/commands/pr.d.ts.map +0 -1
- package/dist/commands/pr.js +0 -148
- package/dist/commands/pr.js.map +0 -1
- package/dist/commands/ps.d.ts +0 -57
- package/dist/commands/ps.d.ts.map +0 -1
- package/dist/commands/ps.js +0 -202
- package/dist/commands/ps.js.map +0 -1
- package/dist/commands/refresh-helpers.d.ts +0 -25
- package/dist/commands/refresh-helpers.d.ts.map +0 -1
- package/dist/commands/refresh-helpers.js +0 -56
- package/dist/commands/refresh-helpers.js.map +0 -1
- package/dist/commands/refresh.d.ts +0 -23
- package/dist/commands/refresh.d.ts.map +0 -1
- package/dist/commands/refresh.js +0 -237
- package/dist/commands/refresh.js.map +0 -1
- package/dist/commands/rekey.d.ts +0 -84
- package/dist/commands/rekey.d.ts.map +0 -1
- package/dist/commands/rekey.js +0 -209
- package/dist/commands/rekey.js.map +0 -1
- package/dist/commands/repos-list-json.d.ts +0 -58
- package/dist/commands/repos-list-json.d.ts.map +0 -1
- package/dist/commands/repos-list-json.js +0 -45
- package/dist/commands/repos-list-json.js.map +0 -1
- package/dist/commands/repos.d.ts +0 -11
- package/dist/commands/repos.d.ts.map +0 -1
- package/dist/commands/repos.js +0 -102
- package/dist/commands/repos.js.map +0 -1
- package/dist/commands/restart.d.ts +0 -18
- package/dist/commands/restart.d.ts.map +0 -1
- package/dist/commands/restart.js +0 -113
- package/dist/commands/restart.js.map +0 -1
- package/dist/commands/resume.d.ts +0 -63
- package/dist/commands/resume.d.ts.map +0 -1
- package/dist/commands/resume.js +0 -174
- package/dist/commands/resume.js.map +0 -1
- package/dist/commands/runbooks.d.ts +0 -45
- package/dist/commands/runbooks.d.ts.map +0 -1
- package/dist/commands/runbooks.js +0 -313
- package/dist/commands/runbooks.js.map +0 -1
- package/dist/commands/seed.d.ts +0 -27
- package/dist/commands/seed.d.ts.map +0 -1
- package/dist/commands/seed.js +0 -303
- package/dist/commands/seed.js.map +0 -1
- package/dist/commands/services-tls.d.ts +0 -120
- package/dist/commands/services-tls.d.ts.map +0 -1
- package/dist/commands/services-tls.js +0 -489
- package/dist/commands/services-tls.js.map +0 -1
- package/dist/commands/services.d.ts +0 -218
- package/dist/commands/services.d.ts.map +0 -1
- package/dist/commands/services.js +0 -830
- package/dist/commands/services.js.map +0 -1
- package/dist/commands/setup-linux-gate.d.ts +0 -26
- package/dist/commands/setup-linux-gate.d.ts.map +0 -1
- package/dist/commands/setup-linux-gate.js +0 -40
- package/dist/commands/setup-linux-gate.js.map +0 -1
- package/dist/commands/setup-metrics.d.ts +0 -26
- package/dist/commands/setup-metrics.d.ts.map +0 -1
- package/dist/commands/setup-metrics.js +0 -56
- package/dist/commands/setup-metrics.js.map +0 -1
- package/dist/commands/setup-phase-5a-skill-source.d.ts +0 -84
- package/dist/commands/setup-phase-5a-skill-source.d.ts.map +0 -1
- package/dist/commands/setup-phase-5a-skill-source.js +0 -259
- package/dist/commands/setup-phase-5a-skill-source.js.map +0 -1
- package/dist/commands/setup-phase-5b-project-sweep.d.ts +0 -38
- package/dist/commands/setup-phase-5b-project-sweep.d.ts.map +0 -1
- package/dist/commands/setup-phase-5b-project-sweep.js +0 -175
- package/dist/commands/setup-phase-5b-project-sweep.js.map +0 -1
- package/dist/commands/setup-phase-8-kg-hook.d.ts +0 -48
- package/dist/commands/setup-phase-8-kg-hook.d.ts.map +0 -1
- package/dist/commands/setup-phase-8-kg-hook.js +0 -93
- package/dist/commands/setup-phase-8-kg-hook.js.map +0 -1
- package/dist/commands/setup-phase-9-memory-bridge.d.ts +0 -36
- package/dist/commands/setup-phase-9-memory-bridge.d.ts.map +0 -1
- package/dist/commands/setup-phase-9-memory-bridge.js +0 -59
- package/dist/commands/setup-phase-9-memory-bridge.js.map +0 -1
- package/dist/commands/setup.d.ts +0 -231
- package/dist/commands/setup.d.ts.map +0 -1
- package/dist/commands/setup.js +0 -1374
- package/dist/commands/setup.js.map +0 -1
- package/dist/commands/skills-100x.d.ts +0 -34
- package/dist/commands/skills-100x.d.ts.map +0 -1
- package/dist/commands/skills-100x.js +0 -405
- package/dist/commands/skills-100x.js.map +0 -1
- package/dist/commands/skills-doctor.d.ts +0 -14
- package/dist/commands/skills-doctor.d.ts.map +0 -1
- package/dist/commands/skills-doctor.js +0 -126
- package/dist/commands/skills-doctor.js.map +0 -1
- package/dist/commands/skills-hook.d.ts +0 -19
- package/dist/commands/skills-hook.d.ts.map +0 -1
- package/dist/commands/skills-hook.js +0 -99
- package/dist/commands/skills-hook.js.map +0 -1
- package/dist/commands/skills-install-model-router.d.ts +0 -20
- package/dist/commands/skills-install-model-router.d.ts.map +0 -1
- package/dist/commands/skills-install-model-router.js +0 -55
- package/dist/commands/skills-install-model-router.js.map +0 -1
- package/dist/commands/skills-migrate-back.d.ts +0 -21
- package/dist/commands/skills-migrate-back.d.ts.map +0 -1
- package/dist/commands/skills-migrate-back.js +0 -222
- package/dist/commands/skills-migrate-back.js.map +0 -1
- package/dist/commands/skills-migrate-hooks-back.d.ts +0 -19
- package/dist/commands/skills-migrate-hooks-back.d.ts.map +0 -1
- package/dist/commands/skills-migrate-hooks-back.js +0 -83
- package/dist/commands/skills-migrate-hooks-back.js.map +0 -1
- package/dist/commands/skills-migrate-hooks.d.ts +0 -40
- package/dist/commands/skills-migrate-hooks.d.ts.map +0 -1
- package/dist/commands/skills-migrate-hooks.js +0 -178
- package/dist/commands/skills-migrate-hooks.js.map +0 -1
- package/dist/commands/skills-migrate.d.ts +0 -33
- package/dist/commands/skills-migrate.d.ts.map +0 -1
- package/dist/commands/skills-migrate.js +0 -216
- package/dist/commands/skills-migrate.js.map +0 -1
- package/dist/commands/skills-onboard.d.ts +0 -26
- package/dist/commands/skills-onboard.d.ts.map +0 -1
- package/dist/commands/skills-onboard.js +0 -230
- package/dist/commands/skills-onboard.js.map +0 -1
- package/dist/commands/skills-shadow-backups.d.ts +0 -15
- package/dist/commands/skills-shadow-backups.d.ts.map +0 -1
- package/dist/commands/skills-shadow-backups.js +0 -132
- package/dist/commands/skills-shadow-backups.js.map +0 -1
- package/dist/commands/skills-source.d.ts +0 -61
- package/dist/commands/skills-source.d.ts.map +0 -1
- package/dist/commands/skills-source.js +0 -895
- package/dist/commands/skills-source.js.map +0 -1
- package/dist/commands/skills.d.ts +0 -59
- package/dist/commands/skills.d.ts.map +0 -1
- package/dist/commands/skills.js +0 -461
- package/dist/commands/skills.js.map +0 -1
- package/dist/commands/status.d.ts +0 -65
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js +0 -249
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/stop.d.ts +0 -10
- package/dist/commands/stop.d.ts.map +0 -1
- package/dist/commands/stop.js +0 -17
- package/dist/commands/stop.js.map +0 -1
- package/dist/commands/substrate-audit-log.d.ts +0 -51
- package/dist/commands/substrate-audit-log.d.ts.map +0 -1
- package/dist/commands/substrate-audit-log.js +0 -161
- package/dist/commands/substrate-audit-log.js.map +0 -1
- package/dist/commands/substrate.d.ts +0 -87
- package/dist/commands/substrate.d.ts.map +0 -1
- package/dist/commands/substrate.js +0 -194
- package/dist/commands/substrate.js.map +0 -1
- package/dist/commands/update.d.ts +0 -89
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js +0 -331
- package/dist/commands/update.js.map +0 -1
- package/dist/commands/upgrade-history.d.ts +0 -15
- package/dist/commands/upgrade-history.d.ts.map +0 -1
- package/dist/commands/upgrade-history.js +0 -34
- package/dist/commands/upgrade-history.js.map +0 -1
- package/dist/commands/upgrade-lock.d.ts +0 -93
- package/dist/commands/upgrade-lock.d.ts.map +0 -1
- package/dist/commands/upgrade-lock.js +0 -225
- package/dist/commands/upgrade-lock.js.map +0 -1
- package/dist/commands/upgrade-log.d.ts +0 -86
- package/dist/commands/upgrade-log.d.ts.map +0 -1
- package/dist/commands/upgrade-log.js +0 -146
- package/dist/commands/upgrade-log.js.map +0 -1
- package/dist/commands/upgrade.d.ts +0 -445
- package/dist/commands/upgrade.d.ts.map +0 -1
- package/dist/commands/upgrade.js +0 -1718
- package/dist/commands/upgrade.js.map +0 -1
- package/dist/commands/workspace-list-json.d.ts +0 -73
- package/dist/commands/workspace-list-json.d.ts.map +0 -1
- package/dist/commands/workspace-list-json.js +0 -59
- package/dist/commands/workspace-list-json.js.map +0 -1
- package/dist/commands/workspace.d.ts +0 -23
- package/dist/commands/workspace.d.ts.map +0 -1
- package/dist/commands/workspace.js +0 -203
- package/dist/commands/workspace.js.map +0 -1
- package/dist/commands/world-snapshot.d.ts +0 -32
- package/dist/commands/world-snapshot.d.ts.map +0 -1
- package/dist/commands/world-snapshot.js +0 -531
- package/dist/commands/world-snapshot.js.map +0 -1
- package/dist/commands/world-upgrade.d.ts +0 -33
- package/dist/commands/world-upgrade.d.ts.map +0 -1
- package/dist/commands/world-upgrade.js +0 -82
- package/dist/commands/world-upgrade.js.map +0 -1
- package/dist/commands/world.d.ts +0 -12
- package/dist/commands/world.d.ts.map +0 -1
- package/dist/commands/world.js +0 -18
- package/dist/commands/world.js.map +0 -1
- package/dist/commands/worldspec/compile.d.ts +0 -20
- package/dist/commands/worldspec/compile.d.ts.map +0 -1
- package/dist/commands/worldspec/compile.js +0 -130
- package/dist/commands/worldspec/compile.js.map +0 -1
- package/dist/commands/worldspec/index.d.ts +0 -12
- package/dist/commands/worldspec/index.d.ts.map +0 -1
- package/dist/commands/worldspec/index.js +0 -23
- package/dist/commands/worldspec/index.js.map +0 -1
- package/dist/commands/worldspec/init.d.ts +0 -15
- package/dist/commands/worldspec/init.d.ts.map +0 -1
- package/dist/commands/worldspec/init.js +0 -166
- package/dist/commands/worldspec/init.js.map +0 -1
- package/dist/commands/worldspec/schema.d.ts +0 -11
- package/dist/commands/worldspec/schema.d.ts.map +0 -1
- package/dist/commands/worldspec/schema.js +0 -55
- package/dist/commands/worldspec/schema.js.map +0 -1
- package/dist/commands/worldspec/validate.d.ts +0 -15
- package/dist/commands/worldspec/validate.d.ts.map +0 -1
- package/dist/commands/worldspec/validate.js +0 -66
- package/dist/commands/worldspec/validate.js.map +0 -1
- package/dist/commands/yolo.d.ts +0 -95
- package/dist/commands/yolo.d.ts.map +0 -1
- package/dist/commands/yolo.js +0 -377
- package/dist/commands/yolo.js.map +0 -1
- package/dist/context.d.ts +0 -30
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -56
- package/dist/context.js.map +0 -1
- package/dist/docker-host.d.ts +0 -18
- package/dist/docker-host.d.ts.map +0 -1
- package/dist/docker-host.js +0 -17
- package/dist/docker-host.js.map +0 -1
- package/dist/exit-codes.d.ts +0 -67
- package/dist/exit-codes.d.ts.map +0 -1
- package/dist/exit-codes.js +0 -67
- package/dist/exit-codes.js.map +0 -1
- package/dist/from-manifest.d.ts +0 -53
- package/dist/from-manifest.d.ts.map +0 -1
- package/dist/from-manifest.js +0 -95
- package/dist/from-manifest.js.map +0 -1
- package/dist/image-presence.d.ts +0 -40
- package/dist/image-presence.d.ts.map +0 -1
- package/dist/image-presence.js +0 -39
- package/dist/image-presence.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/install-root.d.ts +0 -74
- package/dist/install-root.d.ts.map +0 -1
- package/dist/install-root.js +0 -98
- package/dist/install-root.js.map +0 -1
- package/dist/lib/anthropic-base-url-file.d.ts +0 -37
- package/dist/lib/anthropic-base-url-file.d.ts.map +0 -1
- package/dist/lib/anthropic-base-url-file.js +0 -46
- package/dist/lib/anthropic-base-url-file.js.map +0 -1
- package/dist/lib/auth-backend.d.ts +0 -168
- package/dist/lib/auth-backend.d.ts.map +0 -1
- package/dist/lib/auth-backend.js +0 -172
- package/dist/lib/auth-backend.js.map +0 -1
- package/dist/lib/auth-list-cache.d.ts +0 -67
- package/dist/lib/auth-list-cache.d.ts.map +0 -1
- package/dist/lib/auth-list-cache.js +0 -84
- package/dist/lib/auth-list-cache.js.map +0 -1
- package/dist/lib/auth-list.d.ts +0 -107
- package/dist/lib/auth-list.d.ts.map +0 -1
- package/dist/lib/auth-list.js +0 -123
- package/dist/lib/auth-list.js.map +0 -1
- package/dist/lib/auth-login.d.ts +0 -92
- package/dist/lib/auth-login.d.ts.map +0 -1
- package/dist/lib/auth-login.js +0 -124
- package/dist/lib/auth-login.js.map +0 -1
- package/dist/lib/auth-mutator-backend.d.ts +0 -54
- package/dist/lib/auth-mutator-backend.d.ts.map +0 -1
- package/dist/lib/auth-mutator-backend.js +0 -62
- package/dist/lib/auth-mutator-backend.js.map +0 -1
- package/dist/lib/auth-refresh-kubernetes.d.ts +0 -65
- package/dist/lib/auth-refresh-kubernetes.d.ts.map +0 -1
- package/dist/lib/auth-refresh-kubernetes.js +0 -125
- package/dist/lib/auth-refresh-kubernetes.js.map +0 -1
- package/dist/lib/auth-remote.d.ts +0 -172
- package/dist/lib/auth-remote.d.ts.map +0 -1
- package/dist/lib/auth-remote.js +0 -394
- package/dist/lib/auth-remote.js.map +0 -1
- package/dist/lib/bootstrap-kubernetes.d.ts +0 -164
- package/dist/lib/bootstrap-kubernetes.d.ts.map +0 -1
- package/dist/lib/bootstrap-kubernetes.js +0 -1002
- package/dist/lib/bootstrap-kubernetes.js.map +0 -1
- package/dist/lib/build-if-stale.d.ts +0 -33
- package/dist/lib/build-if-stale.d.ts.map +0 -1
- package/dist/lib/build-if-stale.js +0 -156
- package/dist/lib/build-if-stale.js.map +0 -1
- package/dist/lib/bundle-freshness.d.ts +0 -57
- package/dist/lib/bundle-freshness.d.ts.map +0 -1
- package/dist/lib/bundle-freshness.js +0 -223
- package/dist/lib/bundle-freshness.js.map +0 -1
- package/dist/lib/bundle-source.d.ts +0 -52
- package/dist/lib/bundle-source.d.ts.map +0 -1
- package/dist/lib/bundle-source.js +0 -83
- package/dist/lib/bundle-source.js.map +0 -1
- package/dist/lib/cf-access-token.d.ts +0 -32
- package/dist/lib/cf-access-token.d.ts.map +0 -1
- package/dist/lib/cf-access-token.js +0 -51
- package/dist/lib/cf-access-token.js.map +0 -1
- package/dist/lib/completion-generator.d.ts +0 -107
- package/dist/lib/completion-generator.d.ts.map +0 -1
- package/dist/lib/completion-generator.js +0 -226
- package/dist/lib/completion-generator.js.map +0 -1
- package/dist/lib/config.d.ts +0 -114
- package/dist/lib/config.d.ts.map +0 -1
- package/dist/lib/config.js +0 -246
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/flywheel-probes.d.ts +0 -58
- package/dist/lib/flywheel-probes.d.ts.map +0 -1
- package/dist/lib/flywheel-probes.js +0 -163
- package/dist/lib/flywheel-probes.js.map +0 -1
- package/dist/lib/health-probes.d.ts +0 -267
- package/dist/lib/health-probes.d.ts.map +0 -1
- package/dist/lib/health-probes.js +0 -933
- package/dist/lib/health-probes.js.map +0 -1
- package/dist/lib/help-groups.d.ts +0 -36
- package/dist/lib/help-groups.d.ts.map +0 -1
- package/dist/lib/help-groups.js +0 -124
- package/dist/lib/help-groups.js.map +0 -1
- package/dist/lib/host-side-proxy.d.ts +0 -67
- package/dist/lib/host-side-proxy.d.ts.map +0 -1
- package/dist/lib/host-side-proxy.js +0 -177
- package/dist/lib/host-side-proxy.js.map +0 -1
- package/dist/lib/instrumentation.d.ts +0 -85
- package/dist/lib/instrumentation.d.ts.map +0 -1
- package/dist/lib/instrumentation.js +0 -104
- package/dist/lib/instrumentation.js.map +0 -1
- package/dist/lib/k8s-bootstrap.d.ts +0 -126
- package/dist/lib/k8s-bootstrap.d.ts.map +0 -1
- package/dist/lib/k8s-bootstrap.js +0 -218
- package/dist/lib/k8s-bootstrap.js.map +0 -1
- package/dist/lib/k8s-context-discovery.d.ts +0 -80
- package/dist/lib/k8s-context-discovery.d.ts.map +0 -1
- package/dist/lib/k8s-context-discovery.js +0 -102
- package/dist/lib/k8s-context-discovery.js.map +0 -1
- package/dist/lib/k8s-secret-render.d.ts +0 -141
- package/dist/lib/k8s-secret-render.d.ts.map +0 -1
- package/dist/lib/k8s-secret-render.js +0 -318
- package/dist/lib/k8s-secret-render.js.map +0 -1
- package/dist/lib/kg-caps.d.ts +0 -19
- package/dist/lib/kg-caps.d.ts.map +0 -1
- package/dist/lib/kg-caps.js +0 -19
- package/dist/lib/kg-caps.js.map +0 -1
- package/dist/lib/kubectl-context.d.ts +0 -87
- package/dist/lib/kubectl-context.d.ts.map +0 -1
- package/dist/lib/kubectl-context.js +0 -105
- package/dist/lib/kubectl-context.js.map +0 -1
- package/dist/lib/kubectl-wrap.d.ts +0 -65
- package/dist/lib/kubectl-wrap.d.ts.map +0 -1
- package/dist/lib/kubectl-wrap.js +0 -135
- package/dist/lib/kubectl-wrap.js.map +0 -1
- package/dist/lib/manifest-refresh.d.ts +0 -136
- package/dist/lib/manifest-refresh.d.ts.map +0 -1
- package/dist/lib/manifest-refresh.js +0 -298
- package/dist/lib/manifest-refresh.js.map +0 -1
- package/dist/lib/memory-host-process-migration.d.ts +0 -56
- package/dist/lib/memory-host-process-migration.d.ts.map +0 -1
- package/dist/lib/memory-host-process-migration.js +0 -156
- package/dist/lib/memory-host-process-migration.js.map +0 -1
- package/dist/lib/memory-secret.d.ts +0 -83
- package/dist/lib/memory-secret.d.ts.map +0 -1
- package/dist/lib/memory-secret.js +0 -147
- package/dist/lib/memory-secret.js.map +0 -1
- package/dist/lib/peripheral-registry.d.ts +0 -53
- package/dist/lib/peripheral-registry.d.ts.map +0 -1
- package/dist/lib/peripheral-registry.js +0 -73
- package/dist/lib/peripheral-registry.js.map +0 -1
- package/dist/lib/plans-client.d.ts +0 -69
- package/dist/lib/plans-client.d.ts.map +0 -1
- package/dist/lib/plans-client.js +0 -140
- package/dist/lib/plans-client.js.map +0 -1
- package/dist/lib/port-forward.d.ts +0 -168
- package/dist/lib/port-forward.d.ts.map +0 -1
- package/dist/lib/port-forward.js +0 -393
- package/dist/lib/port-forward.js.map +0 -1
- package/dist/lib/shell-rc.d.ts +0 -90
- package/dist/lib/shell-rc.d.ts.map +0 -1
- package/dist/lib/shell-rc.js +0 -91
- package/dist/lib/shell-rc.js.map +0 -1
- package/dist/lib/shim-generator.d.ts +0 -51
- package/dist/lib/shim-generator.d.ts.map +0 -1
- package/dist/lib/shim-generator.js +0 -88
- package/dist/lib/shim-generator.js.map +0 -1
- package/dist/lib/skills-apply-overlays.d.ts +0 -35
- package/dist/lib/skills-apply-overlays.d.ts.map +0 -1
- package/dist/lib/skills-apply-overlays.js +0 -243
- package/dist/lib/skills-apply-overlays.js.map +0 -1
- package/dist/lib/symlink-reconcile.d.ts +0 -32
- package/dist/lib/symlink-reconcile.d.ts.map +0 -1
- package/dist/lib/symlink-reconcile.js +0 -80
- package/dist/lib/symlink-reconcile.js.map +0 -1
- package/dist/lib/upgrade-check.d.ts +0 -60
- package/dist/lib/upgrade-check.d.ts.map +0 -1
- package/dist/lib/upgrade-check.js +0 -169
- package/dist/lib/upgrade-check.js.map +0 -1
- package/dist/lib/upgrade-kubernetes.d.ts +0 -193
- package/dist/lib/upgrade-kubernetes.d.ts.map +0 -1
- package/dist/lib/upgrade-kubernetes.js +0 -1014
- package/dist/lib/upgrade-kubernetes.js.map +0 -1
- package/dist/lib/world-mcp-register.d.ts +0 -98
- package/dist/lib/world-mcp-register.d.ts.map +0 -1
- package/dist/lib/world-mcp-register.js +0 -117
- package/dist/lib/world-mcp-register.js.map +0 -1
- package/dist/output.d.ts +0 -10
- package/dist/output.d.ts.map +0 -1
- package/dist/output.js +0 -31
- package/dist/output.js.map +0 -1
- package/dist/pleri-config.d.ts +0 -22
- package/dist/pleri-config.d.ts.map +0 -1
- package/dist/pleri-config.js +0 -42
- package/dist/pleri-config.js.map +0 -1
- package/dist/protocol-version.d.ts +0 -79
- package/dist/protocol-version.d.ts.map +0 -1
- package/dist/protocol-version.js +0 -133
- package/dist/protocol-version.js.map +0 -1
- package/dist/registry-allowlist.d.ts +0 -47
- package/dist/registry-allowlist.d.ts.map +0 -1
- package/dist/registry-allowlist.js +0 -67
- package/dist/registry-allowlist.js.map +0 -1
- package/dist/spawn/home-override.d.ts +0 -82
- package/dist/spawn/home-override.d.ts.map +0 -1
- package/dist/spawn/home-override.js +0 -107
- package/dist/spawn/home-override.js.map +0 -1
- package/host-cp/src/linear-sync.mjs +0 -43
package/dist/commands/setup.js
DELETED
|
@@ -1,1374 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* olam setup — substrate-aware fresh-host wizard.
|
|
3
|
-
*
|
|
4
|
-
* Phase C2 of olam-operator-onboarding-parity (plan
|
|
5
|
-
* ~/.claude/plans/olam-operator-onboarding-parity.md).
|
|
6
|
-
*
|
|
7
|
-
* Substrate-aware orchestration. Default substrate = kubernetes (k3d on all
|
|
8
|
-
* platforms — macOS and Linux alike). Existing installs whose ~/.olam/config.json
|
|
9
|
-
* carries host.substrate: 'compose' are protected — they continue on docker/compose
|
|
10
|
-
* and see a one-line migration hint; no auto-migration.
|
|
11
|
-
*
|
|
12
|
-
* Kubernetes substrate phases (default for fresh installs):
|
|
13
|
-
* Phase 1: System check (kubectl on PATH + docker daemon + Node ≥20)
|
|
14
|
-
* Phase 1.5: Install k3d (brew install k3d when available; else upstream install.sh)
|
|
15
|
-
* Phase 2: olam CLI sanity (--version returns)
|
|
16
|
-
* Phase 2.5: Provision cluster (k3d cluster create olam-dev; k3d updates ~/.kube/config)
|
|
17
|
-
* Phase 2.6: Pin kubectl context (writes host.kubectl_context_pinned = k3d-olam-dev)
|
|
18
|
-
* Phase 3: Bootstrap (subprocess: olam bootstrap with kubernetes substrate)
|
|
19
|
-
* Phase 3.5: K3d HTTPS bootstrap (mkcert install + TLS Secret → Traefik IngressRoute)
|
|
20
|
-
* … same as docker thereafter
|
|
21
|
-
*
|
|
22
|
-
* Docker substrate phases (existing compose installs or --substrate=docker):
|
|
23
|
-
* Phase 1: System check (Docker daemon reachable + Node ≥20)
|
|
24
|
-
* Phase 1.5: (no-op for docker)
|
|
25
|
-
* Phase 2: olam CLI sanity (--version returns)
|
|
26
|
-
* Phase 2.5: (no-op for docker)
|
|
27
|
-
* Phase 3: Bootstrap (subprocess: olam bootstrap)
|
|
28
|
-
* Phase 3.5: (no-op for docker)
|
|
29
|
-
* Phase 4: Shell init (idempotent append of completion eval-line)
|
|
30
|
-
* Phase 5: Init global config (ensure ~/.olam/config.json has host.substrate set)
|
|
31
|
-
* Phase 5a: Skill source picker (runs unconditionally; auto-skips when sources already registered)
|
|
32
|
-
* Phase 5b: Project sweep
|
|
33
|
-
* Phase 6: Auth prompt (offer interactive `olam auth login`)
|
|
34
|
-
* Phase 7: Final verify (subprocess: olam doctor; halt on non-zero)
|
|
35
|
-
*
|
|
36
|
-
* End-state prints "next steps" pointing at the 3-contract docs per
|
|
37
|
-
* CLAUDE.md's "Reading order for new orgs."
|
|
38
|
-
*
|
|
39
|
-
* Failure semantics: setup fails fast at the first failed phase + prints
|
|
40
|
-
* a named remedy. All phases are idempotent so re-running is safe.
|
|
41
|
-
*
|
|
42
|
-
* Flags:
|
|
43
|
-
* --substrate=<docker|kubernetes> substrate to target (default: kubernetes; alias k3s→kubernetes)
|
|
44
|
-
* --cluster-name=<name> k3d cluster name (default: olam-dev). Useful for operators with
|
|
45
|
-
* pre-existing clusters or running multiple olam stacks side-by-side.
|
|
46
|
-
* --skip-https-bootstrap skip Phase 3.5 (operator manages TLS certs manually)
|
|
47
|
-
* --skip-shell-init skip Phase 4 (operator manages shell rc manually)
|
|
48
|
-
* --skip-auth skip Phase 6 (operator will run `olam auth login` later)
|
|
49
|
-
* --yes / -y auto-affirm every prompt (non-interactive)
|
|
50
|
-
*
|
|
51
|
-
* Reversibility: clean-revert; each phase delegates to a separately-
|
|
52
|
-
* tested primitive. Phase 4 keeps a `<rc>.olam-bak.<ts>` backup.
|
|
53
|
-
*/
|
|
54
|
-
import { spawn, spawnSync } from 'node:child_process';
|
|
55
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
56
|
-
import { homedir } from 'node:os';
|
|
57
|
-
import path from 'node:path';
|
|
58
|
-
import { createInterface } from 'node:readline';
|
|
59
|
-
import { readCliVersion } from '../cli-version.js';
|
|
60
|
-
import { probeDockerDaemon, probeComposePlugin, probeKubectl, probeK3d, probeColimaKubernetesEnabled, } from '../lib/health-probes.js';
|
|
61
|
-
import { discoverOfferableContexts, defaultClusterInfo, defaultGetContexts, defaultIsIdle, } from '../lib/k8s-context-discovery.js';
|
|
62
|
-
import { appendIdempotent, resolveShellRc } from '../lib/shell-rc.js';
|
|
63
|
-
import { applyKubectlContextPin, findProjectRoot, runGlobalInit } from './init.js';
|
|
64
|
-
import { ensureTlsInstalled } from './services-tls.js';
|
|
65
|
-
import { printError, printHeader, printInfo, printSuccess, printWarning } from '../output.js';
|
|
66
|
-
import { pickSkillSourcePhase, formatPostSetupSuggestion, } from './setup-phase-5a-skill-source.js';
|
|
67
|
-
import { runProjectSweepPhase } from './setup-phase-5b-project-sweep.js';
|
|
68
|
-
import { runKgHookPhase } from './setup-phase-8-kg-hook.js';
|
|
69
|
-
import { runMemoryBridgePhase } from './setup-phase-9-memory-bridge.js';
|
|
70
|
-
import { OLAM_CONFIG_PATH, writeConfig } from '../lib/config.js';
|
|
71
|
-
import { migrateSecretIfNeeded, KNOWN_SECRET_NAMES } from '@olam/core/src/secrets/paths.js';
|
|
72
|
-
import { resolveKubectlContext } from '../lib/kubectl-context.js';
|
|
73
|
-
const REQUIRED_NODE_MAJOR = 20;
|
|
74
|
-
/** k3d cluster name provisioned by olam setup --substrate=kubernetes. */
|
|
75
|
-
export const SETUP_K3D_CLUSTER_NAME = 'olam-dev';
|
|
76
|
-
const NEXT_STEPS_DOCS_DOCKER = [
|
|
77
|
-
'https://github.com/pleri/olam/blob/main/docs/architecture/devbox-contract.md — image contract',
|
|
78
|
-
'https://github.com/pleri/olam/blob/main/docs/architecture/manifest-spec.md — per-repo .adb.yaml schema',
|
|
79
|
-
'https://github.com/pleri/olam/blob/main/docs/architecture/config-spec.md — workspace .olam/config.yaml schema',
|
|
80
|
-
];
|
|
81
|
-
const NEXT_STEPS_DOCS_KUBERNETES = [
|
|
82
|
-
'https://github.com/pleri/olam/blob/main/docs/architecture/devbox-contract.md — image contract',
|
|
83
|
-
'https://github.com/pleri/olam/blob/main/docs/architecture/manifest-spec.md — per-repo .adb.yaml schema',
|
|
84
|
-
'https://github.com/pleri/olam/blob/main/docs/architecture/config-spec.md — workspace .olam/config.yaml schema',
|
|
85
|
-
'https://github.com/pleri/olam/blob/main/docs/k8s/SETUP.md — k3d operator guide',
|
|
86
|
-
];
|
|
87
|
-
// ── Default deps ───────────────────────────────────────────────────────
|
|
88
|
-
const defaultSpawn = (cmd, args) => new Promise((resolve) => {
|
|
89
|
-
const child = spawn(cmd, [...args], { stdio: 'inherit' });
|
|
90
|
-
child.on('exit', (code) => resolve({ status: code }));
|
|
91
|
-
child.on('error', () => resolve({ status: 1 }));
|
|
92
|
-
});
|
|
93
|
-
const defaultPrompt = (question, defaultYes) => {
|
|
94
|
-
// MEDIUM fix (Phase C CP3): non-TTY stdin (CI pipeline forgot `--yes`,
|
|
95
|
-
// or `olam setup < /dev/null`) would otherwise hang on `readline.question`
|
|
96
|
-
// forever with no diagnostic. When stdin is not a TTY, fall back to the
|
|
97
|
-
// default answer with a stderr hint so the operator knows what happened.
|
|
98
|
-
if (!process.stdin.isTTY) {
|
|
99
|
-
process.stderr.write(`[olam setup] non-TTY stdin detected; using default answer (${defaultYes ? 'yes' : 'no'}). `
|
|
100
|
-
+ `Re-run with \`--yes\` for explicit non-interactive mode.\n`);
|
|
101
|
-
return Promise.resolve(defaultYes);
|
|
102
|
-
}
|
|
103
|
-
return new Promise((resolve) => {
|
|
104
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
105
|
-
const suffix = defaultYes ? ' [Y/n]: ' : ' [y/N]: ';
|
|
106
|
-
rl.question(`${question}${suffix}`, (answer) => {
|
|
107
|
-
rl.close();
|
|
108
|
-
const t = answer.trim().toLowerCase();
|
|
109
|
-
if (t === '')
|
|
110
|
-
resolve(defaultYes);
|
|
111
|
-
else if (t === 'y' || t === 'yes')
|
|
112
|
-
resolve(true);
|
|
113
|
-
else if (t === 'n' || t === 'no')
|
|
114
|
-
resolve(false);
|
|
115
|
-
else
|
|
116
|
-
resolve(defaultYes);
|
|
117
|
-
});
|
|
118
|
-
// Belt-and-braces: if stdin closes mid-prompt (EOF), resolve with default.
|
|
119
|
-
rl.on('close', () => resolve(defaultYes));
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
/** k3d / DNS-label name validation — same rules k3d enforces. */
|
|
123
|
-
const CLUSTER_NAME_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
124
|
-
/**
|
|
125
|
-
* Validate the --cluster-name value.
|
|
126
|
-
* Returns an error message when invalid, or null when valid.
|
|
127
|
-
*/
|
|
128
|
-
export function validateClusterName(name) {
|
|
129
|
-
if (name.length === 0)
|
|
130
|
-
return 'cluster name must not be empty';
|
|
131
|
-
if (name.length > 63)
|
|
132
|
-
return 'cluster name must be ≤63 characters (DNS label limit)';
|
|
133
|
-
if (!CLUSTER_NAME_RE.test(name)) {
|
|
134
|
-
return (`cluster name '${name}' is invalid — must match ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ `
|
|
135
|
-
+ '(lowercase alphanumeric, hyphens allowed in the middle)');
|
|
136
|
-
}
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Resolve the effective cluster name.
|
|
141
|
-
* Explicit opt takes priority; falls back to the constant default.
|
|
142
|
-
*/
|
|
143
|
-
function resolveClusterName(opts) {
|
|
144
|
-
return opts.clusterName ?? SETUP_K3D_CLUSTER_NAME;
|
|
145
|
-
}
|
|
146
|
-
// ── Substrate resolution ───────────────────────────────────────────────────
|
|
147
|
-
/** Migration hint printed once when an existing docker/compose install is detected. */
|
|
148
|
-
export const DOCKER_MIGRATION_HINT = 'olam: detected existing docker stack — continuing on docker. '
|
|
149
|
-
+ 'To migrate to k3d, run: olam upgrade --substrate=kubernetes (available in a future release).';
|
|
150
|
-
/**
|
|
151
|
-
* Resolve the effective substrate: explicit opt has highest priority, then
|
|
152
|
-
* auto-detect from ~/.olam/config.json (or override path), then default
|
|
153
|
-
* 'kubernetes' for fresh installs.
|
|
154
|
-
*
|
|
155
|
-
* The --substrate=k3s alias normalises to 'kubernetes'.
|
|
156
|
-
*
|
|
157
|
-
* Existing-install guard: when the config has host.substrate='compose' (the
|
|
158
|
-
* old docker default) and no explicit flag is provided, the wizard continues
|
|
159
|
-
* on 'docker' and prints a one-line migration hint. No auto-migration.
|
|
160
|
-
*/
|
|
161
|
-
function resolveSubstrate(opts, deps) {
|
|
162
|
-
if (opts.substrate === 'kubernetes')
|
|
163
|
-
return 'kubernetes';
|
|
164
|
-
if (opts.substrate === 'docker')
|
|
165
|
-
return 'docker';
|
|
166
|
-
// Auto-detect from config file
|
|
167
|
-
const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
|
|
168
|
-
if (existsSync(configPath)) {
|
|
169
|
-
try {
|
|
170
|
-
const raw = readFileSync(configPath, 'utf8');
|
|
171
|
-
const parsed = JSON.parse(raw);
|
|
172
|
-
const host = parsed.host;
|
|
173
|
-
if (host?.substrate === 'kubernetes')
|
|
174
|
-
return 'kubernetes';
|
|
175
|
-
if (host?.substrate === 'compose') {
|
|
176
|
-
// Existing docker/compose install — protect it from the default flip.
|
|
177
|
-
process.stderr.write(DOCKER_MIGRATION_HINT + '\n');
|
|
178
|
-
return 'docker';
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch {
|
|
182
|
-
// malformed config — fall through to new default
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// Fresh install (no config file, or unrecognised substrate) → new default
|
|
186
|
-
return 'kubernetes';
|
|
187
|
-
}
|
|
188
|
-
const SUBSTRATE_CHOICES = [
|
|
189
|
-
{
|
|
190
|
-
label: 'Docker Desktop (recommended)',
|
|
191
|
-
substrate: 'docker',
|
|
192
|
-
preferredRuntime: 'docker-desktop',
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
label: 'Colima',
|
|
196
|
-
substrate: 'docker',
|
|
197
|
-
preferredRuntime: 'colima',
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
label: 'Kubernetes (k3d on Docker Desktop)',
|
|
201
|
-
substrate: 'kubernetes',
|
|
202
|
-
preferredRuntime: 'docker-desktop',
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
label: 'Kubernetes (k3d on Colima)',
|
|
206
|
-
substrate: 'kubernetes',
|
|
207
|
-
preferredRuntime: 'colima',
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
label: 'Kubernetes (external context already pinned)',
|
|
211
|
-
substrate: 'kubernetes',
|
|
212
|
-
preferredRuntime: 'external-k8s',
|
|
213
|
-
requirePinnedContext: true,
|
|
214
|
-
},
|
|
215
|
-
];
|
|
216
|
-
/** Default (first) choice — Docker Desktop. */
|
|
217
|
-
const DEFAULT_SUBSTRATE_CHOICE = SUBSTRATE_CHOICES[0];
|
|
218
|
-
/**
|
|
219
|
-
* Narrows the picker-internal `SetupSubstrate` to the config-schema `Substrate`.
|
|
220
|
-
* `'docker'` in the picker maps to `'compose'` in the config (they name the same
|
|
221
|
-
* non-kubernetes stack; the config schema predates the picker rename).
|
|
222
|
-
*/
|
|
223
|
-
function toConfigSubstrate(s) {
|
|
224
|
-
return s === 'docker' ? 'compose' : 'kubernetes';
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Phase 0 — Substrate picker.
|
|
228
|
-
*
|
|
229
|
-
* Asks the operator which container runtime + substrate they want to use.
|
|
230
|
-
* Writes `host.substrate` and `host.preferred_runtime` to ~/.olam/config.json.
|
|
231
|
-
*
|
|
232
|
-
* Skip conditions (all silent — return { ok: true, skipped: true }):
|
|
233
|
-
* - opts.substrate is already set → "--substrate=<value> passed"
|
|
234
|
-
* - opts.skipSubstratePicker → "--skip-substrate-picker"
|
|
235
|
-
* - config already has both fields → "already configured (<runtime>)"
|
|
236
|
-
* - !process.stdin.isTTY && !opts.yes → uses docker-desktop default
|
|
237
|
-
* - opts.yes → uses docker-desktop default
|
|
238
|
-
*/
|
|
239
|
-
/**
|
|
240
|
-
* Return a comma-joined list of up to 5 available kubectl context names.
|
|
241
|
-
* Used to populate the error message when the operator enters an unknown context.
|
|
242
|
-
*/
|
|
243
|
-
function listAvailableContexts() {
|
|
244
|
-
const r = spawnSync('kubectl', ['config', 'get-contexts', '-o', 'name'], {
|
|
245
|
-
encoding: 'utf-8',
|
|
246
|
-
stdio: 'pipe',
|
|
247
|
-
});
|
|
248
|
-
if (r.status !== 0 || !r.stdout.trim())
|
|
249
|
-
return '(none found)';
|
|
250
|
-
const names = r.stdout.trim().split('\n').map((n) => n.trim()).filter(Boolean);
|
|
251
|
-
const preview = names.slice(0, 5);
|
|
252
|
-
return preview.join(', ') + (names.length > 5 ? `, … (+${names.length - 5} more)` : '');
|
|
253
|
-
}
|
|
254
|
-
export async function phase0SubstratePicker(opts, deps) {
|
|
255
|
-
// Skip: explicit --substrate= on the command line
|
|
256
|
-
if (opts.substrate !== undefined) {
|
|
257
|
-
return {
|
|
258
|
-
ok: true,
|
|
259
|
-
skipped: true,
|
|
260
|
-
message: `skipped — --substrate=${opts.substrate} passed`,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
// Skip: explicit --skip-substrate-picker
|
|
264
|
-
if (opts.skipSubstratePicker) {
|
|
265
|
-
return { ok: true, skipped: true, message: 'skipped via --skip-substrate-picker' };
|
|
266
|
-
}
|
|
267
|
-
// Skip: already configured in config file
|
|
268
|
-
const configPath = deps.configPath ?? OLAM_CONFIG_PATH;
|
|
269
|
-
if (existsSync(configPath)) {
|
|
270
|
-
try {
|
|
271
|
-
const raw = readFileSync(configPath, 'utf8');
|
|
272
|
-
const parsed = JSON.parse(raw);
|
|
273
|
-
const host = parsed.host;
|
|
274
|
-
if (host?.substrate !== undefined
|
|
275
|
-
&& host?.preferred_runtime !== undefined) {
|
|
276
|
-
return {
|
|
277
|
-
ok: true,
|
|
278
|
-
skipped: true,
|
|
279
|
-
message: `skipped — substrate already configured (${host.preferred_runtime})`,
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
catch {
|
|
284
|
-
// malformed config — proceed to picker
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
// Non-TTY without --yes → use default silently
|
|
288
|
-
if (!process.stdin.isTTY && !opts.yes) {
|
|
289
|
-
writeConfig({ host: { substrate: toConfigSubstrate(DEFAULT_SUBSTRATE_CHOICE.substrate), preferred_runtime: DEFAULT_SUBSTRATE_CHOICE.preferredRuntime } }, { configPath: deps.configPath });
|
|
290
|
-
return {
|
|
291
|
-
ok: true,
|
|
292
|
-
skipped: true,
|
|
293
|
-
message: 'skipped (non-TTY); using docker-desktop default',
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
// --yes mode → use default silently (write config, print summary)
|
|
297
|
-
if (opts.yes) {
|
|
298
|
-
writeConfig({ host: { substrate: toConfigSubstrate(DEFAULT_SUBSTRATE_CHOICE.substrate), preferred_runtime: DEFAULT_SUBSTRATE_CHOICE.preferredRuntime } }, { configPath: deps.configPath });
|
|
299
|
-
process.stdout.write(` ✓ Phase 0: substrate=${DEFAULT_SUBSTRATE_CHOICE.substrate} runtime=${DEFAULT_SUBSTRATE_CHOICE.preferredRuntime}\n`);
|
|
300
|
-
return {
|
|
301
|
-
ok: true,
|
|
302
|
-
message: `substrate=${DEFAULT_SUBSTRATE_CHOICE.substrate} runtime=${DEFAULT_SUBSTRATE_CHOICE.preferredRuntime}`,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
// Interactive picker via @inquirer/prompts select (same pattern as Phase 5a).
|
|
306
|
-
// Lazy-load only when deps don't inject the prompt functions — keeps the
|
|
307
|
-
// import out of the test path and avoids the eager-import overhead.
|
|
308
|
-
const resolvedSelectFn = deps.selectPromptFn
|
|
309
|
-
?? (await import('@inquirer/prompts')).select;
|
|
310
|
-
const choices = SUBSTRATE_CHOICES.map((c, i) => ({
|
|
311
|
-
value: String(i),
|
|
312
|
-
name: c.label,
|
|
313
|
-
}));
|
|
314
|
-
const pickedIndex = await resolvedSelectFn({
|
|
315
|
-
message: 'Choose your container runtime + substrate:',
|
|
316
|
-
choices,
|
|
317
|
-
});
|
|
318
|
-
const choice = SUBSTRATE_CHOICES[Number(pickedIndex)] ?? DEFAULT_SUBSTRATE_CHOICE;
|
|
319
|
-
// Special handling: external context requires kubectl_context_pinned to be set
|
|
320
|
-
if (choice.requirePinnedContext) {
|
|
321
|
-
// Check whether the config already has it
|
|
322
|
-
let hasPinnedContext = false;
|
|
323
|
-
if (existsSync(configPath)) {
|
|
324
|
-
try {
|
|
325
|
-
const raw = readFileSync(configPath, 'utf8');
|
|
326
|
-
const parsed = JSON.parse(raw);
|
|
327
|
-
const host = parsed.host;
|
|
328
|
-
hasPinnedContext = typeof host?.kubectl_context_pinned === 'string'
|
|
329
|
-
&& host.kubectl_context_pinned.length > 0;
|
|
330
|
-
}
|
|
331
|
-
catch {
|
|
332
|
-
// ignore
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
if (!hasPinnedContext) {
|
|
336
|
-
// Prompt for context name + validate
|
|
337
|
-
const resolvedInputFn = deps.inputPromptFn
|
|
338
|
-
?? (await import('@inquirer/prompts')).input;
|
|
339
|
-
const contextName = await resolvedInputFn({
|
|
340
|
-
message: 'Enter your kubectl context name (e.g. lima-k3s, gke_proj_region_cluster):',
|
|
341
|
-
validate: (v) => {
|
|
342
|
-
if (v.trim().length === 0)
|
|
343
|
-
return 'Context name must not be empty';
|
|
344
|
-
const name = v.trim();
|
|
345
|
-
// Sanitize to prevent jsonpath injection via embedded quotes.
|
|
346
|
-
const escaped = name.replace(/"/g, '\\"');
|
|
347
|
-
// Use jsonpath — `get-contexts <name>` exits 0 even for missing contexts
|
|
348
|
-
// (it just prints an empty table). jsonpath prints the name when found,
|
|
349
|
-
// empty string when not found.
|
|
350
|
-
const r = spawnSync('kubectl', ['config', 'view', '-o', `jsonpath={.contexts[?(@.name=="${escaped}")].name}`], { stdio: 'pipe', encoding: 'utf-8' });
|
|
351
|
-
if (r.status !== 0) {
|
|
352
|
-
return 'kubectl not available — verify kubectl is installed and re-run setup';
|
|
353
|
-
}
|
|
354
|
-
if (r.stdout.trim() !== name) {
|
|
355
|
-
return (`Context "${name}" not found in kubeconfig. `
|
|
356
|
-
+ `Available: ${listAvailableContexts()}`);
|
|
357
|
-
}
|
|
358
|
-
return true;
|
|
359
|
-
},
|
|
360
|
-
});
|
|
361
|
-
writeConfig({
|
|
362
|
-
host: {
|
|
363
|
-
substrate: toConfigSubstrate(choice.substrate),
|
|
364
|
-
preferred_runtime: choice.preferredRuntime,
|
|
365
|
-
kubectl_context_pinned: contextName.trim(),
|
|
366
|
-
},
|
|
367
|
-
}, { configPath: deps.configPath });
|
|
368
|
-
process.stdout.write(` ✓ Phase 0: substrate=${choice.substrate} runtime=${choice.preferredRuntime} context=${contextName.trim()}\n`);
|
|
369
|
-
return {
|
|
370
|
-
ok: true,
|
|
371
|
-
message: `substrate=${choice.substrate} runtime=${choice.preferredRuntime} context=${contextName.trim()}`,
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
writeConfig({ host: { substrate: toConfigSubstrate(choice.substrate), preferred_runtime: choice.preferredRuntime } }, { configPath: deps.configPath });
|
|
376
|
-
process.stdout.write(` ✓ Phase 0: substrate=${choice.substrate} runtime=${choice.preferredRuntime}\n`);
|
|
377
|
-
return {
|
|
378
|
-
ok: true,
|
|
379
|
-
message: `substrate=${choice.substrate} runtime=${choice.preferredRuntime}`,
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Phase 0.5 — Detect existing reachable kubeconfig contexts (ADR 021).
|
|
384
|
-
*
|
|
385
|
-
* Only runs when substrate=kubernetes. On docker substrate, returns no-op.
|
|
386
|
-
*
|
|
387
|
-
* Behaviour:
|
|
388
|
-
* 1. --reuse-cluster=<name> provided → validate reachability of that context.
|
|
389
|
-
* If reachable, skip Phase 1.5 + 2.5 and pin Phase 2.6 to this context.
|
|
390
|
-
* If unreachable, fail fast with actionable error.
|
|
391
|
-
* 2. --yes mode: if reachable idle contexts exist, print an info line and
|
|
392
|
-
* continue to k3d provision (backward compat — --yes defaults to NO reuse).
|
|
393
|
-
* 3. Interactive: prompt for each offerable context; operator chooses.
|
|
394
|
-
*
|
|
395
|
-
* Returns a PhaseResult extended with an optional `reuseContext` field.
|
|
396
|
-
* When `reuseContext` is set, later phases skip k3d install/provision.
|
|
397
|
-
*/
|
|
398
|
-
async function phase0_5DetectExistingContext(substrate, opts, deps) {
|
|
399
|
-
if (substrate !== 'kubernetes') {
|
|
400
|
-
return { ok: true, skipped: true, message: 'no-op for docker substrate' };
|
|
401
|
-
}
|
|
402
|
-
// --reuse-cluster=<name> explicit opt-in: validate that context.
|
|
403
|
-
if (opts.reuseCluster) {
|
|
404
|
-
const name = opts.reuseCluster;
|
|
405
|
-
const clusterInfoFn = deps.kubectlClusterInfo ?? defaultClusterInfo;
|
|
406
|
-
const probe = clusterInfoFn(name);
|
|
407
|
-
if (!probe.reachable) {
|
|
408
|
-
return {
|
|
409
|
-
ok: false,
|
|
410
|
-
message: `--reuse-cluster=${name} but context is not reachable: ${probe.error ?? 'unknown error'}`,
|
|
411
|
-
remedy: `Verify the context exists (\`kubectl config get-contexts\`) and is reachable `
|
|
412
|
-
+ `(\`kubectl --context=${name} cluster-info\`), then re-run \`olam setup --reuse-cluster=${name}\`.`,
|
|
413
|
-
reuseContext: undefined,
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
return {
|
|
417
|
-
ok: true,
|
|
418
|
-
message: `will reuse context ${name}${probe.serverUrl ? ` (${probe.serverUrl})` : ''}`,
|
|
419
|
-
reuseContext: name,
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
// Discover reachable idle contexts not owned by olam.
|
|
423
|
-
const { offerable } = discoverOfferableContexts(deps.kubeContextDeps);
|
|
424
|
-
if (offerable.length === 0) {
|
|
425
|
-
return {
|
|
426
|
-
ok: true,
|
|
427
|
-
skipped: true,
|
|
428
|
-
message: 'no idle reachable contexts detected; will provision k3d cluster',
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
// --yes mode: backward compat — default to NO reuse; print informational hint.
|
|
432
|
-
if (opts.yes) {
|
|
433
|
-
process.stdout.write(` Detected ${offerable.length} existing Kubernetes context(s): ${offerable.join(', ')}. `
|
|
434
|
-
+ `To reuse one, pass --reuse-cluster=<name>. Provisioning k3d (--yes default).\n`);
|
|
435
|
-
return {
|
|
436
|
-
ok: true,
|
|
437
|
-
skipped: true,
|
|
438
|
-
message: `idle context(s) available but --yes defaults to k3d provision; use --reuse-cluster=<name> to opt in`,
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
// Interactive: prompt for each offerable context.
|
|
442
|
-
const promptFn = deps.prompt ?? defaultPrompt;
|
|
443
|
-
for (const ctx of offerable) {
|
|
444
|
-
const reuse = await promptFn(`Detected existing Kubernetes context \`${ctx}\`. Use this cluster instead of provisioning a new k3d cluster?`, false);
|
|
445
|
-
if (reuse) {
|
|
446
|
-
return {
|
|
447
|
-
ok: true,
|
|
448
|
-
message: `operator chose to reuse context ${ctx}`,
|
|
449
|
-
reuseContext: ctx,
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
return {
|
|
454
|
-
ok: true,
|
|
455
|
-
skipped: true,
|
|
456
|
-
message: 'operator declined reuse; will provision k3d cluster',
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
async function phase1SystemCheck(substrate, deps) {
|
|
460
|
-
const nodeVersion = deps.nodeVersion ?? process.version;
|
|
461
|
-
const nodeMajor = parseNodeMajor(nodeVersion);
|
|
462
|
-
const nodeOk = nodeMajor !== null && nodeMajor >= REQUIRED_NODE_MAJOR;
|
|
463
|
-
if (substrate === 'kubernetes') {
|
|
464
|
-
// kubectl is required on all platforms.
|
|
465
|
-
const kubectlProbe = await probeKubectl(deps.dockerExec);
|
|
466
|
-
if (!kubectlProbe.ok) {
|
|
467
|
-
return phaseFromProbe(kubectlProbe);
|
|
468
|
-
}
|
|
469
|
-
// docker is only required when the cluster is k3d-managed (k3d runs its node
|
|
470
|
-
// containers on the operator's local docker daemon). External kubernetes clusters
|
|
471
|
-
// (K3s-on-Lima, Kind on a remote VM, GKE, AKS, kubeadm, etc.) reach the
|
|
472
|
-
// apiserver directly via kubectl and don't need a local docker daemon.
|
|
473
|
-
//
|
|
474
|
-
// Heuristic: kubectl context names that START with `k3d-` are k3d-managed
|
|
475
|
-
// (e.g. `k3d-olam-dev`, `k3d-olam-host`). Anything else (`lima-k3s`,
|
|
476
|
-
// `kind-foo`, `gke_proj_region_cluster`, custom names) is treated as external
|
|
477
|
-
// — docker is optional.
|
|
478
|
-
const ctx = resolveKubectlContext(deps.configPath);
|
|
479
|
-
const isK3dManaged = ctx.context?.startsWith('k3d-') ?? false;
|
|
480
|
-
if (isK3dManaged) {
|
|
481
|
-
const dockerProbe = await probeDockerDaemon(deps.dockerExec);
|
|
482
|
-
if (!dockerProbe.ok) {
|
|
483
|
-
return {
|
|
484
|
-
ok: false,
|
|
485
|
-
message: 'docker daemon required for k3d-managed cluster: ' + dockerProbe.message,
|
|
486
|
-
remedy: dockerProbe.remedy,
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
else if (ctx.context !== undefined) {
|
|
491
|
-
// Surface that we deliberately skipped the docker check so the operator
|
|
492
|
-
// sees the decision in the phase log.
|
|
493
|
-
process.stdout.write(` ℹ skipped docker check — kubectl context "${ctx.context}" is not k3d-managed\n`);
|
|
494
|
-
}
|
|
495
|
-
// If ctx.context is undefined (no context pinned yet), the kubectlProbe above
|
|
496
|
-
// already confirms kubectl is present; the cluster-provision phases that follow
|
|
497
|
-
// will surface the missing context error — don't double-fail here.
|
|
498
|
-
if (!nodeOk) {
|
|
499
|
-
return {
|
|
500
|
-
ok: false,
|
|
501
|
-
message: `Node.js ${nodeVersion} is too old (need ≥${REQUIRED_NODE_MAJOR})`,
|
|
502
|
-
remedy: `Install Node.js ${REQUIRED_NODE_MAJOR}+ LTS via nvm/fnm/asdf and re-run \`olam setup\`.`,
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
|
-
// ADR 021 Phase 1 Colima lint: warn when Colima has kubernetes.enabled:true
|
|
506
|
-
// on macOS. This causes k3d to conflict on the same Lima VM ports.
|
|
507
|
-
// Warning only — operator may be using --reuse-cluster=colima intentionally.
|
|
508
|
-
const platform = String(deps.osPlatform ?? process.platform);
|
|
509
|
-
const home = deps.home ?? homedir();
|
|
510
|
-
const colimaLint = probeColimaKubernetesEnabled({ platform, home });
|
|
511
|
-
if (colimaLint.ok && 'warn' in colimaLint && colimaLint.warn === true) {
|
|
512
|
-
const lintWithWarn = colimaLint;
|
|
513
|
-
printWarning(` ⚠ ${lintWithWarn.remedy}`);
|
|
514
|
-
}
|
|
515
|
-
const dockerNote = isK3dManaged ? '; docker ready' : '';
|
|
516
|
-
return { ok: true, message: `kubectl on PATH${dockerNote}; node ${nodeVersion}` };
|
|
517
|
-
}
|
|
518
|
-
// Docker substrate (default)
|
|
519
|
-
const dockerProbe = await probeDockerDaemon(deps.dockerExec);
|
|
520
|
-
if (!dockerProbe.ok) {
|
|
521
|
-
return phaseFromProbe(dockerProbe);
|
|
522
|
-
}
|
|
523
|
-
// Verify docker compose v2 plugin. Linux operators who installed docker.io
|
|
524
|
-
// (or via `brew install docker` on macOS) without the compose plugin will
|
|
525
|
-
// hit cryptic "unknown command" errors later; fail early with a clear remedy.
|
|
526
|
-
const composeProbe = await probeComposePlugin(deps.dockerExec);
|
|
527
|
-
if (!composeProbe.ok) {
|
|
528
|
-
return phaseFromProbe(composeProbe);
|
|
529
|
-
}
|
|
530
|
-
if (!nodeOk) {
|
|
531
|
-
return {
|
|
532
|
-
ok: false,
|
|
533
|
-
message: `Node.js ${nodeVersion} is too old (need ≥${REQUIRED_NODE_MAJOR})`,
|
|
534
|
-
remedy: `Install Node.js ${REQUIRED_NODE_MAJOR}+ LTS via nvm/fnm/asdf and re-run \`olam setup\`.`,
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
return {
|
|
538
|
-
ok: true,
|
|
539
|
-
message: `${dockerProbe.message}; ${composeProbe.message}; node ${nodeVersion}`,
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* Phase 1.5 — Install missing substrate tools (idempotent).
|
|
544
|
-
*
|
|
545
|
-
* Docker: no-op.
|
|
546
|
-
* Kubernetes (all platforms): installs k3d via brew when available, else the
|
|
547
|
-
* upstream install script. k3d works on both macOS and Linux — no sudo needed
|
|
548
|
-
* (k3d only requires docker, which Phase 1 already confirmed).
|
|
549
|
-
*
|
|
550
|
-
* @param reuseContext - when set (ADR 021 Phase 0.5), skip k3d install
|
|
551
|
-
*/
|
|
552
|
-
async function phase1_5InstallSubstrate(substrate, opts, deps, reuseContext) {
|
|
553
|
-
if (substrate === 'docker') {
|
|
554
|
-
return { ok: true, skipped: true, message: 'no-op for docker substrate' };
|
|
555
|
-
}
|
|
556
|
-
// ADR 021: when reusing an existing context, k3d install is not needed.
|
|
557
|
-
if (reuseContext) {
|
|
558
|
-
return {
|
|
559
|
-
ok: true,
|
|
560
|
-
skipped: true,
|
|
561
|
-
message: `skipped k3d install (reusing context ${reuseContext})`,
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
// k3d only runs on k3d-managed clusters (context name starts with `k3d-`).
|
|
565
|
-
// External clusters (lima-k3s, kind-*, gke_*, custom names) already have their
|
|
566
|
-
// own k8s distribution installed — k3d is irrelevant and would be misleading to
|
|
567
|
-
// install. Mirror the same heuristic used by phase1SystemCheck for consistency.
|
|
568
|
-
const ctx = resolveKubectlContext(deps.configPath);
|
|
569
|
-
const isK3dManaged = ctx.context?.startsWith('k3d-') ?? false;
|
|
570
|
-
if (!isK3dManaged && ctx.context !== undefined) {
|
|
571
|
-
return {
|
|
572
|
-
ok: true,
|
|
573
|
-
skipped: true,
|
|
574
|
-
message: `skipped k3d install — kubectl context "${ctx.context}" is not k3d-managed`,
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
578
|
-
const promptFn = deps.prompt ?? defaultPrompt;
|
|
579
|
-
// k3d works on both darwin and linux; one path for both.
|
|
580
|
-
// Requires docker daemon (Phase 1 already checks this).
|
|
581
|
-
const k3dProbe = await probeK3d(deps.dockerExec);
|
|
582
|
-
if (k3dProbe.ok) {
|
|
583
|
-
return { ok: true, message: `k3d already present: ${k3dProbe.message}` };
|
|
584
|
-
}
|
|
585
|
-
// Determine installer: brew when available (common on macOS, sometimes on Linux),
|
|
586
|
-
// else upstream install script (no sudo needed).
|
|
587
|
-
const hasBrew = spawnSync('command', ['-v', 'brew'], { shell: true, stdio: 'pipe' }).status === 0;
|
|
588
|
-
const useBrewMsg = hasBrew ? 'Homebrew' : 'upstream install script';
|
|
589
|
-
if (!opts.yes) {
|
|
590
|
-
const confirmed = await promptFn(`k3d is not installed. Install via ${useBrewMsg}?`, true);
|
|
591
|
-
if (!confirmed) {
|
|
592
|
-
return {
|
|
593
|
-
ok: false,
|
|
594
|
-
message: 'k3d install declined; required for kubernetes substrate',
|
|
595
|
-
remedy: 'Install manually: `brew install k3d` or curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash, '
|
|
596
|
-
+ 'then re-run `olam setup --substrate=kubernetes`.',
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
if (hasBrew) {
|
|
601
|
-
process.stdout.write('Installing k3d via Homebrew...\n');
|
|
602
|
-
const r = await spawnFn('brew', ['install', 'k3d']);
|
|
603
|
-
if (r.status !== 0) {
|
|
604
|
-
return {
|
|
605
|
-
ok: false,
|
|
606
|
-
message: `brew install k3d failed (exit ${r.status ?? 'signal'})`,
|
|
607
|
-
remedy: 'Try manually: `brew install k3d` or curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash',
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
process.stdout.write('Installing k3d via upstream install script...\n');
|
|
613
|
-
const r = await spawnFn('bash', [
|
|
614
|
-
'-c',
|
|
615
|
-
'curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash',
|
|
616
|
-
]);
|
|
617
|
-
if (r.status !== 0) {
|
|
618
|
-
return {
|
|
619
|
-
ok: false,
|
|
620
|
-
message: `k3d upstream install failed (exit ${r.status ?? 'signal'})`,
|
|
621
|
-
remedy: 'Install manually: https://k3d.io/v5.x/installation/',
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
// Verify k3d is now on PATH
|
|
626
|
-
const k3dCheck = await probeK3d(deps.dockerExec);
|
|
627
|
-
if (!k3dCheck.ok) {
|
|
628
|
-
return {
|
|
629
|
-
ok: false,
|
|
630
|
-
message: 'k3d still not on PATH after install — shell PATH may need updating',
|
|
631
|
-
remedy: 'Close and re-open your terminal, then re-run `olam setup --substrate=kubernetes`.',
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
return { ok: true, message: `k3d installed: ${k3dCheck.message}` };
|
|
635
|
-
}
|
|
636
|
-
function parseNodeMajor(version) {
|
|
637
|
-
const m = version.match(/^v?(\d+)\./);
|
|
638
|
-
if (!m)
|
|
639
|
-
return null;
|
|
640
|
-
const n = Number.parseInt(m[1], 10);
|
|
641
|
-
return Number.isFinite(n) ? n : null;
|
|
642
|
-
}
|
|
643
|
-
function phaseFromProbe(probe) {
|
|
644
|
-
if (probe.ok)
|
|
645
|
-
return { ok: true, message: probe.message };
|
|
646
|
-
return { ok: false, message: probe.message, remedy: probe.remedy };
|
|
647
|
-
}
|
|
648
|
-
/**
|
|
649
|
-
* Phase 2.5 — Provision k3d cluster (all platforms).
|
|
650
|
-
* No-op for docker substrate.
|
|
651
|
-
* Idempotent: if the cluster already exists, logs and skips.
|
|
652
|
-
* k3d updates ~/.kube/config automatically — no kubeconfig juggling needed.
|
|
653
|
-
*
|
|
654
|
-
* @param clusterName - resolved cluster name (default: SETUP_K3D_CLUSTER_NAME)
|
|
655
|
-
* @param reuseContext - when set (ADR 021 Phase 0.5), skip cluster provision
|
|
656
|
-
*/
|
|
657
|
-
async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reuseContext) {
|
|
658
|
-
if (substrate === 'docker') {
|
|
659
|
-
return { ok: true, skipped: true, message: 'no-op for docker substrate' };
|
|
660
|
-
}
|
|
661
|
-
// ADR 021: when reusing an existing context, k3d cluster provision is skipped.
|
|
662
|
-
if (reuseContext) {
|
|
663
|
-
return {
|
|
664
|
-
ok: true,
|
|
665
|
-
skipped: true,
|
|
666
|
-
message: `skipped k3d cluster provision (reusing context ${reuseContext})`,
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
670
|
-
// k3d cluster create <clusterName> (idempotent — same on macOS and Linux)
|
|
671
|
-
// Check if cluster already exists
|
|
672
|
-
const listResult = await captureSpawn('k3d', ['cluster', 'list', '--output', 'json'], deps.dockerExec);
|
|
673
|
-
if (listResult.ok) {
|
|
674
|
-
const exists = clusterExistsInList(listResult.stdout, clusterName);
|
|
675
|
-
if (exists) {
|
|
676
|
-
return {
|
|
677
|
-
ok: true,
|
|
678
|
-
message: `cluster ${clusterName} already exists; skipping create`,
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
process.stdout.write(`Creating k3d cluster ${clusterName}...\n`);
|
|
683
|
-
// Build --volume binds. Two hostPaths in host-cp's deployment resolve to
|
|
684
|
-
// paths inside the k3d node:
|
|
685
|
-
// 1. /host/.config/gh ← gh CLI config (optional; only bound when the
|
|
686
|
-
// host dir exists so fresh machines don't break)
|
|
687
|
-
// 2. /host/olam ← operator's olam source checkout (DEV ONLY;
|
|
688
|
-
// opt-in via --host-cp-dev-path). Published-CLI
|
|
689
|
-
// consumers MUST NOT bind this — they don't
|
|
690
|
-
// have an olam checkout and host-cp degrades
|
|
691
|
-
// gracefully without it (version-status reports
|
|
692
|
-
// 'unknown'; /api/prs runs in empty cwd).
|
|
693
|
-
const volumes = [];
|
|
694
|
-
const ghConfigDir = `${homedir()}/.config/gh`;
|
|
695
|
-
if (existsSync(ghConfigDir)) {
|
|
696
|
-
volumes.push('--volume', `${ghConfigDir}:/host/.config/gh`);
|
|
697
|
-
}
|
|
698
|
-
else {
|
|
699
|
-
process.stdout.write(` note: ${ghConfigDir} does not exist; skipping gh-config bind. ` +
|
|
700
|
-
`Run \`gh auth login\` to enable in-world GitHub features.\n`);
|
|
701
|
-
}
|
|
702
|
-
if (opts.hostCpDevPath) {
|
|
703
|
-
if (!existsSync(opts.hostCpDevPath)) {
|
|
704
|
-
return {
|
|
705
|
-
ok: false,
|
|
706
|
-
message: `--host-cp-dev-path ${opts.hostCpDevPath} does not exist`,
|
|
707
|
-
remedy: `Provide an absolute path to a local olam source checkout, or omit --host-cp-dev-path to use the published image.`,
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
volumes.push('--volume', `${opts.hostCpDevPath}:/host/olam`);
|
|
711
|
-
process.stdout.write(` dev-mode: mounting ${opts.hostCpDevPath} → /host/olam (host-cp will read live source)\n`);
|
|
712
|
-
}
|
|
713
|
-
// --port flags map Traefik's loadbalancer ports (80/443 inside the cluster)
|
|
714
|
-
// to host ports 8080/8443. Without these, the SPA at https://olam.local is
|
|
715
|
-
// only reachable via `kubectl port-forward svc/traefik 8443:443` — a manual
|
|
716
|
-
// step that has to stay running. With them, `https://olam.local:8443` works
|
|
717
|
-
// out of the box. k3d does NOT support adding port flags to an existing
|
|
718
|
-
// cluster (k3d-io/k3d#1147), so this only takes effect for fresh clusters;
|
|
719
|
-
// operators on pre-existing clusters need to `k3d cluster delete <name>` and
|
|
720
|
-
// re-run setup. The runbook (docs/runbooks/k3d-https-setup.md) covers it.
|
|
721
|
-
const createArgs = [
|
|
722
|
-
'cluster', 'create', clusterName,
|
|
723
|
-
...volumes,
|
|
724
|
-
'--port', '8443:443@loadbalancer',
|
|
725
|
-
'--port', '8080:80@loadbalancer',
|
|
726
|
-
'--wait', '--timeout', '90s',
|
|
727
|
-
];
|
|
728
|
-
const createResult = await spawnFn('k3d', createArgs);
|
|
729
|
-
if (createResult.status !== 0) {
|
|
730
|
-
return {
|
|
731
|
-
ok: false,
|
|
732
|
-
message: `k3d cluster create ${clusterName} failed (exit ${createResult.status ?? 'signal'})`,
|
|
733
|
-
remedy: `Run manually: k3d ${createArgs.join(' ')}`,
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
// Verify kubectl can reach it (k3d updates ~/.kube/config automatically)
|
|
737
|
-
const ctxResult = captureSpawnSync('kubectl', ['config', 'current-context']);
|
|
738
|
-
const ctx = ctxResult.ok ? ctxResult.stdout.trim() : '(unknown)';
|
|
739
|
-
return { ok: true, message: `cluster ${clusterName} created; context: ${ctx}` };
|
|
740
|
-
}
|
|
741
|
-
/** Capture-only spawn via dockerExec (no subprocess) for list/query operations. */
|
|
742
|
-
async function captureSpawn(cmd, args, dockerExec) {
|
|
743
|
-
const exec = dockerExec ?? ((c, a) => {
|
|
744
|
-
const r = spawnSync(c, [...a], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
745
|
-
return { status: r.status, stdout: r.stdout ?? '', stderr: r.stderr ?? '' };
|
|
746
|
-
});
|
|
747
|
-
const r = exec(cmd, args);
|
|
748
|
-
return { ok: r.status === 0, stdout: r.stdout, stderr: r.stderr };
|
|
749
|
-
}
|
|
750
|
-
/** Synchronous capture spawn used for non-critical reads (cluster context). */
|
|
751
|
-
function captureSpawnSync(cmd, args) {
|
|
752
|
-
const r = spawnSync(cmd, [...args], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
753
|
-
return { ok: r.status === 0, stdout: r.stdout ?? '' };
|
|
754
|
-
}
|
|
755
|
-
/** Parse k3d cluster list JSON and return true if clusterName is present. */
|
|
756
|
-
function clusterExistsInList(json, clusterName) {
|
|
757
|
-
try {
|
|
758
|
-
const parsed = JSON.parse(json);
|
|
759
|
-
return Array.isArray(parsed) && parsed.some((c) => c.name === clusterName);
|
|
760
|
-
}
|
|
761
|
-
catch {
|
|
762
|
-
return false;
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
async function phase2CliSanity(deps) {
|
|
766
|
-
// CRITICAL fix (Phase C CP3): readCliVersion() is the canonical
|
|
767
|
-
// source (same helper `index.ts:55` uses for `--version`). The
|
|
768
|
-
// OLAM_CLI_VERSION env var is only assigned INSIDE the host-cp
|
|
769
|
-
// container (host-cp.ts:423); it is NEVER set in the operator's
|
|
770
|
-
// host process — relying on it would make Phase 2 fail for every
|
|
771
|
-
// operator on Day 1.
|
|
772
|
-
const version = deps.olamCliVersion ?? safeReadCliVersion();
|
|
773
|
-
if (!version || version === 'unknown') {
|
|
774
|
-
return {
|
|
775
|
-
ok: false,
|
|
776
|
-
message: 'olam CLI version not detectable',
|
|
777
|
-
remedy: 'Re-install `olam` via `npm install -g @pleri/olam-cli@stable` and re-run.',
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
// Migrate any secrets still living at ~/.olam/<name> → ~/.olam/secrets/<name>.
|
|
781
|
-
// Idempotent: no-op when the new path already exists or the old path is absent.
|
|
782
|
-
for (const name of KNOWN_SECRET_NAMES) {
|
|
783
|
-
migrateSecretIfNeeded(name);
|
|
784
|
-
}
|
|
785
|
-
return { ok: true, message: `olam ${version}` };
|
|
786
|
-
}
|
|
787
|
-
function safeReadCliVersion() {
|
|
788
|
-
try {
|
|
789
|
-
return readCliVersion();
|
|
790
|
-
}
|
|
791
|
-
catch {
|
|
792
|
-
return null;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
/**
|
|
796
|
-
* Phase 2.6 — Pin kubectl context after k3d cluster creation (or context reuse).
|
|
797
|
-
* No-op for docker substrate.
|
|
798
|
-
*
|
|
799
|
-
* `olam upgrade` (called by bootstrap step 6/6) requires
|
|
800
|
-
* host.kubectl_context_pinned in ~/.olam/config.json. On the kubernetes
|
|
801
|
-
* substrate, Phase 2.5 creates the cluster (context = k3d-<cluster>),
|
|
802
|
-
* but the standard `olam init` that writes this field runs in Phase 5
|
|
803
|
-
* (AFTER bootstrap). This phase bridges the gap: it pins the context
|
|
804
|
-
* immediately after cluster creation so bootstrap/upgrade can proceed.
|
|
805
|
-
*
|
|
806
|
-
* When reuseContext is set (ADR 021), pins to the reused context name
|
|
807
|
-
* instead of the k3d-derived context name.
|
|
808
|
-
*
|
|
809
|
-
* Idempotent: applyKubectlContextPin skips when the field is already set.
|
|
810
|
-
*
|
|
811
|
-
* @param clusterName - resolved cluster name (default: SETUP_K3D_CLUSTER_NAME)
|
|
812
|
-
* @param reuseContext - when set (ADR 021 Phase 0.5), pin to this context name
|
|
813
|
-
*/
|
|
814
|
-
async function phase2_6PinKubectlContext(substrate, clusterName, deps, reuseContext) {
|
|
815
|
-
if (substrate !== 'kubernetes') {
|
|
816
|
-
return { ok: true, skipped: true, message: 'no-op for docker substrate' };
|
|
817
|
-
}
|
|
818
|
-
// ADR 021: reused context uses the context name directly (not k3d-prefixed).
|
|
819
|
-
// k3d names the context `k3d-<cluster-name>`; reused contexts use their own name.
|
|
820
|
-
const expectedContext = reuseContext ?? `k3d-${clusterName}`;
|
|
821
|
-
// Ensure ~/.olam/config.json exists with a valid schema before patching
|
|
822
|
-
// kubectl_context_pinned. applyKubectlContextPin preserves existing keys but
|
|
823
|
-
// starts from `{}` when the file is absent — that produces an invalid schema
|
|
824
|
-
// (`readConfig` warns and falls back to defaults, losing kubectl_context_pinned).
|
|
825
|
-
// writeConfig reads current config (or creates a valid default) and writes a
|
|
826
|
-
// schema-conformant file. The subsequent applyKubectlContextPin will then
|
|
827
|
-
// patch kubectl_context_pinned on top of that valid foundation.
|
|
828
|
-
writeConfig({ host: { substrate: 'kubernetes' } }, { configPath: deps.configPath });
|
|
829
|
-
const result = applyKubectlContextPin([expectedContext], {
|
|
830
|
-
configPath: deps.configPath,
|
|
831
|
-
});
|
|
832
|
-
if ('pinned' in result) {
|
|
833
|
-
return { ok: true, message: `kubectl context pinned: ${result.pinned}` };
|
|
834
|
-
}
|
|
835
|
-
if ('skipped' in result) {
|
|
836
|
-
return { ok: true, message: `kubectl context already pinned (${result.skipped})` };
|
|
837
|
-
}
|
|
838
|
-
// 'refused' — multiple contexts (should not happen since we pass exactly one)
|
|
839
|
-
return {
|
|
840
|
-
ok: false,
|
|
841
|
-
message: `kubectl context pin refused: ${result.refused}`,
|
|
842
|
-
remedy: `Set host.kubectl_context_pinned = ${expectedContext} in ~/.olam/config.json and re-run.`,
|
|
843
|
-
};
|
|
844
|
-
}
|
|
845
|
-
async function phase3Bootstrap(substrate, deps, opts) {
|
|
846
|
-
// HIGH fix (Phase C CP3): pass --skip-auth-login. `olam bootstrap`
|
|
847
|
-
// step 6 (bootstrap.ts:499-520) runs PKCE interactively by default.
|
|
848
|
-
// Phase 6 owns the operator-facing auth UX (with non-fatal recovery);
|
|
849
|
-
// letting bootstrap run auth too means double-prompt + collapses
|
|
850
|
-
// Phase 6's recovery affordance when auth fails during bootstrap.
|
|
851
|
-
//
|
|
852
|
-
// Substrate-aware: the bootstrap command reads ~/.olam/config.json for
|
|
853
|
-
// substrate dispatch. For kubernetes substrate we additionally pass
|
|
854
|
-
// --skip-cluster-create (Phase 2.5 already created it) and
|
|
855
|
-
// --skip-observability is NOT passed — bootstrap still installs observability.
|
|
856
|
-
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
857
|
-
const bootstrapArgs = ['bootstrap', '--skip-auth-login'];
|
|
858
|
-
if (substrate === 'kubernetes') {
|
|
859
|
-
// Cluster was already created by Phase 2.5; bootstrap's preflight
|
|
860
|
-
// and cluster-create steps should skip.
|
|
861
|
-
bootstrapArgs.push('--skip-cluster-create');
|
|
862
|
-
}
|
|
863
|
-
// Forward --host-cp-dev-path so direct `olam bootstrap` callers and
|
|
864
|
-
// operators who pass it through `olam setup` get consistent behavior.
|
|
865
|
-
// Phase 2.5 already consumes this for k3d cluster create; bootstrap
|
|
866
|
-
// still threads it for symmetry with the standalone bootstrap path.
|
|
867
|
-
if (substrate === 'kubernetes' && opts.hostCpDevPath) {
|
|
868
|
-
bootstrapArgs.push('--host-cp-dev-path', opts.hostCpDevPath);
|
|
869
|
-
}
|
|
870
|
-
// Forward output + pre-pull preferences to the k3s bootstrap subprocess.
|
|
871
|
-
if (substrate === 'kubernetes' && opts.verbose) {
|
|
872
|
-
bootstrapArgs.push('--verbose');
|
|
873
|
-
}
|
|
874
|
-
if (substrate === 'kubernetes' && opts.skipPrepull) {
|
|
875
|
-
bootstrapArgs.push('--skip-prepull');
|
|
876
|
-
}
|
|
877
|
-
const r = await spawnFn('olam', bootstrapArgs);
|
|
878
|
-
if (r.status === 0) {
|
|
879
|
-
return { ok: true, message: `olam bootstrap succeeded (substrate: ${substrate})` };
|
|
880
|
-
}
|
|
881
|
-
return {
|
|
882
|
-
ok: false,
|
|
883
|
-
message: `olam bootstrap exited ${r.status}`,
|
|
884
|
-
remedy: 'Re-run `olam setup` after inspecting the bootstrap error above (bootstrap is idempotent).',
|
|
885
|
-
};
|
|
886
|
-
}
|
|
887
|
-
export async function phase3_5K3dHttpsBootstrap(substrate, opts, _deps) {
|
|
888
|
-
if (opts.skipHttpsBootstrap) {
|
|
889
|
-
return { ok: true, skipped: true, message: 'skipped via --skip-https-bootstrap' };
|
|
890
|
-
}
|
|
891
|
-
if (substrate !== 'kubernetes') {
|
|
892
|
-
return { ok: true, skipped: true, message: 'no-op for docker substrate' };
|
|
893
|
-
}
|
|
894
|
-
// Probe for mkcert on PATH; offer to install via brew if absent on macOS.
|
|
895
|
-
const spawnFn = spawnSync;
|
|
896
|
-
const whichResult = spawnFn('which', ['mkcert'], { encoding: 'utf-8' });
|
|
897
|
-
const mkcertOnPath = whichResult.status === 0 && whichResult.stdout.trim().length > 0;
|
|
898
|
-
if (!mkcertOnPath) {
|
|
899
|
-
// Check whether brew is available.
|
|
900
|
-
const brewResult = spawnFn('which', ['brew'], { encoding: 'utf-8' });
|
|
901
|
-
const brewAvailable = brewResult.status === 0 && brewResult.stdout.trim().length > 0;
|
|
902
|
-
if (!brewAvailable) {
|
|
903
|
-
return {
|
|
904
|
-
ok: true,
|
|
905
|
-
skipped: true,
|
|
906
|
-
message: 'mkcert not installed and brew not available; SPA accessible via port-forward (HTTP/1.1 only). '
|
|
907
|
-
+ 'See docs/runbooks/k3d-https-setup.md for manual install instructions.',
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
if (!opts.yes) {
|
|
911
|
-
return {
|
|
912
|
-
ok: true,
|
|
913
|
-
skipped: true,
|
|
914
|
-
message: 'mkcert not installed; run `brew install mkcert nss` then re-run `olam setup` '
|
|
915
|
-
+ '(or `olam services tls-install`) to enable HTTPS. '
|
|
916
|
-
+ 'SPA still accessible via port-forward (HTTP/1.1 only). '
|
|
917
|
-
+ 'Use --yes to auto-install or --skip-https-bootstrap to skip permanently.',
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
// --yes is set: install mkcert via brew. stdio:'inherit' so the operator
|
|
921
|
-
// sees brew's download/install progress (otherwise it appears to hang for
|
|
922
|
-
// 30-90s on a fresh mac). Matches the Phase 1.5 k3d-install pattern.
|
|
923
|
-
process.stdout.write('Installing mkcert + nss via Homebrew (Firefox cert trust)...\n');
|
|
924
|
-
const brewInstall = spawnFn('brew', ['install', 'mkcert', 'nss'], { stdio: 'inherit' });
|
|
925
|
-
if (brewInstall.status !== 0) {
|
|
926
|
-
return {
|
|
927
|
-
ok: true,
|
|
928
|
-
skipped: true,
|
|
929
|
-
message: `brew install mkcert nss exited ${brewInstall.status}; `
|
|
930
|
-
+ 'SPA accessible via port-forward (HTTP/1.1 only). '
|
|
931
|
-
+ 'Install mkcert manually and re-run `olam services tls-install`.',
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
// mkcert is (now) available — provision the TLS Secret.
|
|
936
|
-
const result = await ensureTlsInstalled();
|
|
937
|
-
// Check /etc/hosts for olam.local.
|
|
938
|
-
let hostsWarning = '';
|
|
939
|
-
try {
|
|
940
|
-
const hostsBody = readFileSync('/etc/hosts', 'utf-8');
|
|
941
|
-
if (!/^[^#\n]*\bolam\.local\b/m.test(hostsBody)) {
|
|
942
|
-
hostsWarning =
|
|
943
|
-
" Add to /etc/hosts: echo '127.0.0.1 olam.local' | sudo tee -a /etc/hosts";
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
catch {
|
|
947
|
-
// /etc/hosts unreadable — skip the check silently.
|
|
948
|
-
}
|
|
949
|
-
if (result.action === 'installed' || result.action === 'renewed') {
|
|
950
|
-
const urlPart = result.httpsPort !== undefined
|
|
951
|
-
? ` SPA at https://olam.local:${result.httpsPort}.`
|
|
952
|
-
: '';
|
|
953
|
-
return {
|
|
954
|
-
ok: true,
|
|
955
|
-
message: `TLS cert ${result.action} at ${result.action === 'installed' ? 'olam-host-cp-tls' : 'olam-host-cp-tls (renewed)'};${urlPart}${hostsWarning}`,
|
|
956
|
-
};
|
|
957
|
-
}
|
|
958
|
-
if (result.action === 'skipped') {
|
|
959
|
-
return { ok: true, message: `TLS already provisioned (skipped).${hostsWarning}` };
|
|
960
|
-
}
|
|
961
|
-
// action === 'failed' — non-fatal: port-forward fallback still works.
|
|
962
|
-
return {
|
|
963
|
-
ok: true,
|
|
964
|
-
skipped: true,
|
|
965
|
-
message: `TLS install failed (non-fatal): ${result.reason ?? 'unknown error'}. `
|
|
966
|
-
+ 'SPA still accessible via port-forward (HTTP/1.1 only). '
|
|
967
|
-
+ 'Re-run `olam services tls-install` after fixing the issue.',
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
async function phase4ShellInit(opts, deps) {
|
|
971
|
-
if (opts.skipShellInit) {
|
|
972
|
-
return { ok: true, skipped: true, message: 'skipped via --skip-shell-init' };
|
|
973
|
-
}
|
|
974
|
-
const home = deps.home ?? homedir();
|
|
975
|
-
const shellEnv = deps.shellEnv ?? process.env.SHELL;
|
|
976
|
-
const rcPath = resolveShellRc(home, shellEnv);
|
|
977
|
-
if (rcPath === null) {
|
|
978
|
-
return {
|
|
979
|
-
ok: true,
|
|
980
|
-
skipped: true,
|
|
981
|
-
message: `unsupported $SHELL (${shellEnv ?? 'unset'}); add \`eval "$(olam completion <shell>)"\` to your shell rc manually`,
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
const shellBasename = path.basename(shellEnv);
|
|
985
|
-
const evalLine = `eval "$(olam completion ${shellBasename})"`;
|
|
986
|
-
const result = appendIdempotent({
|
|
987
|
-
rcPath,
|
|
988
|
-
marker: 'olam completion',
|
|
989
|
-
contentLine: evalLine,
|
|
990
|
-
clock: deps.clock,
|
|
991
|
-
});
|
|
992
|
-
if (result.status === 'no-rc-file') {
|
|
993
|
-
return {
|
|
994
|
-
ok: true,
|
|
995
|
-
skipped: true,
|
|
996
|
-
message: `${rcPath} not present; skipped (add \`${evalLine}\` to your shell rc manually)`,
|
|
997
|
-
};
|
|
998
|
-
}
|
|
999
|
-
if (result.status === 'already-present') {
|
|
1000
|
-
return { ok: true, message: `${rcPath}: already configured (no change)` };
|
|
1001
|
-
}
|
|
1002
|
-
return {
|
|
1003
|
-
ok: true,
|
|
1004
|
-
message: `${rcPath}: appended (backup: ${result.backupPath})`,
|
|
1005
|
-
};
|
|
1006
|
-
}
|
|
1007
|
-
async function phase5InitProject(opts, deps) {
|
|
1008
|
-
// Phase 5: Init GLOBAL config — ensure ~/.olam/config.json has host.substrate set.
|
|
1009
|
-
// Per-repo config (.olam/config.yaml) is `olam repos` territory; setup must not
|
|
1010
|
-
// walk up to .git and write per-repo config. See CLAUDE.md: "Olam init should be
|
|
1011
|
-
// GLOBAL on install, not repo-specific."
|
|
1012
|
-
const globalConfigPath = deps.configPath ?? OLAM_CONFIG_PATH;
|
|
1013
|
-
const result = runGlobalInit({ configPath: globalConfigPath });
|
|
1014
|
-
if (!result.ok) {
|
|
1015
|
-
return {
|
|
1016
|
-
ok: false,
|
|
1017
|
-
message: result.message,
|
|
1018
|
-
remedy: 'Inspect the error above and re-run `olam setup`, or run `olam init --global` manually.',
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
if (result.alreadySet) {
|
|
1022
|
-
return { ok: true, message: 'already initialised globally (no change)' };
|
|
1023
|
-
}
|
|
1024
|
-
return { ok: true, message: result.message };
|
|
1025
|
-
}
|
|
1026
|
-
async function phase5aSkillSource(opts, deps) {
|
|
1027
|
-
if (opts.skipSkillSource) {
|
|
1028
|
-
return { ok: true, skipped: true, message: 'skipped via --skip-skill-source' };
|
|
1029
|
-
}
|
|
1030
|
-
// Run unconditionally. pickSkillSourcePhase auto-detects existing skill sources
|
|
1031
|
-
// (skips silently when ≥1 are registered) and handles the interactive TUI,
|
|
1032
|
-
// non-interactive --skill-source flag, and non-TTY fallback internally.
|
|
1033
|
-
// Use --skip-skill-source to opt out entirely (headless CI, manual setup later).
|
|
1034
|
-
return pickSkillSourcePhase(opts, deps);
|
|
1035
|
-
}
|
|
1036
|
-
async function phase5bProjectSweep(opts, deps) {
|
|
1037
|
-
return runProjectSweepPhase(opts, deps);
|
|
1038
|
-
}
|
|
1039
|
-
async function phase6Auth(opts, deps) {
|
|
1040
|
-
if (opts.skipAuth) {
|
|
1041
|
-
return {
|
|
1042
|
-
ok: true,
|
|
1043
|
-
skipped: true,
|
|
1044
|
-
message: 'skipped via --skip-auth (run `olam auth login` later)',
|
|
1045
|
-
};
|
|
1046
|
-
}
|
|
1047
|
-
const promptFn = deps.prompt ?? defaultPrompt;
|
|
1048
|
-
const shouldLaunch = opts.yes
|
|
1049
|
-
? true
|
|
1050
|
-
: await promptFn('`olam auth login` is interactive (PKCE browser flow, 5 min timeout). Launch now?', false);
|
|
1051
|
-
if (!shouldLaunch) {
|
|
1052
|
-
return {
|
|
1053
|
-
ok: true,
|
|
1054
|
-
skipped: true,
|
|
1055
|
-
message: 'declined; run `olam auth login` later when ready',
|
|
1056
|
-
};
|
|
1057
|
-
}
|
|
1058
|
-
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
1059
|
-
const r = await spawnFn('olam', ['auth', 'login']);
|
|
1060
|
-
if (r.status === 0) {
|
|
1061
|
-
return { ok: true, message: 'olam auth login succeeded' };
|
|
1062
|
-
}
|
|
1063
|
-
// Auth login failure is recoverable + operator-driven; don't fail the phase
|
|
1064
|
-
return {
|
|
1065
|
-
ok: true,
|
|
1066
|
-
skipped: true,
|
|
1067
|
-
message: `olam auth login exited ${r.status}; re-run \`olam auth login\` after resolving`,
|
|
1068
|
-
};
|
|
1069
|
-
}
|
|
1070
|
-
async function phase7Verify(opts, deps) {
|
|
1071
|
-
if (opts.skipDoctor) {
|
|
1072
|
-
return { ok: true, skipped: true, message: 'skipped via --skip-doctor' };
|
|
1073
|
-
}
|
|
1074
|
-
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
1075
|
-
const r = await spawnFn('olam', ['doctor']);
|
|
1076
|
-
if (r.status === 0) {
|
|
1077
|
-
return { ok: true, message: 'olam doctor: all probes green' };
|
|
1078
|
-
}
|
|
1079
|
-
return {
|
|
1080
|
-
ok: false,
|
|
1081
|
-
message: `olam doctor exited ${r.status}`,
|
|
1082
|
-
remedy: 'Inspect doctor output above; the specific failing probe names its remedy.',
|
|
1083
|
-
};
|
|
1084
|
-
}
|
|
1085
|
-
async function phase8KgHook(opts, deps) {
|
|
1086
|
-
if (opts.skipKgHook) {
|
|
1087
|
-
return { ok: true, skipped: true, message: 'skipped via --skip-kg-hook' };
|
|
1088
|
-
}
|
|
1089
|
-
return runKgHookPhase(opts, deps);
|
|
1090
|
-
}
|
|
1091
|
-
async function phase9MemoryBridge(opts, deps) {
|
|
1092
|
-
if (opts.skipMemoryBridge) {
|
|
1093
|
-
return { ok: true, skipped: true, message: 'skipped via --skip-memory-bridge' };
|
|
1094
|
-
}
|
|
1095
|
-
return runMemoryBridgePhase(opts, deps);
|
|
1096
|
-
}
|
|
1097
|
-
// ── Orchestrator ──────────────────────────────────────────────────────
|
|
1098
|
-
const PHASE_TITLES = [
|
|
1099
|
-
'Phase 0: Substrate picker',
|
|
1100
|
-
'Phase 0.5: Detect existing k8s context',
|
|
1101
|
-
'Phase 1: System check',
|
|
1102
|
-
'Phase 1.5: Substrate tools install',
|
|
1103
|
-
'Phase 2: olam CLI sanity',
|
|
1104
|
-
'Phase 2.5: Cluster provision',
|
|
1105
|
-
'Phase 2.6: Pin kubectl context',
|
|
1106
|
-
'Phase 3: Bootstrap',
|
|
1107
|
-
'Phase 3.5: K3d HTTPS bootstrap',
|
|
1108
|
-
'Phase 4: Shell init',
|
|
1109
|
-
'Phase 5: Init project',
|
|
1110
|
-
'Phase 5a: Skill source picker',
|
|
1111
|
-
'Phase 5b: Project sweep',
|
|
1112
|
-
'Phase 6: Auth prompt',
|
|
1113
|
-
'Phase 7: Final verification',
|
|
1114
|
-
'Phase 8: KG hook install',
|
|
1115
|
-
'Phase 9: Agent memory bridge install',
|
|
1116
|
-
];
|
|
1117
|
-
export async function runSetup(opts, deps = {}) {
|
|
1118
|
-
// ── --continue mode: skip Phases 1-7, run only Phase 8 + Phase 9 ──────────
|
|
1119
|
-
if (opts.continueMode) {
|
|
1120
|
-
printHeader('olam setup --continue — Phase 8 + Phase 9 only');
|
|
1121
|
-
const results = [];
|
|
1122
|
-
let failureAt = null;
|
|
1123
|
-
// Migrate secrets idempotently (same as full run).
|
|
1124
|
-
for (const name of KNOWN_SECRET_NAMES) {
|
|
1125
|
-
migrateSecretIfNeeded(name);
|
|
1126
|
-
}
|
|
1127
|
-
// Phase 8 title is at PHASE_TITLES index 15 (0=0, 0.5=1, 1=2, … 7=14, 8=15).
|
|
1128
|
-
const p8Title = PHASE_TITLES[15];
|
|
1129
|
-
const p9Title = PHASE_TITLES[16];
|
|
1130
|
-
process.stdout.write(`\n${p8Title}\n`);
|
|
1131
|
-
const p8Result = await phase8KgHook(opts, deps);
|
|
1132
|
-
results.push({ name: p8Title, result: p8Result });
|
|
1133
|
-
if (p8Result.ok && p8Result.skipped) {
|
|
1134
|
-
printWarning(` ⊘ ${p8Result.message}`);
|
|
1135
|
-
}
|
|
1136
|
-
else if (p8Result.ok) {
|
|
1137
|
-
printSuccess(` ✓ ${p8Result.message}`);
|
|
1138
|
-
}
|
|
1139
|
-
else {
|
|
1140
|
-
printError(` ✗ ${p8Result.message}`);
|
|
1141
|
-
if (p8Result.remedy)
|
|
1142
|
-
printWarning(` remedy: ${p8Result.remedy}`);
|
|
1143
|
-
failureAt = 8;
|
|
1144
|
-
}
|
|
1145
|
-
if (failureAt === null) {
|
|
1146
|
-
process.stdout.write(`\n${p9Title}\n`);
|
|
1147
|
-
const p9Result = await phase9MemoryBridge(opts, deps);
|
|
1148
|
-
results.push({ name: p9Title, result: p9Result });
|
|
1149
|
-
if (p9Result.ok && p9Result.skipped) {
|
|
1150
|
-
printWarning(` ⊘ ${p9Result.message}`);
|
|
1151
|
-
}
|
|
1152
|
-
else if (p9Result.ok) {
|
|
1153
|
-
printSuccess(` ✓ ${p9Result.message}`);
|
|
1154
|
-
}
|
|
1155
|
-
else {
|
|
1156
|
-
printError(` ✗ ${p9Result.message}`);
|
|
1157
|
-
if (p9Result.remedy)
|
|
1158
|
-
printWarning(` remedy: ${p9Result.remedy}`);
|
|
1159
|
-
failureAt = 9;
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
process.stdout.write('\n');
|
|
1163
|
-
if (failureAt !== null) {
|
|
1164
|
-
printError(`Setup FAILED at Phase ${failureAt}`);
|
|
1165
|
-
return { phases: results, failureAt, exitCode: 1 };
|
|
1166
|
-
}
|
|
1167
|
-
printSuccess('Setup --continue complete.');
|
|
1168
|
-
return { phases: results, failureAt: null, exitCode: 0 };
|
|
1169
|
-
}
|
|
1170
|
-
// ── Full setup (Phases 0 through 9) ───────────────────────────────────────
|
|
1171
|
-
// Phase 0 (substrate picker) runs eagerly BEFORE resolveSubstrate so it can
|
|
1172
|
-
// write host.substrate to config — resolveSubstrate then reads the written value.
|
|
1173
|
-
// We still push the result into the phases array for the SetupReport.
|
|
1174
|
-
const results = [];
|
|
1175
|
-
let failureAt = null;
|
|
1176
|
-
const phase0Title = PHASE_TITLES[0];
|
|
1177
|
-
process.stdout.write(`\n${phase0Title}\n`);
|
|
1178
|
-
const phase0Result = await phase0SubstratePicker(opts, deps);
|
|
1179
|
-
results.push({ name: phase0Title, result: phase0Result });
|
|
1180
|
-
if (phase0Result.ok && phase0Result.skipped) {
|
|
1181
|
-
printWarning(` ⊘ ${phase0Result.message}`);
|
|
1182
|
-
}
|
|
1183
|
-
else if (phase0Result.ok) {
|
|
1184
|
-
// Summary line already printed inside phase0SubstratePicker for non-skip path.
|
|
1185
|
-
}
|
|
1186
|
-
else {
|
|
1187
|
-
printError(` ✗ ${phase0Result.message}`);
|
|
1188
|
-
if (phase0Result.remedy)
|
|
1189
|
-
printWarning(` remedy: ${phase0Result.remedy}`);
|
|
1190
|
-
process.stdout.write('\n');
|
|
1191
|
-
printError('Setup FAILED at Phase 0');
|
|
1192
|
-
return { phases: results, failureAt: 0, exitCode: 1 };
|
|
1193
|
-
}
|
|
1194
|
-
const substrate = resolveSubstrate(opts, deps);
|
|
1195
|
-
const clusterName = resolveClusterName(opts);
|
|
1196
|
-
// Cluster-name flag validation (fail fast before any I/O).
|
|
1197
|
-
// Only validate when the kubernetes substrate is in play — the flag is a
|
|
1198
|
-
// no-op for docker and should not block docker-only operators who pass it
|
|
1199
|
-
// accidentally, but we still validate the format to surface typos.
|
|
1200
|
-
if (opts.clusterName !== undefined) {
|
|
1201
|
-
const nameError = validateClusterName(opts.clusterName);
|
|
1202
|
-
if (nameError !== null) {
|
|
1203
|
-
const errResult = {
|
|
1204
|
-
ok: false,
|
|
1205
|
-
message: `--cluster-name: ${nameError}`,
|
|
1206
|
-
remedy: 'Use a DNS-compatible name: lowercase letters, digits, hyphens in the middle. '
|
|
1207
|
-
+ 'Example: olam-test, my-stack-1',
|
|
1208
|
-
};
|
|
1209
|
-
printError(` ✗ ${errResult.message}`);
|
|
1210
|
-
if (errResult.remedy)
|
|
1211
|
-
printWarning(` remedy: ${errResult.remedy}`);
|
|
1212
|
-
return { phases: [{ name: 'Phase 0: Flag validation', result: errResult }], failureAt: 1, exitCode: 1 };
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
const bannerSubstrate = substrate === 'kubernetes' ? 'Kubernetes (k3d)' : 'Docker Compose';
|
|
1216
|
-
printHeader(`olam setup — Olam local stack on ${bannerSubstrate}`);
|
|
1217
|
-
process.stdout.write(`substrate: ${substrate}\n`);
|
|
1218
|
-
if (substrate === 'kubernetes') {
|
|
1219
|
-
process.stdout.write(`cluster: ${clusterName}\n`);
|
|
1220
|
-
}
|
|
1221
|
-
// Migrate secrets from ~/.olam/<name> → ~/.olam/secrets/<name> on every
|
|
1222
|
-
// setup run. Idempotent — operators who already ran setup once see no-op.
|
|
1223
|
-
for (const name of KNOWN_SECRET_NAMES) {
|
|
1224
|
-
migrateSecretIfNeeded(name);
|
|
1225
|
-
}
|
|
1226
|
-
// Phase 0.5: detect existing k8s context. Run eagerly (not in phaseFns) so
|
|
1227
|
-
// we can capture reuseContext and thread it through Phases 1.5, 2.5, 2.6.
|
|
1228
|
-
// We still push the result into the phases array for the SetupReport.
|
|
1229
|
-
const phase0_5Title = PHASE_TITLES[1];
|
|
1230
|
-
process.stdout.write(`\n${phase0_5Title}\n`);
|
|
1231
|
-
const phase0_5Result = await phase0_5DetectExistingContext(substrate, opts, deps);
|
|
1232
|
-
results.push({ name: phase0_5Title, result: phase0_5Result });
|
|
1233
|
-
if (phase0_5Result.ok && phase0_5Result.skipped) {
|
|
1234
|
-
printWarning(` ⊘ ${phase0_5Result.message}`);
|
|
1235
|
-
}
|
|
1236
|
-
else if (phase0_5Result.ok) {
|
|
1237
|
-
printSuccess(` ✓ ${phase0_5Result.message}`);
|
|
1238
|
-
}
|
|
1239
|
-
else {
|
|
1240
|
-
printError(` ✗ ${phase0_5Result.message}`);
|
|
1241
|
-
if (phase0_5Result.remedy)
|
|
1242
|
-
printWarning(` remedy: ${phase0_5Result.remedy}`);
|
|
1243
|
-
process.stdout.write('\n');
|
|
1244
|
-
printError('Setup FAILED at Phase 1');
|
|
1245
|
-
return { phases: results, failureAt: 1, exitCode: 1 };
|
|
1246
|
-
}
|
|
1247
|
-
const reuseContext = phase0_5Result.reuseContext;
|
|
1248
|
-
const phaseFns = [
|
|
1249
|
-
() => phase1SystemCheck(substrate, deps),
|
|
1250
|
-
() => phase1_5InstallSubstrate(substrate, opts, deps, reuseContext),
|
|
1251
|
-
() => phase2CliSanity(deps),
|
|
1252
|
-
() => phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reuseContext),
|
|
1253
|
-
() => phase2_6PinKubectlContext(substrate, clusterName, deps, reuseContext),
|
|
1254
|
-
() => phase3Bootstrap(substrate, deps, opts),
|
|
1255
|
-
() => phase3_5K3dHttpsBootstrap(substrate, opts, deps),
|
|
1256
|
-
() => phase4ShellInit(opts, deps),
|
|
1257
|
-
() => phase5InitProject(opts, deps),
|
|
1258
|
-
() => phase5aSkillSource(opts, deps),
|
|
1259
|
-
() => phase5bProjectSweep(opts, deps),
|
|
1260
|
-
() => phase6Auth(opts, deps),
|
|
1261
|
-
() => phase7Verify(opts, deps),
|
|
1262
|
-
() => phase8KgHook(opts, deps),
|
|
1263
|
-
() => phase9MemoryBridge(opts, deps),
|
|
1264
|
-
];
|
|
1265
|
-
// results + failureAt were initialised above (before Phase 0).
|
|
1266
|
-
// phaseFns indices correspond to PHASE_TITLES[2..] (Phase 0 = [0], Phase 0.5 = [1]).
|
|
1267
|
-
for (let i = 0; i < phaseFns.length; i += 1) {
|
|
1268
|
-
const name = PHASE_TITLES[i + 2];
|
|
1269
|
-
process.stdout.write(`\n${name}\n`);
|
|
1270
|
-
const result = await phaseFns[i]();
|
|
1271
|
-
results.push({ name, result });
|
|
1272
|
-
if (result.ok && result.skipped) {
|
|
1273
|
-
printWarning(` ⊘ ${result.message}`);
|
|
1274
|
-
}
|
|
1275
|
-
else if (result.ok) {
|
|
1276
|
-
printSuccess(` ✓ ${result.message}`);
|
|
1277
|
-
}
|
|
1278
|
-
else {
|
|
1279
|
-
printError(` ✗ ${result.message}`);
|
|
1280
|
-
if (result.remedy)
|
|
1281
|
-
printWarning(` remedy: ${result.remedy}`);
|
|
1282
|
-
failureAt = i + 2; // phaseFns[0] lands at results[2] — Phase 0 + Phase 0.5 occupy [0] + [1]
|
|
1283
|
-
break;
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
process.stdout.write('\n');
|
|
1287
|
-
if (failureAt !== null) {
|
|
1288
|
-
printError(`Setup FAILED at Phase ${failureAt}`);
|
|
1289
|
-
return { phases: results, failureAt, exitCode: 1 };
|
|
1290
|
-
}
|
|
1291
|
-
printSuccess('Setup complete.');
|
|
1292
|
-
process.stdout.write('\nNext steps — read these in order for the 3-contract pattern:\n');
|
|
1293
|
-
const nextStepsDocs = substrate === 'kubernetes' ? NEXT_STEPS_DOCS_KUBERNETES : NEXT_STEPS_DOCS_DOCKER;
|
|
1294
|
-
for (const line of nextStepsDocs) {
|
|
1295
|
-
printInfo('docs', line);
|
|
1296
|
-
}
|
|
1297
|
-
// Print the skill-source suggestion only when the operator explicitly opted out
|
|
1298
|
-
// via --skip-skill-source (they asked us not to run Phase 5a at all).
|
|
1299
|
-
// When Phase 5a ran unconditionally (the default), it either registered a source,
|
|
1300
|
-
// found existing ones, or the operator chose "skip for now" in the interactive picker
|
|
1301
|
-
// — no post-setup hint needed because the phase itself communicated the outcome.
|
|
1302
|
-
if (opts.skipSkillSource) {
|
|
1303
|
-
process.stdout.write(formatPostSetupSuggestion());
|
|
1304
|
-
}
|
|
1305
|
-
else {
|
|
1306
|
-
process.stdout.write('\n');
|
|
1307
|
-
}
|
|
1308
|
-
return { phases: results, failureAt: null, exitCode: 0 };
|
|
1309
|
-
}
|
|
1310
|
-
export function registerSetup(program) {
|
|
1311
|
-
program
|
|
1312
|
-
.command('setup')
|
|
1313
|
-
.description('Fresh-host onboarding wizard (k3d cluster + services, idempotent)')
|
|
1314
|
-
.option('--skip-substrate-picker', 'Skip Phase 0 substrate picker (uses existing config or default). '
|
|
1315
|
-
+ 'For non-interactive setups where host.substrate is managed manually.')
|
|
1316
|
-
.option('--substrate <substrate>', 'Target substrate: kubernetes (default, alias: k3s) or docker. '
|
|
1317
|
-
+ 'Auto-detected from ~/.olam/config.json when not specified.')
|
|
1318
|
-
.option('--cluster-name <name>', 'k3d cluster name to create/use (kubernetes substrate only; default: olam-dev). '
|
|
1319
|
-
+ 'Use a different name to avoid colliding with a pre-existing olam-dev cluster, '
|
|
1320
|
-
+ 'to run multiple olam stacks side-by-side, or for per-run unique names in CI smoke. '
|
|
1321
|
-
+ 'Must be DNS-compatible: lowercase alphanumeric, hyphens allowed in the middle.')
|
|
1322
|
-
.option('--reuse-cluster <name>', 'Reuse an existing kubeconfig context instead of provisioning a new k3d cluster. '
|
|
1323
|
-
+ 'Pair with --substrate=kubernetes. Skips Phase 1.5 (k3d install) and Phase 2.5 '
|
|
1324
|
-
+ '(cluster provision); Phase 2.6 pins to this context. Operator owns the cluster '
|
|
1325
|
-
+ 'lifecycle (teardown not handled by olam setup). '
|
|
1326
|
-
+ 'Example: --reuse-cluster=colima (for Colima k8s users).')
|
|
1327
|
-
.option('--skip-https-bootstrap', 'Skip Phase 3.5 (do not install mkcert or provision TLS Secret; run `olam services tls-install` later)')
|
|
1328
|
-
.option('--skip-shell-init', 'Skip Phase 4 (do not append to ~/.zshrc / ~/.bashrc)')
|
|
1329
|
-
.option('--skip-auth', 'Skip Phase 6 (do not prompt for `olam auth login`)')
|
|
1330
|
-
.option('--skip-skill-source', 'Skip Phase 5a entirely (run `olam skills source add` later; default: Phase 5a runs and auto-skips when sources already registered)')
|
|
1331
|
-
.option('--skill-source <id-or-url>', 'Non-interactive Phase 5a: curated name (e.g. atlas-toolbox) or git URL (skips interactive picker)')
|
|
1332
|
-
.option('--skip-project-sweep', 'Skip Phase 5b (do not walk projects directory for repo discovery)')
|
|
1333
|
-
.option('--projects <path>', 'Phase 5b: project root path to walk (default: ~/Projects)')
|
|
1334
|
-
.option('--dry-run', 'Phase 5b: print matches without registering or building (no side effects)')
|
|
1335
|
-
.option('--exclude <glob...>', 'Phase 5b: additional skip patterns for project sweep')
|
|
1336
|
-
.option('--skip-kg', 'Phase 5b: skip KG eager-build sub-step (sources still registered)')
|
|
1337
|
-
.option('--skip-doctor', 'Skip Phase 7 final `olam doctor` verification (for CI or minimal setups)')
|
|
1338
|
-
.option('--host-cp-dev-path <path>', 'DEV-ONLY: mount a local olam source checkout into the k3d node at '
|
|
1339
|
-
+ '/host/olam so host-cp reads live source. Regular operators DO NOT '
|
|
1340
|
-
+ 'use this — the published image is self-contained. Absolute path required.')
|
|
1341
|
-
.option('-y, --yes', 'Auto-affirm every prompt (non-interactive)')
|
|
1342
|
-
.option('--continue', 'Skip Phases 1-7 (initial setup) and run Phase 8 (KG hook) + Phase 9 '
|
|
1343
|
-
+ '(memory bridge) only. Use after `olam setup` has run once successfully.')
|
|
1344
|
-
.option('--skip-kg-hook', 'Skip Phase 8 (do not install KG hook; run `olam kg install-hook --scope user` later)')
|
|
1345
|
-
.option('--skip-memory-bridge', 'Skip Phase 9 (do not register agentmemory MCP; run `olam memory install` later)')
|
|
1346
|
-
.option('--verbose', '[k3s] stream all bootstrap phase output sequentially instead of collapsing to live spinner lines')
|
|
1347
|
-
.option('--skip-prepull', '[k3s] skip pre-pulling olam-* images into the k3d node (pods cold-pull on demand)')
|
|
1348
|
-
.action(async (rawOpts) => {
|
|
1349
|
-
// Normalise the --substrate flag: 'k3s' is an alias for 'kubernetes'.
|
|
1350
|
-
let substrate;
|
|
1351
|
-
const rawSubstrate = rawOpts.substrate;
|
|
1352
|
-
if (rawSubstrate === 'k3s' || rawSubstrate === 'kubernetes') {
|
|
1353
|
-
substrate = 'kubernetes';
|
|
1354
|
-
}
|
|
1355
|
-
else if (rawSubstrate === 'docker') {
|
|
1356
|
-
substrate = 'docker';
|
|
1357
|
-
}
|
|
1358
|
-
else if (rawSubstrate !== undefined) {
|
|
1359
|
-
process.stderr.write(`[olam setup] Unknown --substrate value '${rawSubstrate}'. `
|
|
1360
|
-
+ `Valid values: docker, kubernetes (alias: k3s).\n`);
|
|
1361
|
-
process.exitCode = 1;
|
|
1362
|
-
return;
|
|
1363
|
-
}
|
|
1364
|
-
// commander maps `--continue` to rawOpts.continue (reserved word in JS,
|
|
1365
|
-
// but valid as an object property). Map it to continueMode to avoid
|
|
1366
|
-
// shadowing the `continue` keyword in the surrounding scope.
|
|
1367
|
-
const { substrate: _drop, continue: continueFlag, ...restOpts } = rawOpts;
|
|
1368
|
-
void _drop;
|
|
1369
|
-
const report = await runSetup({ ...restOpts, substrate, continueMode: continueFlag });
|
|
1370
|
-
if (report.exitCode !== 0)
|
|
1371
|
-
process.exitCode = report.exitCode;
|
|
1372
|
-
});
|
|
1373
|
-
}
|
|
1374
|
-
//# sourceMappingURL=setup.js.map
|