@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
|
@@ -1,1014 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* upgrade-kubernetes.ts — 8-step kubernetes upgrade path for olam upgrade.
|
|
3
|
-
*
|
|
4
|
-
* Phase 1b C2 of olam-host-suite-phase-1b-k3s-beta-flavour (plan
|
|
5
|
-
* ~/.claude/plans/olam-host-suite-phase-1b-k3s-beta-flavour.md).
|
|
6
|
-
*
|
|
7
|
-
* Phase 2 Phase C extensions:
|
|
8
|
-
* C1 — step 2.5: in-memory ConfigMap substitution for inter-peripheral K8s DNS URLs (D4)
|
|
9
|
-
* C2 — step 2.6: per-peripheral Secret pre-check (iterates PERIPHERALS; D12 pattern)
|
|
10
|
-
* C3 — step 2.7: CoreDNS warm-up wait + extend steps 3/4/5 to iterate peripherals
|
|
11
|
-
*
|
|
12
|
-
* Phase 2 Phase D extensions:
|
|
13
|
-
* D5 — OLAM_PHASE_2_BETA guard removed; all peripherals deploy unconditionally (Phase 2 GA)
|
|
14
|
-
*
|
|
15
|
-
* Decisions consumed:
|
|
16
|
-
* D4 — K8s DNS URL form for inter-peripheral service URLs
|
|
17
|
-
* D10 — context-allowlist + OLAM_K8S_CONTEXT_ACK strict-equality check
|
|
18
|
-
* D12 — Secret pre-check (base64-decode + key-name + placeholder exact match)
|
|
19
|
-
* D14 — --force-refresh-manifests flag + --accept-security-regression guard
|
|
20
|
-
* D15 — kubectl rollout status --timeout=180s; state snapshot on failure
|
|
21
|
-
* D17 — port-forward spawn via flock (spawnPortForward from port-forward.ts)
|
|
22
|
-
* D22 — probeKubernetesApiReachable pre-flight via kubectl-wrap (5s timeout)
|
|
23
|
-
* D27 — audit log entry (phase2.flag_removed) emitted per upgrade run
|
|
24
|
-
*
|
|
25
|
-
* Step order (Phase D — kubernetes substrate, Phase 2 GA):
|
|
26
|
-
* 0 probeKubernetesApiReachable — 5s timeout kubectl cluster-info
|
|
27
|
-
* (Step 0.5 D4 k3d node bind-mount preflight REMOVED in
|
|
28
|
-
* olam-k3d-on-mac-substrate-decision Phase B B3 — R3-A retracted.)
|
|
29
|
-
* 0.5b B4 ensureK8sBootstrap (namespace + RBAC + ConfigMap + PVC + secrets)
|
|
30
|
-
* 0.6 R3-C create/update ghcr-pull imagePullSecret in olam namespace (when GH_TOKEN available)
|
|
31
|
-
* NOTE: relocated from pre-step 0.4 to post-bootstrap (R4-W2-A) — the
|
|
32
|
-
* `olam` namespace must exist before kubectl can create the secret.
|
|
33
|
-
* 0.7 olam-k3d-on-mac-substrate-decision Phase A — host-side docker-
|
|
34
|
-
* socket-proxy auto-start on macOS (Decision #1 + #3). Linux substrate
|
|
35
|
-
* is a no-op. Resolves R4-W2-F (virtiofs ENOTSUP on stat of docker.sock
|
|
36
|
-
* hostPath bind mounts) by routing host-cp's docker access through a
|
|
37
|
-
* host-side proxy container reachable via in-cluster ExternalName
|
|
38
|
-
* Service (host.k3d.internal:2375).
|
|
39
|
-
* 1 D10 context-allowlist + OLAM_K8S_CONTEXT_ACK strict-equality byte-for-byte
|
|
40
|
-
* 2 D12 Secret pre-check (olam-host-cp-secret; base64-decode; key-name check)
|
|
41
|
-
* 2.6 C2 per-peripheral Secret pre-check (iterates PERIPHERALS; unconditional — D5)
|
|
42
|
-
* 2.7 C3 CoreDNS warm-up wait (kubectl wait --for=condition=Available deployment/coredns -n kube-system)
|
|
43
|
-
* 3 kubectl apply host-cp manifests + all 4 peripheral manifest dirs (alphabetical)
|
|
44
|
-
* 3.5 C1 in-memory ConfigMap substitution — K8s DNS URLs AFTER step 3 (B7 fix — last-write-wins)
|
|
45
|
-
* 4 D15 kubectl rollout status (all 5 deployments in parallel)
|
|
46
|
-
* 5 D17 port-forward spawn for host-cp + spawnAllPeripheralPortForwards in parallel
|
|
47
|
-
* 6 verify /health returns X-Olam-Engine: kubernetes
|
|
48
|
-
* 7 emit upgrade.complete instrumentation event
|
|
49
|
-
* 8 success message
|
|
50
|
-
*
|
|
51
|
-
* Manifests NOT auto-rolled-back on failure (D15 spec). Operator must
|
|
52
|
-
* manually intervene; state snapshot is printed on failure.
|
|
53
|
-
*/
|
|
54
|
-
import * as fs from 'node:fs';
|
|
55
|
-
import * as os from 'node:os';
|
|
56
|
-
import * as path from 'node:path';
|
|
57
|
-
import { parse as yamlParse, stringify as yamlStringify } from 'yaml';
|
|
58
|
-
import ora from 'ora';
|
|
59
|
-
import pc from 'picocolors';
|
|
60
|
-
import { printError, printSuccess, printInfo, printWarning } from '../output.js';
|
|
61
|
-
// buildDockerSocketRemedy + defaultDetectK8sClusterType removed in
|
|
62
|
-
// olam-k3d-on-mac-substrate-decision Phase B B3 — Pre-step 0b retracted.
|
|
63
|
-
import { kubectlWrap } from './kubectl-wrap.js';
|
|
64
|
-
import { spawnPortForward, spawnAllPeripheralPortForwards, probePortForwardLiveness } from './port-forward.js';
|
|
65
|
-
import { emitUpgradeComplete } from './instrumentation.js';
|
|
66
|
-
import { runManifestRefresh, seedManifestsFromBundle } from './manifest-refresh.js';
|
|
67
|
-
import { OLAM_HOME, OLAM_STATE_DIR } from './config.js';
|
|
68
|
-
import { PERIPHERALS } from './peripheral-registry.js';
|
|
69
|
-
import { resolveKubectlContext, autoPinKubectlContext } from './kubectl-context.js';
|
|
70
|
-
import { ensureK8sBootstrap, resolveK8sAssetsRoot } from './k8s-bootstrap.js';
|
|
71
|
-
import { startHostSideProxy } from './host-side-proxy.js';
|
|
72
|
-
/**
|
|
73
|
-
* Resolve the bundled docker-socket-proxy.compose.yaml path. Looks under
|
|
74
|
-
* the same k8s-assets root that ships the in-cluster manifests. Returns
|
|
75
|
-
* null when the bundle layout is unexpected (dev contexts without a built
|
|
76
|
-
* tarball). Step 0.7's caller treats null as a continue-with-warning.
|
|
77
|
-
*/
|
|
78
|
-
function resolveHostSideProxyComposePath() {
|
|
79
|
-
const root = resolveK8sAssetsRoot();
|
|
80
|
-
if (root === null)
|
|
81
|
-
return null;
|
|
82
|
-
const candidate = path.join(root, 'host-side', 'docker-socket-proxy.compose.yaml');
|
|
83
|
-
return fs.existsSync(candidate) ? candidate : null;
|
|
84
|
-
}
|
|
85
|
-
export const OLAM_K8S_MANIFESTS_DIR = path.join(OLAM_HOME, 'k8s', 'manifests');
|
|
86
|
-
export const K8S_NAMESPACE = 'olam';
|
|
87
|
-
export const HOST_CP_SECRET_NAME = 'olam-host-cp-secret';
|
|
88
|
-
export const HOST_CP_DEPLOYMENT_NAME = 'olam-host-cp';
|
|
89
|
-
export const PORT_FORWARD_TARGET = 'service/olam-host-cp';
|
|
90
|
-
export const HOST_CP_HEALTH_URL = 'http://127.0.0.1:19000/health';
|
|
91
|
-
/** Audit log for substrate upgrade events (D18). */
|
|
92
|
-
export const SUBSTRATE_AUDIT_LOG = path.join(OLAM_STATE_DIR, 'substrate-audit.jsonl');
|
|
93
|
-
/** Placeholder values that indicate the Secret has not been configured (D12). */
|
|
94
|
-
const PLACEHOLDER_VALUES = new Set(['OLAM_AUTH_SECRET', 'GH_TOKEN']);
|
|
95
|
-
/** Required keys in the olam-host-cp-secret (D12). */
|
|
96
|
-
const REQUIRED_SECRET_KEYS = ['OLAM_AUTH_SECRET', 'GH_TOKEN'];
|
|
97
|
-
/**
|
|
98
|
-
* Peripheral secret metadata: name and required keys with their placeholder patterns.
|
|
99
|
-
* Placeholder pattern: starts with REPLACE_ME_ (as per the template files in
|
|
100
|
-
* packages/host-cp/k8s/templates/).
|
|
101
|
-
*/
|
|
102
|
-
const PERIPHERAL_SECRETS = [
|
|
103
|
-
{ name: 'auth-service', secretName: 'olam-auth-service-secret', keys: ['OLAM_AUTH_DB_SECRET'] },
|
|
104
|
-
{ name: 'mcp-auth-service', secretName: 'olam-mcp-auth-service-secret', keys: ['OLAM_MCP_AUTH_JWT_SECRET'] },
|
|
105
|
-
{ name: 'kg-service', secretName: 'olam-kg-service-secret', keys: ['OLAM_KG_BEARER_TOKEN'] },
|
|
106
|
-
{ name: 'memory-service', secretName: 'olam-memory-service-secret', keys: ['OLAM_MEMORY_BEARER_SECRET'] },
|
|
107
|
-
// Phase B Model B: plan-chat-service joins the registry. The Secret is named
|
|
108
|
-
// olam-plan-chat-secret (NOT olam-plan-chat-service-secret) because it's also
|
|
109
|
-
// mounted by the host-cp pod for SPA bearer injection — the substrate-scope
|
|
110
|
-
// name is more honest than tying it to one consumer.
|
|
111
|
-
{ name: 'plan-chat-service', secretName: 'olam-plan-chat-secret', keys: ['PLAN_CHAT_SECRET'] },
|
|
112
|
-
];
|
|
113
|
-
/** K8s cluster DNS base domain for the olam namespace. */
|
|
114
|
-
const K8S_DNS_SUFFIX = 'olam.svc.cluster.local';
|
|
115
|
-
/**
|
|
116
|
-
* Build the K8s in-cluster DNS URL for a peripheral service.
|
|
117
|
-
* Form: http://<k8sResourceName>.olam.svc.cluster.local:<port>
|
|
118
|
-
*
|
|
119
|
-
* The PERIPHERALS registry stores the full k8s resource name (with `olam-` prefix)
|
|
120
|
-
* in `k8sResourceName`. The DNS hostname MUST match the Service metadata.name in
|
|
121
|
-
* 60-service.yaml (e.g. `olam-auth-service`).
|
|
122
|
-
*
|
|
123
|
-
* C3 (R3-F): fix — previous form `http://auth-service.olam.svc.cluster.local`
|
|
124
|
-
* resolved to nothing; correct form is `http://olam-auth-service.olam.svc.cluster.local`.
|
|
125
|
-
*/
|
|
126
|
-
function buildK8sDnsUrl(k8sResourceName, port) {
|
|
127
|
-
return `http://${k8sResourceName}.${K8S_DNS_SUFFIX}:${port}`;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Append a JSONL audit entry to the substrate audit log (D18).
|
|
131
|
-
* Best-effort: errors are logged to stderr but do not abort the upgrade.
|
|
132
|
-
*/
|
|
133
|
-
function appendSubstrateAuditEntry(entry, stderr) {
|
|
134
|
-
try {
|
|
135
|
-
const line = JSON.stringify(entry) + '\n';
|
|
136
|
-
const dir = path.dirname(SUBSTRATE_AUDIT_LOG);
|
|
137
|
-
if (!fs.existsSync(dir))
|
|
138
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
139
|
-
fs.writeFileSync(SUBSTRATE_AUDIT_LOG, line, { encoding: 'utf8', flag: 'a', mode: 0o600 });
|
|
140
|
-
}
|
|
141
|
-
catch (err) {
|
|
142
|
-
stderr.write(`${pc.yellow('[warn]')} could not write substrate audit log: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
/** D10 — allowed kubectl context patterns. Currently: anything non-empty.
|
|
146
|
-
* The allowlist is enforced by OLAM_K8S_CONTEXT_ACK strict-equality. */
|
|
147
|
-
function isContextAllowed(context) {
|
|
148
|
-
return typeof context === 'string' && context.length > 0;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* D6 — Managed-k8s cluster server URL patterns (Decision #18 active retraction).
|
|
152
|
-
*
|
|
153
|
-
* Matches the cluster server URL (from `kubectl config view --minify`).
|
|
154
|
-
* These patterns indicate managed Kubernetes providers where hostPath
|
|
155
|
-
* /var/run/docker.sock does not reach the operator's docker daemon.
|
|
156
|
-
* Operators on managed k8s must use a local k3d/k3s cluster instead.
|
|
157
|
-
*
|
|
158
|
-
* Pattern sources:
|
|
159
|
-
* - EKS: *.amazonaws.com — AWS API server endpoint
|
|
160
|
-
* - GKE: *.googleapis.com — Google API server; also *.gke.io
|
|
161
|
-
* - AKS: *.azmk8s.io — Azure managed k8s endpoint
|
|
162
|
-
* - DO: *.do-user-*.k8s.ondigitalocean.com — DigitalOcean
|
|
163
|
-
* - Civo: *.civo.com — Civo cloud
|
|
164
|
-
*/
|
|
165
|
-
const MANAGED_K8S_URL_PATTERNS = [
|
|
166
|
-
{ pattern: /\.amazonaws\.com(:\d+)?$/, provider: 'EKS (Amazon)' },
|
|
167
|
-
{ pattern: /\.googleapis\.com(:\d+)?$/, provider: 'GKE (Google)' },
|
|
168
|
-
{ pattern: /\.gke\.io(:\d+)?$/, provider: 'GKE (Google)' },
|
|
169
|
-
{ pattern: /\.azmk8s\.io(:\d+)?$/, provider: 'AKS (Azure)' },
|
|
170
|
-
{ pattern: /\.k8s\.ondigitalocean\.com(:\d+)?$/, provider: 'DOKS (DigitalOcean)' },
|
|
171
|
-
{ pattern: /\.civo\.com(:\d+)?$/, provider: 'Civo' },
|
|
172
|
-
];
|
|
173
|
-
/**
|
|
174
|
-
* Detect whether the active kubectl context is a managed-k8s provider.
|
|
175
|
-
* Returns the detected provider name if managed, null if local/unknown.
|
|
176
|
-
* Fail-open: unrecognized cluster URLs return null (no false positives).
|
|
177
|
-
*/
|
|
178
|
-
async function detectManagedK8sProvider(deps) {
|
|
179
|
-
if (deps.getClusterServerUrlImpl) {
|
|
180
|
-
const url = await deps.getClusterServerUrlImpl();
|
|
181
|
-
if (!url)
|
|
182
|
-
return null;
|
|
183
|
-
for (const { pattern, provider } of MANAGED_K8S_URL_PATTERNS) {
|
|
184
|
-
if (pattern.test(url))
|
|
185
|
-
return provider;
|
|
186
|
-
}
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
189
|
-
// Default: run kubectl config view --minify to get the server URL.
|
|
190
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
191
|
-
const result = await wrap(['config', 'view', '--minify', '-o', 'jsonpath={.clusters[0].cluster.server}'], { timeout: 5_000 });
|
|
192
|
-
if (!result.ok || !result.stdout.trim())
|
|
193
|
-
return null;
|
|
194
|
-
const url = result.stdout.trim();
|
|
195
|
-
for (const { pattern, provider } of MANAGED_K8S_URL_PATTERNS) {
|
|
196
|
-
if (pattern.test(url))
|
|
197
|
-
return provider;
|
|
198
|
-
}
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Step 0 — D22: probe Kubernetes API reachability (5s timeout).
|
|
203
|
-
* Uses kubectl cluster-info with a tight timeout to detect unreachable API server.
|
|
204
|
-
*/
|
|
205
|
-
async function probeKubernetesApiReachable(context, deps) {
|
|
206
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
207
|
-
const result = await wrap(['--context', context, 'cluster-info'], { timeout: 5_000 });
|
|
208
|
-
return result.ok;
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Step 2 — D12: Secret pre-check.
|
|
212
|
-
*
|
|
213
|
-
* Fetches the olam-host-cp-secret, base64-decodes each data value, and:
|
|
214
|
-
* a) Asserts OLAM_AUTH_SECRET and GH_TOKEN keys are present.
|
|
215
|
-
* b) EXACT-EQUALS check against placeholder strings — if any decoded value
|
|
216
|
-
* equals the literal placeholder name ('OLAM_AUTH_SECRET' or 'GH_TOKEN'),
|
|
217
|
-
* the secret has not been configured and the upgrade is refused.
|
|
218
|
-
*
|
|
219
|
-
* Returns null on success; error message string on failure.
|
|
220
|
-
*/
|
|
221
|
-
async function checkSecretPreCondition(context, deps) {
|
|
222
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
223
|
-
const result = await wrap([
|
|
224
|
-
'--context', context,
|
|
225
|
-
'get', 'secret', HOST_CP_SECRET_NAME,
|
|
226
|
-
'-n', K8S_NAMESPACE,
|
|
227
|
-
'-o', 'json',
|
|
228
|
-
], { timeout: 15_000 });
|
|
229
|
-
if (!result.ok) {
|
|
230
|
-
return (`Secret "${HOST_CP_SECRET_NAME}" not found in namespace "${K8S_NAMESPACE}".\n` +
|
|
231
|
-
` Create it first: kubectl --context ${context} apply -f <your-secret.yaml>\n` +
|
|
232
|
-
` ${result.stderr.split('\n')[0] ?? ''}`);
|
|
233
|
-
}
|
|
234
|
-
let secretJson;
|
|
235
|
-
try {
|
|
236
|
-
secretJson = JSON.parse(result.stdout);
|
|
237
|
-
}
|
|
238
|
-
catch {
|
|
239
|
-
return `Failed to parse Secret JSON: ${result.stdout.slice(0, 200)}`;
|
|
240
|
-
}
|
|
241
|
-
const data = secretJson.data ?? {};
|
|
242
|
-
for (const key of REQUIRED_SECRET_KEYS) {
|
|
243
|
-
if (!(key in data)) {
|
|
244
|
-
return (`Secret "${HOST_CP_SECRET_NAME}" is missing required key "${key}".\n` +
|
|
245
|
-
` Keys found: ${Object.keys(data).join(', ') || '(none)'}\n` +
|
|
246
|
-
` Add the key and re-run.`);
|
|
247
|
-
}
|
|
248
|
-
const b64 = data[key] ?? '';
|
|
249
|
-
const decoded = Buffer.from(b64, 'base64').toString('utf8');
|
|
250
|
-
// EXACT-EQUALS: decoded value === placeholder name means unconfigured (D12).
|
|
251
|
-
if (PLACEHOLDER_VALUES.has(decoded)) {
|
|
252
|
-
return (`Secret "${HOST_CP_SECRET_NAME}" key "${key}" still holds its placeholder value.\n` +
|
|
253
|
-
` Replace the placeholder with a real value, then re-run.`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return null; // all checks passed
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Step 4 — D15: kubectl rollout status with state snapshot on failure.
|
|
260
|
-
* Wrapper timeout: 185s (5s padding over the kubectl --timeout=180s).
|
|
261
|
-
* 180s budget: fresh CI clusters with cold image pulls need more time.
|
|
262
|
-
*/
|
|
263
|
-
async function waitForRollout(context, deps, stderr) {
|
|
264
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
265
|
-
const result = await wrap([
|
|
266
|
-
'--context', context,
|
|
267
|
-
'rollout', 'status',
|
|
268
|
-
`deployment/${HOST_CP_DEPLOYMENT_NAME}`,
|
|
269
|
-
'-n', K8S_NAMESPACE,
|
|
270
|
-
'--timeout=180s',
|
|
271
|
-
], { timeout: 185_000 });
|
|
272
|
-
if (result.ok)
|
|
273
|
-
return true;
|
|
274
|
-
// State snapshot on failure (D15).
|
|
275
|
-
stderr.write(`${pc.red('error:')} kubectl rollout status timed out or failed.\n` +
|
|
276
|
-
` reason: ${result.reason ?? 'nonzero'} exitCode=${result.exitCode}\n\n`);
|
|
277
|
-
stderr.write(`${pc.dim('--- kubectl get pods -n olam -o wide ---')}\n`);
|
|
278
|
-
const podsResult = await wrap(['--context', context, 'get', 'pods', '-n', K8S_NAMESPACE, '-o', 'wide'], { timeout: 10_000 });
|
|
279
|
-
stderr.write((podsResult.stdout || podsResult.stderr || '(no output)') + '\n');
|
|
280
|
-
stderr.write(`\n${pc.dim('--- kubectl describe deployment/olam-host-cp -n olam ---')}\n`);
|
|
281
|
-
const descResult = await wrap(['--context', context, 'describe', `deployment/${HOST_CP_DEPLOYMENT_NAME}`, '-n', K8S_NAMESPACE], { timeout: 10_000 });
|
|
282
|
-
stderr.write((descResult.stdout || descResult.stderr || '(no output)') + '\n');
|
|
283
|
-
stderr.write(`\n${pc.yellow('note:')} Manifests are NOT auto-rolled-back. Inspect the state above and remediate manually.\n`);
|
|
284
|
-
return false;
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Step 2.5 — C1: in-memory ConfigMap substitution for inter-peripheral K8s DNS URLs (D4).
|
|
288
|
-
*
|
|
289
|
-
* Reads the bundled host-cp ConfigMap YAML from manifestsDir/30-configmap.yaml,
|
|
290
|
-
* patches the inter-peripheral URL values to K8s cluster-DNS form, then applies
|
|
291
|
-
* the patched manifest via `kubectl apply -f -` on stdin.
|
|
292
|
-
*
|
|
293
|
-
* Does NOT rewrite any file on disk.
|
|
294
|
-
* Only runs on kubernetes substrate (called after substrate check).
|
|
295
|
-
*
|
|
296
|
-
* Returns null on success; error message string on failure.
|
|
297
|
-
*/
|
|
298
|
-
async function applyConfigMapSubstitution(context, manifestsDir, deps) {
|
|
299
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
300
|
-
const readFileSync = deps.readFileSyncImpl ?? fs.readFileSync;
|
|
301
|
-
const configMapPath = path.join(manifestsDir, '30-configmap.yaml');
|
|
302
|
-
let rawYaml;
|
|
303
|
-
try {
|
|
304
|
-
rawYaml = readFileSync(configMapPath, 'utf8');
|
|
305
|
-
}
|
|
306
|
-
catch (err) {
|
|
307
|
-
return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
308
|
-
}
|
|
309
|
-
// Parse → patch data values → re-serialize.
|
|
310
|
-
let parsed;
|
|
311
|
-
try {
|
|
312
|
-
parsed = yamlParse(rawYaml);
|
|
313
|
-
}
|
|
314
|
-
catch (err) {
|
|
315
|
-
return `Failed to parse ConfigMap YAML at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
316
|
-
}
|
|
317
|
-
const data = (parsed['data'] ?? {});
|
|
318
|
-
// Substitute each peripheral's ConfigMap key to K8s DNS form.
|
|
319
|
-
for (const peripheral of PERIPHERALS) {
|
|
320
|
-
data[peripheral.configMapKeyInHostCp] = buildK8sDnsUrl(peripheral.k8sResourceName, peripheral.port);
|
|
321
|
-
}
|
|
322
|
-
parsed['data'] = data;
|
|
323
|
-
const patchedYaml = yamlStringify(parsed);
|
|
324
|
-
// Apply via stdin pipe (D20 compliance: no value in argv).
|
|
325
|
-
const result = await wrap(['--context', context, 'apply', '-f', '-'], { timeout: 30_000, stdin: patchedYaml });
|
|
326
|
-
if (!result.ok) {
|
|
327
|
-
return `kubectl apply (ConfigMap substitution) failed: ${result.stderr.split('\n')[0] ?? ''}`;
|
|
328
|
-
}
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
331
|
-
/**
|
|
332
|
-
* Step 2.6 — C2: per-peripheral Secret pre-check.
|
|
333
|
-
*
|
|
334
|
-
* Iterates PERIPHERAL_SECRETS; for each, fetches the Secret via kubectl,
|
|
335
|
-
* base64-decodes each value, and refuses if:
|
|
336
|
-
* (a) Secret does not exist → names the peripheral + Secret resource.
|
|
337
|
-
* (b) Any key is missing → names the peripheral + key.
|
|
338
|
-
* (c) Any value starts with REPLACE_ME_ (placeholder not configured) → names key.
|
|
339
|
-
*
|
|
340
|
-
* Mirrors Phase 1b's D12 host-cp Secret pre-check pattern, generalised to N peripherals.
|
|
341
|
-
*
|
|
342
|
-
* Returns null on success; error message string on first failure.
|
|
343
|
-
*/
|
|
344
|
-
async function checkPeripheralSecrets(context, deps) {
|
|
345
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
346
|
-
for (const { name, secretName, keys } of PERIPHERAL_SECRETS) {
|
|
347
|
-
const result = await wrap([
|
|
348
|
-
'--context', context,
|
|
349
|
-
'get', 'secret', secretName,
|
|
350
|
-
'-n', K8S_NAMESPACE,
|
|
351
|
-
'-o', 'json',
|
|
352
|
-
], { timeout: 15_000 });
|
|
353
|
-
if (!result.ok) {
|
|
354
|
-
return (`Peripheral Secret "${secretName}" (${name}) not found in namespace "${K8S_NAMESPACE}".\n` +
|
|
355
|
-
` Create it first: kubectl --context ${context} apply -f <your-${name}-secret.yaml>\n` +
|
|
356
|
-
` ${result.stderr.split('\n')[0] ?? ''}`);
|
|
357
|
-
}
|
|
358
|
-
let secretJson;
|
|
359
|
-
try {
|
|
360
|
-
secretJson = JSON.parse(result.stdout);
|
|
361
|
-
}
|
|
362
|
-
catch {
|
|
363
|
-
return `Failed to parse Secret JSON for "${secretName}" (${name}): ${result.stdout.slice(0, 200)}`;
|
|
364
|
-
}
|
|
365
|
-
const data = secretJson.data ?? {};
|
|
366
|
-
for (const key of keys) {
|
|
367
|
-
if (!(key in data)) {
|
|
368
|
-
return (`Peripheral Secret "${secretName}" (${name}) is missing required key "${key}".\n` +
|
|
369
|
-
` Keys found: ${Object.keys(data).join(', ') || '(none)'}\n` +
|
|
370
|
-
` Add the key and re-run.`);
|
|
371
|
-
}
|
|
372
|
-
const b64 = data[key] ?? '';
|
|
373
|
-
const decoded = Buffer.from(b64, 'base64').toString('utf8');
|
|
374
|
-
if (decoded.startsWith('REPLACE_ME_')) {
|
|
375
|
-
return (`Peripheral Secret "${secretName}" (${name}) key "${key}" still holds its placeholder value.\n` +
|
|
376
|
-
` Replace the placeholder with a real value, then re-run.`);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
return null; // all peripheral secrets verified
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Step 2.7 — C3: CoreDNS warm-up wait.
|
|
384
|
-
*
|
|
385
|
-
* Runs `kubectl wait --for=condition=Available deployment/coredns -n kube-system --timeout=30s`
|
|
386
|
-
* before step 3 to ensure DNS resolution is available for peripheral service discovery.
|
|
387
|
-
*
|
|
388
|
-
* Returns true on success; false on timeout or failure.
|
|
389
|
-
*/
|
|
390
|
-
async function waitForCoreDns(context, deps) {
|
|
391
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
392
|
-
const result = await wrap([
|
|
393
|
-
'--context', context,
|
|
394
|
-
'wait',
|
|
395
|
-
'--for=condition=Available',
|
|
396
|
-
'deployment/coredns',
|
|
397
|
-
'-n', 'kube-system',
|
|
398
|
-
'--timeout=30s',
|
|
399
|
-
], { timeout: 35_000 });
|
|
400
|
-
return result.ok;
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Step 6 — verify /health returns X-Olam-Engine: kubernetes.
|
|
404
|
-
*/
|
|
405
|
-
async function verifyHealthHeader(deps) {
|
|
406
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
407
|
-
try {
|
|
408
|
-
const res = await fetchImpl(HOST_CP_HEALTH_URL, {
|
|
409
|
-
signal: AbortSignal.timeout(5_000),
|
|
410
|
-
});
|
|
411
|
-
const engine = res.headers.get('x-olam-engine') ?? res.headers.get('X-Olam-Engine');
|
|
412
|
-
return { ok: engine === 'kubernetes', engineHeader: engine };
|
|
413
|
-
}
|
|
414
|
-
catch {
|
|
415
|
-
return { ok: false, engineHeader: null };
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* Step 0.4 — R3-C: create/update ghcr-pull imagePullSecret (Decision R3-#3).
|
|
420
|
-
*
|
|
421
|
-
* Creates a kubernetes.io/dockerconfigjson Secret named `ghcr-pull` in the
|
|
422
|
-
* `olam` namespace so all 5 Deployment specs (host-cp + 4 peripherals) can
|
|
423
|
-
* pull private images from ghcr.io/pleri/* without anonymous rate limits.
|
|
424
|
-
*
|
|
425
|
-
* Token resolution order:
|
|
426
|
-
* 1. deps.ghTokenOverride (test injection — ghTokenOverrideActive must be true)
|
|
427
|
-
* 2. host.gh_token in ~/.olam/config.json (operator config, not yet wired here —
|
|
428
|
-
* future: read via resolveKubectlContext deps; skipped for Phase B scope)
|
|
429
|
-
* 3. GH_TOKEN environment variable
|
|
430
|
-
*
|
|
431
|
-
* Returns { skipped: true } when no token is available (not a hard failure —
|
|
432
|
-
* operators without a GH token fall back to anonymous pulls which may rate-limit).
|
|
433
|
-
*
|
|
434
|
-
* Idempotent: `kubectl apply -f -` (stdin) is a no-op when the Secret already
|
|
435
|
-
* exists with the same content (kubectl reports "configured" or "unchanged").
|
|
436
|
-
*/
|
|
437
|
-
async function createGhcrPullSecret(context, deps, stderr) {
|
|
438
|
-
// Resolve GH token from override (test injection) or environment.
|
|
439
|
-
let ghToken;
|
|
440
|
-
if (deps.ghTokenOverrideActive === true) {
|
|
441
|
-
ghToken = deps.ghTokenOverride;
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
ghToken = process.env['GH_TOKEN'];
|
|
445
|
-
}
|
|
446
|
-
if (!ghToken) {
|
|
447
|
-
stderr.write(`${pc.yellow('[warn]')} GH_TOKEN not found — skipping ghcr-pull Secret creation.\n` +
|
|
448
|
-
` Image pulls from ghcr.io/pleri/* will use anonymous access (may rate-limit).\n` +
|
|
449
|
-
` Set GH_TOKEN env var or add host.gh_token to ~/.olam/config.json to enable.\n`);
|
|
450
|
-
return { skipped: true, reason: 'no GH_TOKEN in env or config' };
|
|
451
|
-
}
|
|
452
|
-
const dockerConfigJson = JSON.stringify({
|
|
453
|
-
auths: {
|
|
454
|
-
'ghcr.io': {
|
|
455
|
-
auth: Buffer.from(`pleri:${ghToken}`).toString('base64'),
|
|
456
|
-
},
|
|
457
|
-
},
|
|
458
|
-
});
|
|
459
|
-
const secretManifest = {
|
|
460
|
-
apiVersion: 'v1',
|
|
461
|
-
kind: 'Secret',
|
|
462
|
-
type: 'kubernetes.io/dockerconfigjson',
|
|
463
|
-
metadata: { name: 'ghcr-pull', namespace: K8S_NAMESPACE },
|
|
464
|
-
data: {
|
|
465
|
-
'.dockerconfigjson': Buffer.from(dockerConfigJson).toString('base64'),
|
|
466
|
-
},
|
|
467
|
-
};
|
|
468
|
-
const secretYaml = JSON.stringify(secretManifest); // kubectl apply accepts JSON as YAML
|
|
469
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
470
|
-
const result = await wrap(['--context', context, 'apply', '-f', '-'], { timeout: 30_000, stdin: secretYaml });
|
|
471
|
-
if (!result.ok) {
|
|
472
|
-
return { skipped: false, reason: `kubectl apply ghcr-pull failed: ${result.stderr.split('\n')[0] ?? ''}` };
|
|
473
|
-
}
|
|
474
|
-
return { skipped: false };
|
|
475
|
-
}
|
|
476
|
-
// K3D_NODE_CONTAINER, defaultCheckK3dNodeMounts, preflightK3dNodeMounts
|
|
477
|
-
// REMOVED in olam-k3d-on-mac-substrate-decision Phase B B3 (2026-05-21).
|
|
478
|
-
// They were the Decision #11 backward-compat preflight for the R3-A
|
|
479
|
-
// two-volume hostPath approach, which is fully retracted (Phase B B2).
|
|
480
|
-
// host-cp now reaches docker via TCP through the docker-socket-proxy
|
|
481
|
-
// ExternalName Service — no docker socket bind into k3d nodes at all.
|
|
482
|
-
/**
|
|
483
|
-
* Early-exit probe for healthy-cluster re-runs.
|
|
484
|
-
*
|
|
485
|
-
* Reads the host-cp image spec from the on-disk 50-deployment.yaml, queries
|
|
486
|
-
* the running deployment's current image + readyReplicas, and returns true
|
|
487
|
-
* when the cluster is already at the desired state. When true the caller
|
|
488
|
-
* prints a single skip line and exits 0 without running any of the 8 steps.
|
|
489
|
-
*
|
|
490
|
-
* Fail-open: any read/parse/kubectl error returns false (run the full flow).
|
|
491
|
-
* Only triggers when --force-refresh-manifests is NOT set.
|
|
492
|
-
*
|
|
493
|
-
* Exported for unit testing (injectable deps).
|
|
494
|
-
*/
|
|
495
|
-
export async function probeClusterAlreadyAtDesiredState(context, manifestsDir, deps) {
|
|
496
|
-
const readFileSyncImpl = deps.readFileSyncImpl ?? fs.readFileSync;
|
|
497
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
498
|
-
// 1. Read desired image from 50-deployment.yaml
|
|
499
|
-
const deploymentManifestPath = path.join(manifestsDir, '50-deployment.yaml');
|
|
500
|
-
let desiredImage = null;
|
|
501
|
-
try {
|
|
502
|
-
const raw = readFileSyncImpl(deploymentManifestPath, 'utf8');
|
|
503
|
-
// Match the main container image line: "image: <ref>@sha256:<digest>"
|
|
504
|
-
// The manifest uses `image: ghcr.io/pleri/olam-host-cp@sha256:<digest>`
|
|
505
|
-
const match = raw.match(/^\s+image:\s+(ghcr\.io\/pleri\/olam-host-cp@sha256:[a-f0-9]+)/m);
|
|
506
|
-
if (match?.[1]) {
|
|
507
|
-
desiredImage = match[1].trim();
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
catch {
|
|
511
|
-
return { atDesiredState: false, desiredDigest: null };
|
|
512
|
-
}
|
|
513
|
-
if (!desiredImage) {
|
|
514
|
-
// Could not parse desired image — fail open.
|
|
515
|
-
return { atDesiredState: false, desiredDigest: null };
|
|
516
|
-
}
|
|
517
|
-
// Extract just the digest portion for reporting.
|
|
518
|
-
const digestMatch = desiredImage.match(/sha256:[a-f0-9]+/);
|
|
519
|
-
const desiredDigest = digestMatch?.[0] ?? null;
|
|
520
|
-
// 2. Query running deployment image + readyReplicas
|
|
521
|
-
const imageResult = await wrap([
|
|
522
|
-
'--context', context,
|
|
523
|
-
'get', 'deploy', HOST_CP_DEPLOYMENT_NAME,
|
|
524
|
-
'-n', K8S_NAMESPACE,
|
|
525
|
-
'-o', `jsonpath={.spec.template.spec.containers[?(@.name=="${HOST_CP_DEPLOYMENT_NAME}")].image}`,
|
|
526
|
-
], { timeout: 10_000 });
|
|
527
|
-
if (!imageResult.ok || !imageResult.stdout.trim()) {
|
|
528
|
-
return { atDesiredState: false, desiredDigest };
|
|
529
|
-
}
|
|
530
|
-
const runningImage = imageResult.stdout.trim();
|
|
531
|
-
// 3. Check readyReplicas
|
|
532
|
-
const replicasResult = await wrap([
|
|
533
|
-
'--context', context,
|
|
534
|
-
'get', 'deploy', HOST_CP_DEPLOYMENT_NAME,
|
|
535
|
-
'-n', K8S_NAMESPACE,
|
|
536
|
-
'-o', 'jsonpath={.status.readyReplicas}',
|
|
537
|
-
], { timeout: 10_000 });
|
|
538
|
-
const readyReplicas = parseInt(replicasResult.stdout.trim() || '0', 10);
|
|
539
|
-
// 4. Cluster is at desired state iff images match AND deployment is healthy.
|
|
540
|
-
const atDesiredState = runningImage === desiredImage && readyReplicas >= 1;
|
|
541
|
-
return { atDesiredState, desiredDigest };
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Main entrypoint for the kubernetes upgrade path.
|
|
545
|
-
*
|
|
546
|
-
* Called from upgrade.ts when host.substrate === 'kubernetes'.
|
|
547
|
-
*/
|
|
548
|
-
export async function runUpgradeKubernetes(opts = {}, deps = {}) {
|
|
549
|
-
const stdout = deps.stdout ?? process.stdout;
|
|
550
|
-
const stderr = deps.stderr ?? process.stderr;
|
|
551
|
-
const manifestsDir = deps.manifestsDir ?? OLAM_K8S_MANIFESTS_DIR;
|
|
552
|
-
const startMs = Date.now();
|
|
553
|
-
// ── Pre-step 0: B5 — seed manifests from bundle if dir absent ────
|
|
554
|
-
// Closes T2/B2: ENOENT at step 2.5 (30-configmap.yaml) on fresh installs.
|
|
555
|
-
// Runs FIRST so manifests are available for all subsequent steps.
|
|
556
|
-
{
|
|
557
|
-
const seedImpl = deps.seedManifestsImpl ?? seedManifestsFromBundle;
|
|
558
|
-
const seedResult = seedImpl(opts.forceRefreshManifests === true, deps.seedManifestsDeps ?? {});
|
|
559
|
-
if (seedResult.seeded) {
|
|
560
|
-
stdout.write(`${pc.dim('[seed]')} ${seedResult.message}\n`);
|
|
561
|
-
}
|
|
562
|
-
else if (!seedResult.skipped) {
|
|
563
|
-
// Hard error: copy failed (permission denied, ENOSPC, etc.).
|
|
564
|
-
stderr.write(`${pc.red('error:')} Manifest seed failed: ${seedResult.error}\n`);
|
|
565
|
-
return { exitCode: 1, summary: 'manifest seed failed' };
|
|
566
|
-
}
|
|
567
|
-
// skipped: dir exists or bundle absent (dev context) — no output, continue.
|
|
568
|
-
}
|
|
569
|
-
// ── Pre-step 0b: early-exit probe — skip all 8 steps on healthy re-run ──
|
|
570
|
-
// Reads desired host-cp image from 50-deployment.yaml, compares to running
|
|
571
|
-
// deployment. When they match AND readyReplicas >= 1, nothing has changed:
|
|
572
|
-
// all 8 steps are no-ops, so we skip them and report in <1s.
|
|
573
|
-
// Only active when --force-refresh-manifests is NOT set (that flag is the
|
|
574
|
-
// explicit "re-run everything" escape hatch).
|
|
575
|
-
if (!opts.forceRefreshManifests) {
|
|
576
|
-
// Need a context for the probe — resolve it first with a lightweight helper.
|
|
577
|
-
const earlyCtxResolved = resolveKubectlContext(deps.configPath);
|
|
578
|
-
let earlyCtx = null;
|
|
579
|
-
if (earlyCtxResolved.error === undefined) {
|
|
580
|
-
earlyCtx = earlyCtxResolved.context;
|
|
581
|
-
}
|
|
582
|
-
else {
|
|
583
|
-
// Try auto-pin (same logic as the main flow below).
|
|
584
|
-
const autoPin = (deps.autoPinImpl ?? autoPinKubectlContext)({ configPath: deps.configPath });
|
|
585
|
-
if (autoPin.context !== undefined) {
|
|
586
|
-
earlyCtx = autoPin.context;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
if (earlyCtx !== null) {
|
|
590
|
-
const probe = await probeClusterAlreadyAtDesiredState(earlyCtx, manifestsDir, deps);
|
|
591
|
-
if (probe.atDesiredState) {
|
|
592
|
-
const digest = probe.desiredDigest ?? '(unknown)';
|
|
593
|
-
stdout.write(`${pc.green('✓')} cluster already at desired state — host-cp ${pc.dim(digest)} ready, skipping 8-step flow\n`);
|
|
594
|
-
// Still emit the instrumentation event so dashboards track re-runs.
|
|
595
|
-
const emitImpl = deps.emitImpl ?? emitUpgradeComplete;
|
|
596
|
-
emitImpl({
|
|
597
|
-
substrate: 'kubernetes',
|
|
598
|
-
duration_ms: Date.now() - startMs,
|
|
599
|
-
flavor: 'k3s',
|
|
600
|
-
skipped: true,
|
|
601
|
-
}, deps.emitOpts ?? {});
|
|
602
|
-
return { exitCode: 0, summary: `cluster already at desired state (host-cp ${digest})` };
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
// ── Step 0.4: R3-C — create/update ghcr-pull imagePullSecret ────────
|
|
607
|
-
// RELOCATED (R4-W2-A): this step previously ran before ensureK8sBootstrap,
|
|
608
|
-
// but the `olam` namespace doesn't exist yet on a fresh cluster — `kubectl
|
|
609
|
-
// apply` failed with `namespaces "olam" not found` and `(continuing)`
|
|
610
|
-
// silently dropped the secret. Subsequent host-cp rollouts then 401'd on
|
|
611
|
-
// image pull. Step 0.4 now runs AFTER Step 0.5 (B4 bootstrap creates the
|
|
612
|
-
// namespace + RBAC) — see below.
|
|
613
|
-
// Step 0.5 REMOVED in olam-k3d-on-mac-substrate-decision Phase B B3
|
|
614
|
-
// (2026-05-21). The k3d node docker socket bind-mount preflight checked
|
|
615
|
-
// whether the cluster was created with the R3-A two-volume hostPath form,
|
|
616
|
-
// which is fully retracted in Phase B B2. There is no longer any docker
|
|
617
|
-
// socket binding into k3d node containers — host-cp reaches docker via
|
|
618
|
-
// TCP through the docker-socket-proxy ExternalName Service, served by a
|
|
619
|
-
// host-side proxy container started by Step 0.7. No preflight needed.
|
|
620
|
-
// ── Pre-step 0a-prelude: B3 — resolve kubectl context ONCE (config + env) ──
|
|
621
|
-
// The context is needed by ALL kubectl-invoking pre-steps and steps below.
|
|
622
|
-
// Resolution policy lives in `kubectl-context.ts` (single source of truth):
|
|
623
|
-
// 1. host.kubectl_context_pinned from ~/.olam/config.json (preferred)
|
|
624
|
-
// 2. OLAM_K8S_CONTEXT_ACK env var (deprecated, emits warning)
|
|
625
|
-
// 3. neither → error with actionable remediation
|
|
626
|
-
//
|
|
627
|
-
// Pre-B3 bug: step 0 read OLAM_K8S_CONTEXT_ACK directly and fell back to
|
|
628
|
-
// 'default' when unset, so operators who had only pinned the config got
|
|
629
|
-
// cryptic `cluster-info failed` failures pointing at the wrong remediation.
|
|
630
|
-
const resolved = resolveKubectlContext(deps.configPath);
|
|
631
|
-
let pinnedContext;
|
|
632
|
-
if (resolved.error !== undefined) {
|
|
633
|
-
// No pin and no ACK — instead of dead-ending, try to auto-pin an
|
|
634
|
-
// unambiguous k3d-olam-* context (canonical k3d-olam-host or a sole
|
|
635
|
-
// match) and persist it. Only when auto-pin is also ambiguous do we
|
|
636
|
-
// surface an error — now listing the candidate contexts + the exact
|
|
637
|
-
// `olam config set` command rather than a generic "set it manually".
|
|
638
|
-
const autoPin = (deps.autoPinImpl ?? autoPinKubectlContext)({ configPath: deps.configPath });
|
|
639
|
-
if (autoPin.error !== undefined || autoPin.context === undefined) {
|
|
640
|
-
stderr.write(`${pc.red('error:')} ${autoPin.error ?? resolved.error}\n`);
|
|
641
|
-
return { exitCode: 1, summary: 'kubectl context not configured' };
|
|
642
|
-
}
|
|
643
|
-
pinnedContext = autoPin.context;
|
|
644
|
-
if (autoPin.autoPinnedMessage !== undefined) {
|
|
645
|
-
stderr.write(`${pc.cyan('[auto-pin]')} ${autoPin.autoPinnedMessage}\n`);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
else {
|
|
649
|
-
pinnedContext = resolved.context;
|
|
650
|
-
if (resolved.deprecationWarning !== undefined) {
|
|
651
|
-
stderr.write(`${pc.yellow('[warn]')} ${resolved.deprecationWarning}\n`);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
// ── Pre-step 0a: D6 — managed-k8s context refusal (Decision #18) ──────
|
|
655
|
-
// Detects managed-k8s cluster server URL patterns and refuses BEFORE any
|
|
656
|
-
// kubectl apply. Fail-open: unrecognized cluster URLs proceed normally.
|
|
657
|
-
{
|
|
658
|
-
const managedProvider = await detectManagedK8sProvider(deps);
|
|
659
|
-
if (managedProvider !== null) {
|
|
660
|
-
stderr.write(`${pc.red('error:')} olam upgrade supports local k3d/k3s clusters only.\n` +
|
|
661
|
-
` Detected managed-k8s context: ${managedProvider}\n` +
|
|
662
|
-
` hostPath /var/run/docker.sock is not accessible on managed clusters — the docker\n` +
|
|
663
|
-
` socket does not reach the operator's host daemon on cloud-managed nodes.\n` +
|
|
664
|
-
` See Decision #18 and docs/operator/kubernetes-substrate-beta.md\n` +
|
|
665
|
-
` for supported cluster types and the active retraction of managed-k8s support.\n`);
|
|
666
|
-
return { exitCode: 1, summary: 'managed-k8s context detected (Decision #18 retraction)' };
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
// Pre-step 0b D7 (docker socket bind-mount preflight) REMOVED in
|
|
670
|
-
// olam-k3d-on-mac-substrate-decision Phase B B3 (2026-05-21). The
|
|
671
|
-
// preflight checked /var/run/docker.sock inside host-cp via `kubectl exec`,
|
|
672
|
-
// which is obsolete: host-cp no longer has a docker socket volumeMount
|
|
673
|
-
// (see packages/host-cp/k8s/manifests/50-deployment.yaml). Docker access
|
|
674
|
-
// is via TCP to docker-socket-proxy. Step 0.7 (above) handles the new
|
|
675
|
-
// substrate's UX; the doctor probe for proxy reachability lives in
|
|
676
|
-
// Phase C C1.
|
|
677
|
-
// ── Step 0: D22 — probe Kubernetes API reachability (5s) ─────────
|
|
678
|
-
const step0Spinner = ora('Probing Kubernetes API reachability').start();
|
|
679
|
-
const reachable = await probeKubernetesApiReachable(pinnedContext, deps);
|
|
680
|
-
if (!reachable) {
|
|
681
|
-
step0Spinner.fail('Kubernetes API not reachable');
|
|
682
|
-
stderr.write(`${pc.red('error:')} kubectl cluster-info failed (5s timeout) for context ${pc.bold(pinnedContext)}.\n` +
|
|
683
|
-
` Ensure the cluster is reachable for this context, or update host.kubectl_context_pinned\n` +
|
|
684
|
-
` in ~/.olam/config.json to a working context.\n`);
|
|
685
|
-
return { exitCode: 1, summary: 'kubernetes api not reachable' };
|
|
686
|
-
}
|
|
687
|
-
step0Spinner.succeed('Kubernetes API reachable');
|
|
688
|
-
// ── Step 0.5: B4 — ensureK8sBootstrap ────────────────────────────
|
|
689
|
-
// Apply namespace + RBAC + ConfigMap + PVC + Secret set BEFORE the
|
|
690
|
-
// existing 8-step flow's step 2 Secret pre-check. Without this an npm-only
|
|
691
|
-
// operator running `olam upgrade --substrate=kubernetes` against a fresh
|
|
692
|
-
// cluster hit "namespaces \"olam\" not found" / "Secret olam-host-cp-secret
|
|
693
|
-
// not found". Idempotent: reapply on subsequent runs reuses tokens from
|
|
694
|
-
// ~/.olam/k8s-secrets-state.json so worlds with cached values don't break.
|
|
695
|
-
// --rotate-secrets opts in to fresh value generation.
|
|
696
|
-
if (opts.runK8sBootstrap === true) {
|
|
697
|
-
const step05Spinner = ora('Bootstrapping olam namespace + RBAC + secrets (B4)').start();
|
|
698
|
-
const bootstrapImpl = deps.k8sBootstrapImpl ?? ensureK8sBootstrap;
|
|
699
|
-
// Thread the same kubectlWrap that the rest of upgrade-kubernetes uses so
|
|
700
|
-
// existing tests that inject `kubectlWrapImpl` don't reach the real kubectl
|
|
701
|
-
// binary via the bootstrap module's default.
|
|
702
|
-
const bootstrap = await bootstrapImpl({
|
|
703
|
-
context: pinnedContext,
|
|
704
|
-
namespace: K8S_NAMESPACE,
|
|
705
|
-
rotateSecrets: opts.rotateSecrets === true,
|
|
706
|
-
}, {
|
|
707
|
-
kubectlWrapImpl: deps.kubectlWrapImpl,
|
|
708
|
-
// Route per-manifest progress through spinner.text so each file
|
|
709
|
-
// updates in-place instead of printing a new line (B4 spam fix).
|
|
710
|
-
onProgress: (label) => {
|
|
711
|
-
step05Spinner.text = `Bootstrapping olam namespace + RBAC + secrets (B4)${label}`;
|
|
712
|
-
},
|
|
713
|
-
...(deps.k8sBootstrapDeps ?? {}),
|
|
714
|
-
});
|
|
715
|
-
if (bootstrap.exitCode !== 0) {
|
|
716
|
-
step05Spinner.fail('k8s bootstrap failed');
|
|
717
|
-
stderr.write(`${pc.red('error:')} ${bootstrap.error ?? 'unknown bootstrap error'}\n`);
|
|
718
|
-
return { exitCode: 1, summary: 'k8s bootstrap failed' };
|
|
719
|
-
}
|
|
720
|
-
const appliedCount = bootstrap.result.applied.length;
|
|
721
|
-
const skippedCount = bootstrap.result.skipped.length;
|
|
722
|
-
const note = skippedCount > 0 ? ` (${skippedCount} skipped — see warnings above)` : '';
|
|
723
|
-
step05Spinner.succeed(`k8s bootstrap: ${appliedCount} applied${note}`);
|
|
724
|
-
}
|
|
725
|
-
// ── Step 0.6: R3-C — create/update ghcr-pull imagePullSecret ────────
|
|
726
|
-
// Relocated from before Step 0.5 (see R4-W2-A retest finding). Must run
|
|
727
|
-
// AFTER ensureK8sBootstrap because the secret is namespaced to `olam` and
|
|
728
|
-
// ensureK8sBootstrap is what creates that namespace on a fresh cluster.
|
|
729
|
-
//
|
|
730
|
-
// Failure mode is still soft-warn rather than abort: rollouts that depend
|
|
731
|
-
// on the secret (private GHCR image pulls) surface their own clear 401
|
|
732
|
-
// ImagePullBackOff downstream, which is preferable to blocking operators
|
|
733
|
-
// who don't have GH_TOKEN configured but also aren't pulling private
|
|
734
|
-
// images (e.g. local dev with mirrored public copies).
|
|
735
|
-
{
|
|
736
|
-
const step06Spinner = ora('Creating ghcr-pull imagePullSecret (R3-C)').start();
|
|
737
|
-
const pullSecretResult = await createGhcrPullSecret(pinnedContext, deps, stderr);
|
|
738
|
-
if (pullSecretResult.skipped) {
|
|
739
|
-
step06Spinner.warn(`ghcr-pull Secret skipped: ${pullSecretResult.reason ?? 'no token'}`);
|
|
740
|
-
}
|
|
741
|
-
else if (pullSecretResult.reason) {
|
|
742
|
-
const warnMsg = `ghcr-pull Secret apply failed (continuing): ${pullSecretResult.reason}`;
|
|
743
|
-
step06Spinner.warn(warnMsg);
|
|
744
|
-
stderr.write(`${pc.yellow('[warn]')} ${warnMsg}\n`);
|
|
745
|
-
}
|
|
746
|
-
else {
|
|
747
|
-
step06Spinner.succeed('ghcr-pull imagePullSecret created/updated');
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
// ── Step 0.7: olam-k3d-on-mac-substrate-decision Phase A — host-side ────
|
|
751
|
-
// docker-socket-proxy auto-start on macOS (Decisions #1 + #3 + #7).
|
|
752
|
-
//
|
|
753
|
-
// Resolves R4-W2-F: on macOS + colima + virtiofs, containerd's OCI runtime
|
|
754
|
-
// spec generator calls stat() on docker.sock hostPath bind mounts; virtiofs
|
|
755
|
-
// returns ENOTSUP on stat/statx for socket files. The R3-A two-volume
|
|
756
|
-
// hostPath approach is unrecoverable. This step routes around it by
|
|
757
|
-
// ensuring a host-side `tecnativa/docker-socket-proxy` container is
|
|
758
|
-
// running on the operator's docker daemon (sibling to k3d). The
|
|
759
|
-
// in-cluster Service (packages/host-cp/k8s/manifests/docker-socket-proxy/
|
|
760
|
-
// 60-service.yaml) is `type: ExternalName` aliased to host.k3d.internal,
|
|
761
|
-
// which routes traffic to this host-side container.
|
|
762
|
-
//
|
|
763
|
-
// Decision #7 (Universal): runs on all host OSes regardless of substrate.
|
|
764
|
-
// This means Linux operators also get the proxy. The per-Pod cost is
|
|
765
|
-
// invisible against the maintenance tax of OS-conditional Service generation.
|
|
766
|
-
//
|
|
767
|
-
// Idempotent: `docker compose up -d` on a running container is a no-op
|
|
768
|
-
// success. Failure surfaces an actionable remediation string but does
|
|
769
|
-
// NOT abort the upgrade — host-cp will then fail at Step 4 rollout with
|
|
770
|
-
// a clearer "proxy unreachable" symptom that the new doctor probe
|
|
771
|
-
// (olam-k3d-on-mac-substrate-decision Phase C C1) diagnoses.
|
|
772
|
-
if (process.platform === 'darwin') {
|
|
773
|
-
const step07Spinner = ora('Starting host-side docker-socket-proxy (R4-W2-F)').start();
|
|
774
|
-
const composePath = resolveHostSideProxyComposePath();
|
|
775
|
-
if (composePath === null) {
|
|
776
|
-
step07Spinner.warn('host-side docker-socket-proxy compose yaml not found (bundle layout?)');
|
|
777
|
-
stderr.write(`${pc.yellow('[warn]')} could not locate docker-socket-proxy.compose.yaml in the bundled k8s assets.\n` +
|
|
778
|
-
` This is a packaging bug — please report. Continuing without auto-start.\n`);
|
|
779
|
-
}
|
|
780
|
-
else {
|
|
781
|
-
const startResult = startHostSideProxy(composePath);
|
|
782
|
-
if (!startResult.ok) {
|
|
783
|
-
step07Spinner.warn(`host-side docker-socket-proxy start failed (continuing): ${startResult.reason ?? 'unknown'}`);
|
|
784
|
-
stderr.write(`${pc.yellow('[warn]')} ${startResult.reason ?? 'unknown error'}\n`);
|
|
785
|
-
}
|
|
786
|
-
else {
|
|
787
|
-
step07Spinner.succeed('docker-socket-proxy ready on host');
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
// ── Step 1: D10 — context-allowlist validation ───────────────────
|
|
792
|
-
// The context was already resolved (config-first, env-fallback) before
|
|
793
|
-
// pre-step 0a. Step 1 keeps the D10 allowlist gate + the audit WARN so
|
|
794
|
-
// observability of which context is being used is preserved.
|
|
795
|
-
const step1Spinner = ora('Verifying kubectl context (D10)').start();
|
|
796
|
-
if (!isContextAllowed(pinnedContext)) {
|
|
797
|
-
step1Spinner.fail('Context disallowed');
|
|
798
|
-
stderr.write(`${pc.red('error:')} kubectl context ${pc.bold(pinnedContext)} is not allowed by the D10 allowlist.\n` +
|
|
799
|
-
` See GATES.md G-001 for the context-allowlist requirement.\n`);
|
|
800
|
-
return { exitCode: 1, summary: 'context disallowed' };
|
|
801
|
-
}
|
|
802
|
-
// Audit WARN on bypass (D10: operator explicitly acknowledged a potentially unsafe context).
|
|
803
|
-
process.stderr.write(`${pc.yellow('[WARN]')} OLAM_K8S_UNSAFE_CONTEXT_ACK ctx=${pinnedContext}\n`);
|
|
804
|
-
step1Spinner.succeed(`Context pinned: ${pc.bold(pinnedContext)}`);
|
|
805
|
-
// ── D14: --force-refresh-manifests flag ──────────────────────────
|
|
806
|
-
if (opts.forceRefreshManifests) {
|
|
807
|
-
const step14Spinner = ora('Refreshing manifests (D14)').start();
|
|
808
|
-
const refreshImpl = deps.manifestRefreshImpl ?? runManifestRefresh;
|
|
809
|
-
const refreshResult = await refreshImpl(manifestsDir, opts.acceptSecurityRegression === true, {});
|
|
810
|
-
if (!refreshResult.ok) {
|
|
811
|
-
step14Spinner.fail('Manifest refresh refused');
|
|
812
|
-
stderr.write(`${pc.red('error:')} ${refreshResult.message}\n`);
|
|
813
|
-
return { exitCode: 1, summary: 'manifest refresh refused' };
|
|
814
|
-
}
|
|
815
|
-
step14Spinner.succeed(refreshResult.message);
|
|
816
|
-
}
|
|
817
|
-
// ── Step 2: D12 — Secret pre-check ───────────────────────────────
|
|
818
|
-
const step2Spinner = ora(`Checking Secret ${HOST_CP_SECRET_NAME} (D12)`).start();
|
|
819
|
-
const secretError = await checkSecretPreCondition(pinnedContext, deps);
|
|
820
|
-
if (secretError !== null) {
|
|
821
|
-
step2Spinner.fail('Secret pre-check failed');
|
|
822
|
-
stderr.write(`${pc.red('error:')} ${secretError}\n`);
|
|
823
|
-
return { exitCode: 1, summary: 'secret pre-check failed' };
|
|
824
|
-
}
|
|
825
|
-
step2Spinner.succeed(`Secret ${HOST_CP_SECRET_NAME} verified`);
|
|
826
|
-
// ── D5: Phase 2 GA — OLAM_PHASE_2_BETA guard removed (D27) ──────
|
|
827
|
-
// Emit phase2.flag_removed audit log entry per upgrade run (D27).
|
|
828
|
-
appendSubstrateAuditEntry({
|
|
829
|
-
ts: new Date(deps.nowImpl ? deps.nowImpl() : Date.now()).toISOString(),
|
|
830
|
-
op: 'upgrade',
|
|
831
|
-
substrate: 'kubernetes',
|
|
832
|
-
phase2: { flag_removed: true },
|
|
833
|
-
}, stderr);
|
|
834
|
-
// ── Step 2.6: C2 — per-peripheral Secret pre-check ──────────────
|
|
835
|
-
const step26Spinner = ora('Checking peripheral Secrets (C2)').start();
|
|
836
|
-
const peripheralSecretError = await checkPeripheralSecrets(pinnedContext, deps);
|
|
837
|
-
if (peripheralSecretError !== null) {
|
|
838
|
-
step26Spinner.fail('Peripheral Secret pre-check failed');
|
|
839
|
-
stderr.write(`${pc.red('error:')} ${peripheralSecretError}\n`);
|
|
840
|
-
return { exitCode: 1, summary: 'peripheral secret pre-check failed' };
|
|
841
|
-
}
|
|
842
|
-
step26Spinner.succeed('All peripheral Secrets verified');
|
|
843
|
-
// ── Step 2.7: C3 — CoreDNS warm-up wait ────────────────────────
|
|
844
|
-
const step27Spinner = ora('Waiting for CoreDNS (C3, 30s timeout)').start();
|
|
845
|
-
const coreDnsOk = await waitForCoreDns(pinnedContext, deps);
|
|
846
|
-
if (!coreDnsOk) {
|
|
847
|
-
step27Spinner.warn('CoreDNS not Available within 30s — continuing (DNS may be degraded)');
|
|
848
|
-
}
|
|
849
|
-
else {
|
|
850
|
-
step27Spinner.succeed('CoreDNS Available');
|
|
851
|
-
}
|
|
852
|
-
// ── Step 3: kubectl apply ─────────────────────────────────────────
|
|
853
|
-
const step3Spinner = ora('Applying manifests').start();
|
|
854
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
855
|
-
// Always apply host-cp manifests (top-level manifests dir).
|
|
856
|
-
// kubectl -f <dir> does NOT recurse by default — peripheral subdirs are ignored here.
|
|
857
|
-
const applyResult = await wrap(['--context', pinnedContext, 'apply', '-f', manifestsDir], { timeout: 120_000 });
|
|
858
|
-
if (!applyResult.ok) {
|
|
859
|
-
step3Spinner.fail('kubectl apply failed');
|
|
860
|
-
stderr.write(`${pc.red('error:')} kubectl apply failed (exit ${applyResult.exitCode}):\n` +
|
|
861
|
-
` ${applyResult.stderr.split('\n').slice(0, 5).join('\n ')}\n`);
|
|
862
|
-
return { exitCode: 1, summary: 'kubectl apply failed' };
|
|
863
|
-
}
|
|
864
|
-
// Apply each peripheral's manifest directory (alphabetical order).
|
|
865
|
-
const peripheralNames = [...PERIPHERALS.map((p) => p.name)].sort();
|
|
866
|
-
for (const name of peripheralNames) {
|
|
867
|
-
const peripheralManifestsDir = path.join(manifestsDir, name);
|
|
868
|
-
const peripheralApplyResult = await wrap(['--context', pinnedContext, 'apply', '-f', peripheralManifestsDir], { timeout: 120_000 });
|
|
869
|
-
if (!peripheralApplyResult.ok) {
|
|
870
|
-
step3Spinner.fail(`kubectl apply failed for peripheral "${name}"`);
|
|
871
|
-
stderr.write(`${pc.red('error:')} kubectl apply failed for peripheral "${name}" (exit ${peripheralApplyResult.exitCode}):\n` +
|
|
872
|
-
` ${peripheralApplyResult.stderr.split('\n').slice(0, 5).join('\n ')}\n`);
|
|
873
|
-
return { exitCode: 1, summary: `kubectl apply failed for peripheral ${name}` };
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
step3Spinner.succeed('All manifests applied (host-cp + 4 peripherals)');
|
|
877
|
-
// ── Step 3.5: C1 — in-memory ConfigMap substitution (K8s DNS URLs) ──
|
|
878
|
-
// B7 fix: applied AFTER step 3's bulk kubectl apply -f manifestsDir so the
|
|
879
|
-
// patched ConfigMap is the last write (kubectl last-write-wins). The on-disk
|
|
880
|
-
// 30-configmap.yaml carries compose-substrate URLs; step 3 applies them then
|
|
881
|
-
// step 3.5 overwrites with K8s DNS form. Decision #3.
|
|
882
|
-
const step35Spinner = ora('Re-applying patched ConfigMap with K8s DNS URLs (C1/D4 — B7 fix)').start();
|
|
883
|
-
const configMapError = await applyConfigMapSubstitution(pinnedContext, manifestsDir, deps);
|
|
884
|
-
if (configMapError !== null) {
|
|
885
|
-
step35Spinner.fail('ConfigMap substitution failed');
|
|
886
|
-
stderr.write(`${pc.red('error:')} ${configMapError}\n`);
|
|
887
|
-
return { exitCode: 1, summary: 'configmap substitution failed' };
|
|
888
|
-
}
|
|
889
|
-
step35Spinner.succeed('ConfigMap patched with K8s DNS URLs (survives bulk apply)');
|
|
890
|
-
// ── Step 4: D15 — kubectl rollout status (300s timeout, 305s wrap) ──
|
|
891
|
-
// 300s budget — fresh clusters do TWO rollouts per deployment: bootstrap apply
|
|
892
|
-
// (with manifest-default images) then upgrade patch (with canonical
|
|
893
|
-
// image-digests.json refs), which triggers a second replicaset rollout
|
|
894
|
-
// including a fresh image pull. With cold images at GHCR (host-cp ~380MB,
|
|
895
|
-
// memory-service ~610MB) the combined pull+ready timeline lands close to
|
|
896
|
-
// 180s on CI runners. Bumped from 180s to 300s for headroom.
|
|
897
|
-
const step4Spinner = ora('Waiting for rollout (all 5 deployments, 300s each)').start();
|
|
898
|
-
const deploymentNames = [
|
|
899
|
-
HOST_CP_DEPLOYMENT_NAME,
|
|
900
|
-
...PERIPHERALS.map((p) => p.k8sResourceName),
|
|
901
|
-
];
|
|
902
|
-
const rolloutResults = await Promise.all(deploymentNames.map((deploymentName) => (deps.kubectlWrapImpl ?? kubectlWrap)([
|
|
903
|
-
'--context', pinnedContext,
|
|
904
|
-
'rollout', 'status',
|
|
905
|
-
`deployment/${deploymentName}`,
|
|
906
|
-
'-n', K8S_NAMESPACE,
|
|
907
|
-
'--timeout=300s',
|
|
908
|
-
], { timeout: 305_000 })));
|
|
909
|
-
const failedDeployments = deploymentNames.filter((_, i) => !rolloutResults[i]?.ok);
|
|
910
|
-
if (failedDeployments.length > 0) {
|
|
911
|
-
step4Spinner.fail(`Rollout failed for: ${failedDeployments.join(', ')}`);
|
|
912
|
-
// Emit state snapshot for failed deployments (mirrors D15 pattern).
|
|
913
|
-
for (const [i, name] of failedDeployments.entries()) {
|
|
914
|
-
const result = rolloutResults[deploymentNames.indexOf(name)];
|
|
915
|
-
stderr.write(`${pc.red('error:')} rollout status failed for deployment/${name}.\n`);
|
|
916
|
-
// Emit the actual kubectl output so CI logs show the failure reason.
|
|
917
|
-
if (result && (result.stdout || result.stderr)) {
|
|
918
|
-
stderr.write(`${pc.dim('--- kubectl rollout status output ---')}\n`);
|
|
919
|
-
if (result.stdout)
|
|
920
|
-
stderr.write(result.stdout + '\n');
|
|
921
|
-
if (result.stderr)
|
|
922
|
-
stderr.write(result.stderr + '\n');
|
|
923
|
-
stderr.write(`${pc.dim(`exit code: ${result.exitCode ?? '(none)'}, reason: ${'reason' in result ? result.reason : 'ok'}`)}\n`);
|
|
924
|
-
}
|
|
925
|
-
void i; // suppress unused-var lint
|
|
926
|
-
stderr.write(`${pc.dim(`--- kubectl get pods -n ${K8S_NAMESPACE} -o wide ---`)}\n`);
|
|
927
|
-
const podsResult = await wrap(['--context', pinnedContext, 'get', 'pods', '-n', K8S_NAMESPACE, '-o', 'wide'], { timeout: 10_000 });
|
|
928
|
-
stderr.write((podsResult.stdout || podsResult.stderr || '(no output)') + '\n');
|
|
929
|
-
}
|
|
930
|
-
stderr.write(`\n${pc.yellow('note:')} Manifests are NOT auto-rolled-back. Inspect the state above and remediate manually.\n`);
|
|
931
|
-
return { exitCode: 1, summary: 'rollout status timed out' };
|
|
932
|
-
}
|
|
933
|
-
step4Spinner.succeed('All 5 deployments rolled out');
|
|
934
|
-
// ── Step 5: D17 — port-forward spawn via flock ───────────────────
|
|
935
|
-
// Spawn host-cp and all peripheral port-forwards in parallel.
|
|
936
|
-
const step5Spinner = ora('Establishing port-forward').start();
|
|
937
|
-
const pfSpawn = deps.spawnPortForwardImpl ?? spawnPortForward;
|
|
938
|
-
const spawnAllPeripheral = deps.spawnAllPeripheralPortForwardsImpl ?? spawnAllPeripheralPortForwards;
|
|
939
|
-
const [pfResult] = await Promise.all([
|
|
940
|
-
pfSpawn(pinnedContext, K8S_NAMESPACE, PORT_FORWARD_TARGET, 19000, 19000, deps.portForwardDeps ?? {}),
|
|
941
|
-
spawnAllPeripheral(pinnedContext, K8S_NAMESPACE, deps.peripheralPortForwardDeps ?? {}),
|
|
942
|
-
]);
|
|
943
|
-
if (pfResult.spawned) {
|
|
944
|
-
step5Spinner.succeed(`Port-forward spawned (pid ${pfResult.pid}) + all peripheral port-forwards`);
|
|
945
|
-
}
|
|
946
|
-
else if (pfResult.reason === 'live') {
|
|
947
|
-
step5Spinner.succeed('Port-forward already live + peripheral port-forwards spawned');
|
|
948
|
-
}
|
|
949
|
-
else {
|
|
950
|
-
step5Spinner.warn('Port-forward lock held by concurrent caller; skipping spawn');
|
|
951
|
-
}
|
|
952
|
-
// Brief wait for port-forward tunnel to be ready before health check.
|
|
953
|
-
const sleep = deps.sleepImpl ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
954
|
-
await sleep(1_500);
|
|
955
|
-
// ── Step 6: verify /health returns X-Olam-Engine: kubernetes ─────
|
|
956
|
-
const step6Spinner = ora('Verifying host-cp health (X-Olam-Engine: kubernetes)').start();
|
|
957
|
-
const healthCheck = await verifyHealthHeader(deps);
|
|
958
|
-
if (!healthCheck.ok) {
|
|
959
|
-
step6Spinner.fail(healthCheck.engineHeader !== null
|
|
960
|
-
? `X-Olam-Engine header is "${healthCheck.engineHeader}" (expected "kubernetes")`
|
|
961
|
-
: 'host-cp /health not reachable via port-forward');
|
|
962
|
-
if (healthCheck.engineHeader === 'docker') {
|
|
963
|
-
// A compose-era docker `olam-host-cp` container is squatting
|
|
964
|
-
// 127.0.0.1:19000, so the k8s port-forward could not bind it and the
|
|
965
|
-
// probe hit the docker container. Name the real cause + the fix.
|
|
966
|
-
stderr.write(`${pc.red('error:')} 127.0.0.1:19000 is being served by a compose-era docker host-cp,\n` +
|
|
967
|
-
` not the kubernetes deployment — the docker container is squatting the port so the\n` +
|
|
968
|
-
` k8s port-forward could not bind it. Stop it, then re-run upgrade:\n` +
|
|
969
|
-
` olam host-cp stop\n` +
|
|
970
|
-
` olam upgrade\n`);
|
|
971
|
-
}
|
|
972
|
-
else {
|
|
973
|
-
stderr.write(`${pc.red('error:')} host-cp did not report engine=kubernetes.\n` +
|
|
974
|
-
` The /health port-forward succeeded but no X-Olam-Engine header was returned —\n` +
|
|
975
|
-
` usually means the pod isn't Ready yet, is crashlooping, or failed to pull its image.\n` +
|
|
976
|
-
` Pod-state diagnostics follow (share the FULL block when asking for help):\n`);
|
|
977
|
-
// Surface the actual pod state. The two commands below are read-only +
|
|
978
|
-
// safe to run multiple times. Output is captured + redirected to stderr
|
|
979
|
-
// so the operator sees it inline with the failure.
|
|
980
|
-
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
981
|
-
try {
|
|
982
|
-
const getPods = await wrap(['-n', 'olam', 'get', 'pods', '-l', 'app=olam-host-cp', '-o', 'wide'], { timeout: 5_000 });
|
|
983
|
-
stderr.write(`\n${pc.dim('--- kubectl -n olam get pods -l app=olam-host-cp ---')}\n` +
|
|
984
|
-
`${getPods.stdout || getPods.stderr || '(no output)'}\n`);
|
|
985
|
-
const describe = await wrap(['-n', 'olam', 'describe', 'pod', '-l', 'app=olam-host-cp'], { timeout: 5_000 });
|
|
986
|
-
// Tail the last 40 lines — Events block sits at the bottom and is
|
|
987
|
-
// the highest-signal slice (ImagePullBackOff / FailedScheduling /
|
|
988
|
-
// CrashLoopBackOff all surface there).
|
|
989
|
-
const tail = (describe.stdout || '').split('\n').slice(-40).join('\n');
|
|
990
|
-
stderr.write(`\n${pc.dim('--- kubectl -n olam describe pod (tail 40 lines, includes Events) ---')}\n` +
|
|
991
|
-
`${tail || '(no output)'}\n\n`);
|
|
992
|
-
}
|
|
993
|
-
catch (err) {
|
|
994
|
-
stderr.write(` ${pc.dim('(kubectl diagnostics unavailable: ' + err.message + ')')}\n`);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
return { exitCode: 1, summary: 'health check failed — engine mismatch' };
|
|
998
|
-
}
|
|
999
|
-
step6Spinner.succeed('host-cp reports X-Olam-Engine: kubernetes');
|
|
1000
|
-
// ── Step 7: emit upgrade.complete instrumentation event ───────────
|
|
1001
|
-
const emitImpl = deps.emitImpl ?? emitUpgradeComplete;
|
|
1002
|
-
emitImpl({
|
|
1003
|
-
substrate: 'kubernetes',
|
|
1004
|
-
duration_ms: Date.now() - startMs,
|
|
1005
|
-
flavor: 'k3s',
|
|
1006
|
-
}, deps.emitOpts ?? {});
|
|
1007
|
-
// ── Step 8: success message ────────────────────────────────────────
|
|
1008
|
-
printSuccess('olam upgrade (kubernetes) complete');
|
|
1009
|
-
stdout.write(` context: ${pc.bold(pinnedContext)}\n`);
|
|
1010
|
-
stdout.write(` substrate: ${pc.bold('kubernetes')} (flavor=k3s)\n`);
|
|
1011
|
-
stdout.write(` port-forward: 127.0.0.1:19000 → ${PORT_FORWARD_TARGET}\n`);
|
|
1012
|
-
return { exitCode: 0, summary: 'kubernetes upgrade complete' };
|
|
1013
|
-
}
|
|
1014
|
-
//# sourceMappingURL=upgrade-kubernetes.js.map
|