@pleri/olam-cli 0.1.147 → 0.1.150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/agent-stream/agent-sdk-to-chunks.js +276 -0
  2. package/dist/agent-stream/agent-stream-launch.js +348 -0
  3. package/dist/agent-stream/chunks-subscriber-transport.js +262 -0
  4. package/dist/agent-stream/codex-runner.js +188 -0
  5. package/dist/agent-stream/driver-runner.js +347 -0
  6. package/dist/agent-stream/operator-subscription.js +179 -0
  7. package/dist/commands/auth.d.ts.map +1 -1
  8. package/dist/commands/auth.js +26 -1
  9. package/dist/commands/auth.js.map +1 -1
  10. package/dist/commands/create.d.ts.map +1 -1
  11. package/dist/commands/create.js +39 -0
  12. package/dist/commands/create.js.map +1 -1
  13. package/dist/commands/doctor.d.ts +54 -3
  14. package/dist/commands/doctor.d.ts.map +1 -1
  15. package/dist/commands/doctor.js +348 -6
  16. package/dist/commands/doctor.js.map +1 -1
  17. package/dist/commands/init.d.ts +46 -0
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +90 -0
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/kg-build.d.ts +23 -0
  22. package/dist/commands/kg-build.d.ts.map +1 -1
  23. package/dist/commands/kg-build.js +104 -2
  24. package/dist/commands/kg-build.js.map +1 -1
  25. package/dist/commands/restart.d.ts +18 -0
  26. package/dist/commands/restart.d.ts.map +1 -0
  27. package/dist/commands/restart.js +113 -0
  28. package/dist/commands/restart.js.map +1 -0
  29. package/dist/commands/services.d.ts +41 -3
  30. package/dist/commands/services.d.ts.map +1 -1
  31. package/dist/commands/services.js +221 -13
  32. package/dist/commands/services.js.map +1 -1
  33. package/dist/commands/setup-linux-gate.d.ts +26 -0
  34. package/dist/commands/setup-linux-gate.d.ts.map +1 -0
  35. package/dist/commands/setup-linux-gate.js +42 -0
  36. package/dist/commands/setup-linux-gate.js.map +1 -0
  37. package/dist/commands/setup-metrics.d.ts +26 -0
  38. package/dist/commands/setup-metrics.d.ts.map +1 -0
  39. package/dist/commands/setup-metrics.js +57 -0
  40. package/dist/commands/setup-metrics.js.map +1 -0
  41. package/dist/commands/setup-phase-5a-skill-source.d.ts +68 -0
  42. package/dist/commands/setup-phase-5a-skill-source.d.ts.map +1 -0
  43. package/dist/commands/setup-phase-5a-skill-source.js +196 -0
  44. package/dist/commands/setup-phase-5a-skill-source.js.map +1 -0
  45. package/dist/commands/setup-phase-5b-project-sweep.d.ts +38 -0
  46. package/dist/commands/setup-phase-5b-project-sweep.d.ts.map +1 -0
  47. package/dist/commands/setup-phase-5b-project-sweep.js +176 -0
  48. package/dist/commands/setup-phase-5b-project-sweep.js.map +1 -0
  49. package/dist/commands/setup.d.ts +19 -0
  50. package/dist/commands/setup.d.ts.map +1 -1
  51. package/dist/commands/setup.js +22 -0
  52. package/dist/commands/setup.js.map +1 -1
  53. package/dist/commands/skills-10x.d.ts +23 -0
  54. package/dist/commands/skills-10x.d.ts.map +1 -0
  55. package/dist/commands/skills-10x.js +308 -0
  56. package/dist/commands/skills-10x.js.map +1 -0
  57. package/dist/commands/substrate-audit-log.d.ts +2 -0
  58. package/dist/commands/substrate-audit-log.d.ts.map +1 -1
  59. package/dist/commands/substrate-audit-log.js +13 -0
  60. package/dist/commands/substrate-audit-log.js.map +1 -1
  61. package/dist/image-digests.json +7 -7
  62. package/dist/index.js +18102 -15234
  63. package/dist/index.js.map +1 -1
  64. package/dist/lib/auth-refresh-kubernetes.d.ts +62 -0
  65. package/dist/lib/auth-refresh-kubernetes.d.ts.map +1 -0
  66. package/dist/lib/auth-refresh-kubernetes.js +127 -0
  67. package/dist/lib/auth-refresh-kubernetes.js.map +1 -0
  68. package/dist/lib/build-if-stale.d.ts +33 -0
  69. package/dist/lib/build-if-stale.d.ts.map +1 -0
  70. package/dist/lib/build-if-stale.js +156 -0
  71. package/dist/lib/build-if-stale.js.map +1 -0
  72. package/dist/lib/bundle-freshness.d.ts +57 -0
  73. package/dist/lib/bundle-freshness.d.ts.map +1 -0
  74. package/dist/lib/bundle-freshness.js +223 -0
  75. package/dist/lib/bundle-freshness.js.map +1 -0
  76. package/dist/lib/bundle-source.d.ts +52 -0
  77. package/dist/lib/bundle-source.d.ts.map +1 -0
  78. package/dist/lib/bundle-source.js +83 -0
  79. package/dist/lib/bundle-source.js.map +1 -0
  80. package/dist/lib/kubectl-wrap.d.ts +6 -0
  81. package/dist/lib/kubectl-wrap.d.ts.map +1 -1
  82. package/dist/lib/kubectl-wrap.js +6 -1
  83. package/dist/lib/kubectl-wrap.js.map +1 -1
  84. package/dist/lib/manifest-refresh.d.ts +42 -1
  85. package/dist/lib/manifest-refresh.d.ts.map +1 -1
  86. package/dist/lib/manifest-refresh.js +83 -7
  87. package/dist/lib/manifest-refresh.js.map +1 -1
  88. package/dist/lib/peripheral-registry.d.ts +36 -0
  89. package/dist/lib/peripheral-registry.d.ts.map +1 -0
  90. package/dist/lib/peripheral-registry.js +55 -0
  91. package/dist/lib/peripheral-registry.js.map +1 -0
  92. package/dist/lib/port-forward.d.ts +67 -0
  93. package/dist/lib/port-forward.d.ts.map +1 -1
  94. package/dist/lib/port-forward.js +153 -0
  95. package/dist/lib/port-forward.js.map +1 -1
  96. package/dist/lib/upgrade-kubernetes.d.ts +52 -12
  97. package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
  98. package/dist/lib/upgrade-kubernetes.js +390 -22
  99. package/dist/lib/upgrade-kubernetes.js.map +1 -1
  100. package/dist/mcp-server.js +84 -58
  101. package/host-cp/compose.yaml +6 -0
  102. package/host-cp/k8s/manifests/30-configmap.yaml +6 -0
  103. package/host-cp/k8s/manifests/50-deployment.yaml +46 -9
  104. package/host-cp/k8s/manifests/auth-service/10-serviceaccount.yaml +8 -0
  105. package/host-cp/k8s/manifests/auth-service/20-rbac.yaml +34 -0
  106. package/host-cp/k8s/manifests/auth-service/30-configmap.yaml +24 -0
  107. package/host-cp/k8s/manifests/auth-service/45-pvc.yaml +25 -0
  108. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +117 -0
  109. package/host-cp/k8s/manifests/auth-service/60-service.yaml +21 -0
  110. package/host-cp/k8s/manifests/kg-service/10-serviceaccount.yaml +8 -0
  111. package/host-cp/k8s/manifests/kg-service/20-rbac.yaml +34 -0
  112. package/host-cp/k8s/manifests/kg-service/30-configmap.yaml +18 -0
  113. package/host-cp/k8s/manifests/kg-service/45-pvc.yaml +25 -0
  114. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +108 -0
  115. package/host-cp/k8s/manifests/kg-service/60-service.yaml +21 -0
  116. package/host-cp/k8s/manifests/mcp-auth-service/10-serviceaccount.yaml +8 -0
  117. package/host-cp/k8s/manifests/mcp-auth-service/20-rbac.yaml +34 -0
  118. package/host-cp/k8s/manifests/mcp-auth-service/30-configmap.yaml +18 -0
  119. package/host-cp/k8s/manifests/mcp-auth-service/45-pvc.yaml +25 -0
  120. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +117 -0
  121. package/host-cp/k8s/manifests/mcp-auth-service/60-service.yaml +21 -0
  122. package/host-cp/k8s/manifests/memory-service/10-serviceaccount.yaml +8 -0
  123. package/host-cp/k8s/manifests/memory-service/20-rbac.yaml +34 -0
  124. package/host-cp/k8s/manifests/memory-service/30-configmap.yaml +20 -0
  125. package/host-cp/k8s/manifests/memory-service/45-pvc.yaml +25 -0
  126. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +121 -0
  127. package/host-cp/k8s/manifests/memory-service/60-service.yaml +21 -0
  128. package/host-cp/k8s/templates/auth-service-secret-template.yaml +28 -0
  129. package/host-cp/k8s/templates/kg-service-secret-template.yaml +28 -0
  130. package/host-cp/k8s/templates/mcp-auth-service-secret-template.yaml +28 -0
  131. package/host-cp/k8s/templates/memory-service-secret-template.yaml +29 -0
  132. package/host-cp/src/agent-runtime-trigger.mjs +7 -5
  133. package/host-cp/src/plan-chat-secret.mjs +13 -2
  134. package/host-cp/src/plan-chat-service.mjs +116 -15
  135. package/host-cp/src/server.mjs +23 -11
  136. package/host-cp/src/upgrade-spawner.mjs +10 -5
  137. package/package.json +4 -2
@@ -2,7 +2,8 @@
2
2
  * olam doctor — pass/fail host-health command.
3
3
  *
4
4
  * Phase A3 of olam-operator-onboarding-parity (original 5 probes) +
5
- * Phase C / C2 of olam-host-cp-k3s-prereqs (engine + colima probes).
5
+ * Phase C / C2 of olam-host-cp-k3s-prereqs (engine + colima probes) +
6
+ * Phase 2 Phase A A5 (probeNodeMemory — kubernetes-only, D29).
6
7
  *
7
8
  * Probe layout — Decision 16 positional contract for `--json` consumers:
8
9
  *
@@ -14,6 +15,13 @@
14
15
  * 5. KG storage — probeKgStorage
15
16
  * 6. engine — probeEngine (NEW Phase C / C2)
16
17
  * 7. colima version — probeColimaVersion (NEW Phase C / C2)
18
+ * 8. bundle freshness — probeBundleFreshness (NEW olam-world-bundle-freshness Phase A1)
19
+ * Position 8 in docker mode is docker-only (per-MODE positional contract;
20
+ * kubernetes mode keeps slot 8 = node memory). Non-gating: WARN when any
21
+ * world's `/opt/olam/agent-stream/dist/` differs from the host's freshly
22
+ * built `packages/intelligence/dist/agent-stream/`; PASS otherwise.
23
+ * Silent in kubernetes substrate mode (worlds-as-pods don't support
24
+ * `docker exec` reach-through; Phase C of the plan addresses cloud paths).
17
25
  *
18
26
  * On engine=kubernetes:
19
27
  * 1. api server — probeK8sApiReachable (slot replaced)
@@ -21,8 +29,12 @@
21
29
  * 3. host-cp /health — probeHostCpHealth (unchanged)
22
30
  * 4. auth vault — probeAuthVault (unchanged)
23
31
  * 5. KG storage — probeKgStorage (unchanged)
24
- * 6. engine — probeEngine (NEW)
25
- * 7. colima version — probeColimaVersion (NEW)
32
+ * 6. engine — probeEngine (unchanged)
33
+ * 7. colima version — probeColimaVersion (unchanged)
34
+ * 8. node memory — probeNodeMemory (NEW Phase 2 A5, D29)
35
+ * Position 8 is kubernetes-only (D11 per-MODE positional contract).
36
+ * Non-gating: WARN when free RAM <4 GiB; PASS otherwise.
37
+ * Silent in docker/compose substrate mode.
26
38
  *
27
39
  * The `--json` payload's `probes[]` indexes are stable across engine swap:
28
40
  * consumers parsing `probes[0]` for "daemon-reachability" still see a
@@ -40,7 +52,14 @@
40
52
  * - `--json` emits the same probe array (canonical positional shape).
41
53
  */
42
54
  import { probeDockerDaemon, probeImagePresence, probeHostCpHealth, probeAuthVault, probeKgStorage, probeEngine, probeColimaVersion, probeK8sApiReachable, probeK8sImagePresence, } from '../lib/health-probes.js';
55
+ import { probeBundleFreshness } from '../lib/bundle-freshness.js';
43
56
  import { printError, printSuccess, printWarning, printHeader } from '../output.js';
57
+ import { kubectlWrap } from '../lib/kubectl-wrap.js';
58
+ import { PERIPHERALS } from '../lib/peripheral-registry.js';
59
+ import * as fs from 'node:fs';
60
+ import * as net from 'node:net';
61
+ import * as path from 'node:path';
62
+ import { OLAM_HOME } from '../lib/config.js';
44
63
  /** Default registry prefix for registry-tagged images. Mirrors bootstrap.ts's default. */
45
64
  const DEFAULT_REGISTRY = 'ghcr.io/pleri';
46
65
  /**
@@ -97,7 +116,7 @@ export async function runDoctor(opts, deps = {}) {
97
116
  ? await probeK8sApiReachable(dockerExec)
98
117
  : await probeDockerDaemon(dockerExec);
99
118
  const slot1Name = isK8s ? 'api server' : 'docker daemon';
100
- const rows = [{ name: slot1Name, result: slot1Result }];
119
+ const rows = [{ name: slot1Name, result: slot1Result, position: 1 }];
101
120
  if (!slot1Result.ok) {
102
121
  // Fast-fail: skip per-image / host-cp / auth / kg probes when the
103
122
  // engine's daemon-equivalent is down. Engine + colima probes still
@@ -107,7 +126,7 @@ export async function runDoctor(opts, deps = {}) {
107
126
  probeEngine(fetchImpl),
108
127
  probeColimaVersion(dockerExec),
109
128
  ]);
110
- rows.push({ name: 'engine', result: engineRes }, { name: 'colima version', result: colimaRes });
129
+ rows.push({ name: 'engine', result: engineRes, position: 6 }, { name: 'colima version', result: colimaRes, position: 7 });
111
130
  return emit(makeReport(rows), opts);
112
131
  }
113
132
  // Slots 2-7: parallel (independent; no shared state).
@@ -123,9 +142,331 @@ export async function runDoctor(opts, deps = {}) {
123
142
  probeEngine(fetchImpl),
124
143
  probeColimaVersion(dockerExec),
125
144
  ]);
126
- rows.push({ name: 'images', result: imageResult }, { name: 'host-cp /health', result: hostCpResult }, { name: 'auth vault', result: authResult }, { name: 'KG storage', result: kgResult }, { name: 'engine', result: engineResult }, { name: 'colima version', result: colimaResult });
145
+ rows.push({ name: 'images', result: imageResult, position: 2 }, { name: 'host-cp /health', result: hostCpResult, position: 3 }, { name: 'auth vault', result: authResult, position: 4 }, { name: 'KG storage', result: kgResult, position: 5 }, { name: 'engine', result: engineResult, position: 6 }, { name: 'colima version', result: colimaResult, position: 7 });
146
+ // Per-MODE positional contract (D11) — slot 8+ branches by engine.
147
+ // docker mode: bundle freshness probe — olam-world-bundle-freshness Phase A1
148
+ // (non-gating WARN-or-PASS; informational signal for in-development
149
+ // agent-stream patches).
150
+ // kubernetes mode: D2 peripheral suite (positions 14-25) + storage class
151
+ // (26) + node memory (27). Non-gating informational probes; silent in
152
+ // docker/compose substrate mode. Positions 8-13 reserved for future
153
+ // Phase 1b probes.
154
+ if (isK8s) {
155
+ const wrapImpl = deps.kubectlWrapImpl ?? kubectlWrap;
156
+ const k8sCtx = deps.kubectlContext;
157
+ const manifestsDir = deps.manifestsDir ?? path.join(OLAM_HOME, 'k8s', 'manifests');
158
+ const readFileSyncImpl = deps.readFileSyncImpl ?? fs.readFileSync;
159
+ // Positions 14-25: 4 peripherals × 3 probes in alphabetical order.
160
+ // Alphabetical: auth-service, kg-service, mcp-auth-service, memory-service.
161
+ const sortedPeripherals = [...PERIPHERALS].sort((a, b) => a.name.localeCompare(b.name));
162
+ let peripheralPosition = 14;
163
+ const peripheralProbeRows = await Promise.all(sortedPeripherals.map(async (peripheral) => {
164
+ const startPos = peripheralPosition;
165
+ peripheralPosition += 3;
166
+ return runPeripheralProbes(peripheral, startPos, k8sCtx, wrapImpl);
167
+ }));
168
+ for (const probeRows of peripheralProbeRows) {
169
+ rows.push(...probeRows);
170
+ }
171
+ // Position 26: probeStorageClassMatch (D24 — non-gating, WARN on mismatch).
172
+ const storageClassResult = await probeStorageClassMatch(sortedPeripherals, k8sCtx, manifestsDir, wrapImpl, readFileSyncImpl);
173
+ rows.push({ name: 'storage class match', result: storageClassResult, position: 26 });
174
+ // Position 27: probeNodeMemory (D29 — already seeded in Phase A A5).
175
+ const nodeMemResult = probeNodeMemory(dockerExec, k8sCtx);
176
+ rows.push({ name: 'node memory', result: nodeMemResult, position: 27 });
177
+ // Position 28: probeDockerSocketBindMount (D7 — Phase 2 Phase D).
178
+ // Non-gating: WARN when socket bind-mount absent; PASS when accessible.
179
+ const socketCheckImpl = deps.dockerSocketCheckImpl;
180
+ const socketResult = await probeDockerSocketBindMount(k8sCtx, wrapImpl, socketCheckImpl);
181
+ rows.push({ name: 'docker socket bind-mount', result: socketResult, position: 28 });
182
+ }
183
+ else {
184
+ const bundleResult = await probeBundleFreshness({
185
+ dockerExec,
186
+ repoRootOverride: deps.repoRootOverride,
187
+ });
188
+ rows.push({ name: 'bundle freshness', result: bundleResult, position: 8 });
189
+ }
127
190
  return emit(makeReport(rows), opts);
128
191
  }
192
+ // ── D2 Kubernetes peripheral probes (positions 14-25) ─────────────────────
193
+ const K8S_NAMESPACE = 'olam';
194
+ /**
195
+ * Run 3 probes for one peripheral: Reachable (kubectl exec), PortForwardLiveness (TCP),
196
+ * ImagePresent (kubectl get pod jsonpath). Returns 3 ProbeRows at consecutive positions.
197
+ */
198
+ async function runPeripheralProbes(peripheral, startPosition, kubectlContext, wrapImpl) {
199
+ const ctxArgs = kubectlContext ? ['--context', kubectlContext] : [];
200
+ const rows = [];
201
+ // Probe N: Reachable — kubectl exec into the pod and wget the health path.
202
+ const reachableResult = await (async () => {
203
+ const result = await wrapImpl([
204
+ ...ctxArgs,
205
+ 'exec',
206
+ `deploy/${peripheral.name}`,
207
+ '-n', K8S_NAMESPACE,
208
+ '--',
209
+ 'wget', '-qO-', `http://localhost:${peripheral.port}${peripheral.healthPath}`,
210
+ ], { timeout: 10_000 });
211
+ if (result.ok) {
212
+ return { ok: true, message: `${peripheral.name} pod reachable (${peripheral.healthPath})` };
213
+ }
214
+ const errLine = result.stderr.split('\n')[0] ?? '';
215
+ return {
216
+ ok: false,
217
+ message: `${peripheral.name} pod not reachable`,
218
+ remedy: `Check pod logs: kubectl logs deploy/${peripheral.name} -n ${K8S_NAMESPACE}. stderr: ${errLine}`,
219
+ };
220
+ })();
221
+ rows.push({ name: `${peripheral.name} reachable`, result: reachableResult, position: startPosition });
222
+ // Probe N+1: PortForwardLiveness — TCP connect to 127.0.0.1:<port>.
223
+ const pfLivenessResult = await (async () => {
224
+ return new Promise((resolve) => {
225
+ const socket = new net.Socket();
226
+ let done = false;
227
+ const finish = (alive) => {
228
+ if (done)
229
+ return;
230
+ done = true;
231
+ socket.destroy();
232
+ if (alive) {
233
+ resolve({ ok: true, message: `${peripheral.name} port-forward live on :${peripheral.port}` });
234
+ }
235
+ else {
236
+ resolve({
237
+ ok: true,
238
+ warn: true,
239
+ message: `${peripheral.name} port-forward not live on :${peripheral.port}`,
240
+ remedy: `Run \`olam upgrade\` to establish port-forwards for peripheral services.`,
241
+ });
242
+ }
243
+ };
244
+ const timer = setTimeout(() => finish(false), 2_000);
245
+ socket.once('connect', () => { clearTimeout(timer); finish(true); });
246
+ socket.once('error', () => { clearTimeout(timer); finish(false); });
247
+ socket.connect(peripheral.port, '127.0.0.1');
248
+ });
249
+ })();
250
+ rows.push({ name: `${peripheral.name} port-forward`, result: pfLivenessResult, position: startPosition + 1 });
251
+ // Probe N+2: ImagePresent — kubectl get pod jsonpath for container image.
252
+ const imagePresentResult = await (async () => {
253
+ const result = await wrapImpl([
254
+ ...ctxArgs,
255
+ 'get', 'pod',
256
+ '-n', K8S_NAMESPACE,
257
+ '-l', `app=${peripheral.name}`,
258
+ '-o', `jsonpath={.items[0].status.containerStatuses[0].image}`,
259
+ ], { timeout: 10_000 });
260
+ const image = result.stdout.trim();
261
+ if (result.ok && image.length > 0) {
262
+ return { ok: true, message: `${peripheral.name} image present: ${image}` };
263
+ }
264
+ return {
265
+ ok: true,
266
+ warn: true,
267
+ message: `${peripheral.name} image not detected`,
268
+ remedy: `Verify pod is running: kubectl get pods -n ${K8S_NAMESPACE} -l app=${peripheral.name}`,
269
+ };
270
+ })();
271
+ rows.push({ name: `${peripheral.name} image`, result: imagePresentResult, position: startPosition + 2 });
272
+ return rows;
273
+ }
274
+ /**
275
+ * Position 26 — probeStorageClassMatch (D24).
276
+ *
277
+ * For each peripheral, reads the bound PVC's storageClassName from the cluster
278
+ * and compares against the manifest declaration (45-pvc.yaml). WARN on mismatch.
279
+ * Non-gating per D24 spec.
280
+ */
281
+ async function probeStorageClassMatch(peripherals, kubectlContext, manifestsDir, wrapImpl, readFileSyncImpl) {
282
+ const ctxArgs = kubectlContext ? ['--context', kubectlContext] : [];
283
+ const mismatches = [];
284
+ for (const peripheral of peripherals) {
285
+ // Read declared storageClassName from the manifest PVC file.
286
+ const pvcManifestPath = path.join(manifestsDir, peripheral.name, '45-pvc.yaml');
287
+ let declaredClass;
288
+ try {
289
+ const raw = readFileSyncImpl(pvcManifestPath, 'utf8');
290
+ // Simple regex parse — avoid bringing in yaml parse dep here.
291
+ const match = /storageClassName:\s*(\S+)/.exec(raw);
292
+ declaredClass = match?.[1];
293
+ }
294
+ catch {
295
+ // Manifest not found — skip this peripheral (not deployed yet).
296
+ continue;
297
+ }
298
+ // Read actual storageClassName from the cluster.
299
+ const pvcName = `olam-${peripheral.name}-data`;
300
+ const result = await wrapImpl([
301
+ ...ctxArgs,
302
+ 'get', 'pvc', pvcName,
303
+ '-n', K8S_NAMESPACE,
304
+ '-o', `jsonpath={.spec.storageClassName}`,
305
+ ], { timeout: 10_000 });
306
+ if (!result.ok || !result.stdout.trim()) {
307
+ // PVC not found — skip (peripheral not deployed yet).
308
+ continue;
309
+ }
310
+ const actualClass = result.stdout.trim();
311
+ if (declaredClass && actualClass !== declaredClass) {
312
+ mismatches.push(`${peripheral.name}: declared=${declaredClass} actual=${actualClass}`);
313
+ }
314
+ }
315
+ if (mismatches.length > 0) {
316
+ return {
317
+ ok: true,
318
+ warn: true,
319
+ message: `storage class mismatch on ${mismatches.length} PVC(s)`,
320
+ remedy: `Mismatches: ${mismatches.join('; ')}. Re-provision PVCs or update manifest storageClassName.`,
321
+ };
322
+ }
323
+ return { ok: true, message: 'storage class match: all PVCs match manifest declarations' };
324
+ }
325
+ /**
326
+ * probeNodeMemory — Phase 2 A5, Decision D29.
327
+ *
328
+ * Reads free RAM on the k3d node via `kubectl top node --no-headers`.
329
+ * The fifth column is "FREE" in Ki. Warns when free RAM is below 4 GiB
330
+ * (T4 risk: peripheral service pods OOM before the operator notices).
331
+ *
332
+ * Non-gating (WARN, not FAIL). Only runs in engine=kubernetes mode.
333
+ *
334
+ * kubectl top requires metrics-server. If metrics-server is absent (fresh
335
+ * k3d cluster), `kubectl top` exits non-zero. In that case we emit WARN
336
+ * with a "metrics-server not installed" note rather than FAIL.
337
+ */
338
+ function probeNodeMemory(dockerExec, kubectlContext) {
339
+ if (!dockerExec) {
340
+ // No exec injected — can't run kubectl. Skip gracefully.
341
+ return { ok: true, message: 'node memory probe skipped (no exec)' };
342
+ }
343
+ const contextArgs = kubectlContext ? ['--context', kubectlContext] : [];
344
+ const result = dockerExec('kubectl', [...contextArgs, 'top', 'node', '--no-headers']);
345
+ if (result.status !== 0) {
346
+ // metrics-server absent or cluster unreachable.
347
+ const hint = (result.stderr ?? '').includes('not available') || (result.stderr ?? '').includes('Metrics')
348
+ ? 'metrics-server not installed on cluster — install via: kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml'
349
+ : `kubectl top node failed: ${(result.stderr ?? '').trim()}`;
350
+ return {
351
+ ok: true,
352
+ warn: true,
353
+ message: 'node memory unknown (kubectl top unavailable)',
354
+ remedy: hint,
355
+ };
356
+ }
357
+ // Parse the first node's output. Format:
358
+ // NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
359
+ // We want total node capacity which isn't in `top` output directly;
360
+ // use `kubectl get node -o json` to fetch allocatable memory and compare.
361
+ const topLine = (result.stdout ?? '').trim().split('\n')[0];
362
+ if (!topLine) {
363
+ return {
364
+ ok: true,
365
+ warn: true,
366
+ message: 'node memory unknown (empty kubectl top output)',
367
+ remedy: 'Verify metrics-server is running: kubectl get pods -n kube-system | grep metrics-server',
368
+ };
369
+ }
370
+ // Get allocatable memory from `kubectl get nodes -o jsonpath`.
371
+ const allocResult = dockerExec('kubectl', [
372
+ ...contextArgs,
373
+ 'get', 'nodes', '-o', 'jsonpath={.items[0].status.allocatable.memory}',
374
+ ]);
375
+ if (allocResult.status !== 0 || !(allocResult.stdout ?? '').trim()) {
376
+ return {
377
+ ok: true,
378
+ warn: true,
379
+ message: 'node memory unknown (could not read allocatable memory)',
380
+ remedy: 'kubectl get nodes unreachable',
381
+ };
382
+ }
383
+ // Parse allocatable memory (e.g. "8059228Ki" or "8Gi").
384
+ const raw = (allocResult.stdout ?? '').trim();
385
+ let allocKi;
386
+ if (raw.endsWith('Ki')) {
387
+ allocKi = parseInt(raw.slice(0, -2), 10);
388
+ }
389
+ else if (raw.endsWith('Mi')) {
390
+ allocKi = parseInt(raw.slice(0, -2), 10) * 1024;
391
+ }
392
+ else if (raw.endsWith('Gi')) {
393
+ allocKi = parseInt(raw.slice(0, -2), 10) * 1024 * 1024;
394
+ }
395
+ else {
396
+ // Bytes (no suffix).
397
+ allocKi = Math.floor(parseInt(raw, 10) / 1024);
398
+ }
399
+ // Parse used memory from kubectl top output (4th column: MEMORY(bytes) in Mi).
400
+ const topCols = topLine.trim().split(/\s+/);
401
+ const usedMiStr = topCols[3] ?? '0Mi';
402
+ const usedKi = usedMiStr.endsWith('Mi')
403
+ ? parseInt(usedMiStr.slice(0, -2), 10) * 1024
404
+ : parseInt(usedMiStr, 10);
405
+ const freeKi = allocKi - usedKi;
406
+ const freeGiB = freeKi / (1024 * 1024);
407
+ const WARN_THRESHOLD_GIB = 4;
408
+ if (freeGiB < WARN_THRESHOLD_GIB) {
409
+ return {
410
+ ok: true,
411
+ warn: true,
412
+ message: `node free RAM ${freeGiB.toFixed(1)} GiB (below ${WARN_THRESHOLD_GIB} GiB threshold)`,
413
+ remedy: `Free at least ${WARN_THRESHOLD_GIB} GiB of node RAM before deploying peripheral services to avoid OOM (T4 risk).`,
414
+ };
415
+ }
416
+ return {
417
+ ok: true,
418
+ message: `node free RAM ${freeGiB.toFixed(1)} GiB (≥${WARN_THRESHOLD_GIB} GiB threshold)`,
419
+ };
420
+ }
421
+ /**
422
+ * Default implementation: exec into the host-cp pod and test-open the socket.
423
+ * Uses `test -S /var/run/docker.sock` — exits 0 when the socket file exists
424
+ * and is accessible; non-zero when absent, empty, or permission-denied.
425
+ */
426
+ async function defaultDockerSocketCheck(kubectlContext, wrapImpl) {
427
+ const ctxArgs = kubectlContext ? ['--context', kubectlContext] : [];
428
+ const result = await wrapImpl([
429
+ ...ctxArgs,
430
+ 'exec',
431
+ 'deploy/olam-host-cp',
432
+ '-n', 'olam',
433
+ '--',
434
+ 'test', '-S', '/var/run/docker.sock',
435
+ ], { timeout: 10_000 });
436
+ return result.ok;
437
+ }
438
+ /**
439
+ * probeDockerSocketBindMount — Phase 2 Phase D, D7.
440
+ *
441
+ * Position 28 in the kubernetes probe suite (after probeNodeMemory at 27).
442
+ * Detects whether the docker socket is accessible inside the host-cp pod.
443
+ *
444
+ * PASS: `test -S /var/run/docker.sock` exits 0 inside the pod — socket is
445
+ * present and accessible.
446
+ * WARN: command fails — socket absent or permission-denied. Operator action:
447
+ * recreate the k3d cluster with the --volume socket bind.
448
+ *
449
+ * Non-gating (WARN, not FAIL). Only runs in engine=kubernetes mode.
450
+ */
451
+ async function probeDockerSocketBindMount(kubectlContext, wrapImpl, checkImpl) {
452
+ const check = checkImpl ?? defaultDockerSocketCheck;
453
+ const accessible = await check(kubectlContext, wrapImpl);
454
+ if (accessible) {
455
+ return { ok: true, message: 'docker socket accessible at /var/run/docker.sock' };
456
+ }
457
+ return {
458
+ ok: true,
459
+ warn: true,
460
+ message: 'docker socket not accessible at /var/run/docker.sock',
461
+ remedy: 'Recreate the k3d cluster with the docker socket bind-mount:\n' +
462
+ ' k3d cluster create olam-host \\\n' +
463
+ ' --volume /var/run/docker.sock:/var/run/docker.sock@server:* \\\n' +
464
+ ' --volume ~/.config/gh:/host/.config/gh \\\n' +
465
+ ' --volume <olam-repo>:/host/olam \\\n' +
466
+ ' --wait --timeout 90s\n' +
467
+ 'Then run: olam upgrade',
468
+ };
469
+ }
129
470
  function makeReport(rows) {
130
471
  const failureCount = rows.filter((r) => !r.result.ok).length;
131
472
  const warnCount = rows.filter((r) => isWarn(r.result)).length;
@@ -154,6 +495,7 @@ function emit(report, opts) {
154
495
  const isFail = !r.result.ok;
155
496
  const warn = isWarn(r.result);
156
497
  const base = {
498
+ position: r.position,
157
499
  name: r.name,
158
500
  ok: r.result.ok,
159
501
  message: r.result.message,
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -3,8 +3,54 @@
3
3
  *
4
4
  * Delegates to the same init logic as the MCP server's olam_init tool.
5
5
  * Works without an existing OlamContext (that is the whole point).
6
+ *
7
+ * B6 (Phase 2 dogfood recovery): auto-write host.kubectl_context_pinned to
8
+ * ~/.olam/config.json when exactly ONE ^k3d-olam- context is detected.
9
+ * Decision #7: regex ^k3d-olam- (not ^k3d-) to avoid false-positives.
10
+ * Multiple matches → stderr error, skip. Zero matches → silent skip.
11
+ * Existing value → never overwrite.
6
12
  */
13
+ import * as fs from 'node:fs';
7
14
  import type { Command } from 'commander';
15
+ /** Exec function shape used by detectK3dOlamContext for injection in tests. */
16
+ export type ExecFn = (cmd: string, opts?: {
17
+ encoding: 'utf-8';
18
+ }) => string;
19
+ /**
20
+ * Detect `^k3d-olam-` kubectl contexts from the operator's kubeconfig.
21
+ *
22
+ * Returns:
23
+ * { contexts: string[] } — list of matching context names (may be empty).
24
+ * { contexts: null } — kubectl not found / kubeconfig unreadable (skip silently).
25
+ *
26
+ * Exported for unit testing.
27
+ */
28
+ export declare function detectK3dOlamContexts(execFn?: ExecFn): {
29
+ contexts: string[] | null;
30
+ };
31
+ /**
32
+ * Write host.kubectl_context_pinned to ~/.olam/config.json when exactly one
33
+ * ^k3d-olam- context is detected. Reads the file raw so unknown fields are
34
+ * preserved (OlamConfig strict type doesn't include kubectl_context_pinned).
35
+ *
36
+ * Returns:
37
+ * { pinned: string } — field written.
38
+ * { skipped: string } — reason it was not written (informational; not an error).
39
+ * { refused: string } — multiple contexts detected (emit to stderr).
40
+ *
41
+ * Exported for unit testing.
42
+ */
43
+ export declare function applyKubectlContextPin(contexts: string[], opts?: {
44
+ configPath?: string;
45
+ readFileSyncFn?: typeof fs.readFileSync;
46
+ writeFileSyncFn?: typeof fs.writeFileSync;
47
+ }): {
48
+ pinned: string;
49
+ } | {
50
+ skipped: string;
51
+ } | {
52
+ refused: string;
53
+ };
8
54
  /**
9
55
  * Walk UP from `startDir` to the nearest `.git` directory; return that root
10
56
  * (or `startDir` if no .git is found en route to filesystem root).
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8BzC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoGnD"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAG9B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BzC,+EAA+E;AAC/E,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,KAAK,MAAM,CAAC;AAE3E;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,GAAE,MAAuF,GAC9F;IAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;CAAE,CAY/B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,GAAE;IACJ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC;IACxC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,aAAa,CAAC;CACtC,GACL;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAwChE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgHnD"}
@@ -3,6 +3,12 @@
3
3
  *
4
4
  * Delegates to the same init logic as the MCP server's olam_init tool.
5
5
  * Works without an existing OlamContext (that is the whole point).
6
+ *
7
+ * B6 (Phase 2 dogfood recovery): auto-write host.kubectl_context_pinned to
8
+ * ~/.olam/config.json when exactly ONE ^k3d-olam- context is detected.
9
+ * Decision #7: regex ^k3d-olam- (not ^k3d-) to avoid false-positives.
10
+ * Multiple matches → stderr error, skip. Zero matches → silent skip.
11
+ * Existing value → never overwrite.
6
12
  */
7
13
  import * as fs from 'node:fs';
8
14
  import * as path from 'node:path';
@@ -10,6 +16,7 @@ import { execSync } from 'node:child_process';
10
16
  import pc from 'picocolors';
11
17
  import { printError, printInfo, printHeader } from '../output.js';
12
18
  import { ensureProjectWorkspaceFromConfig } from './workspace.js';
19
+ import { OLAM_CONFIG_PATH } from '../lib/config.js';
13
20
  function detectProjectType(root) {
14
21
  if (fs.existsSync(path.join(root, 'Gemfile')) ||
15
22
  fs.existsSync(path.join(root, 'config', 'routes.rb')))
@@ -34,6 +41,77 @@ function getRepoName(root) {
34
41
  catch { /* fallback */ }
35
42
  return path.basename(root);
36
43
  }
44
+ /**
45
+ * Detect `^k3d-olam-` kubectl contexts from the operator's kubeconfig.
46
+ *
47
+ * Returns:
48
+ * { contexts: string[] } — list of matching context names (may be empty).
49
+ * { contexts: null } — kubectl not found / kubeconfig unreadable (skip silently).
50
+ *
51
+ * Exported for unit testing.
52
+ */
53
+ export function detectK3dOlamContexts(execFn = (cmd, opts) => execSync(cmd, opts)) {
54
+ try {
55
+ const raw = execFn('kubectl config get-contexts -o name', { encoding: 'utf-8' });
56
+ const contexts = raw
57
+ .split('\n')
58
+ .map((l) => l.trim())
59
+ .filter((l) => /^k3d-olam-/.test(l));
60
+ return { contexts };
61
+ }
62
+ catch {
63
+ // kubectl not found or kubeconfig unreadable — skip silently
64
+ return { contexts: null };
65
+ }
66
+ }
67
+ /**
68
+ * Write host.kubectl_context_pinned to ~/.olam/config.json when exactly one
69
+ * ^k3d-olam- context is detected. Reads the file raw so unknown fields are
70
+ * preserved (OlamConfig strict type doesn't include kubectl_context_pinned).
71
+ *
72
+ * Returns:
73
+ * { pinned: string } — field written.
74
+ * { skipped: string } — reason it was not written (informational; not an error).
75
+ * { refused: string } — multiple contexts detected (emit to stderr).
76
+ *
77
+ * Exported for unit testing.
78
+ */
79
+ export function applyKubectlContextPin(contexts, opts = {}) {
80
+ const configPath = opts.configPath ?? OLAM_CONFIG_PATH;
81
+ const readFn = opts.readFileSyncFn ?? fs.readFileSync;
82
+ const writeFn = opts.writeFileSyncFn ?? fs.writeFileSync;
83
+ if (contexts.length === 0) {
84
+ return { skipped: 'no ^k3d-olam- contexts found' };
85
+ }
86
+ if (contexts.length > 1) {
87
+ return { refused: `multiple ^k3d-olam- contexts found: ${contexts.join(', ')} — set host.kubectl_context_pinned manually` };
88
+ }
89
+ const context = contexts[0];
90
+ // Read existing config raw to preserve unknown fields (kubectl_context_pinned
91
+ // is not in OlamConfig strict type; we patch the JSON directly).
92
+ let parsed = {};
93
+ try {
94
+ const raw = readFn(configPath, 'utf8');
95
+ parsed = JSON.parse(raw);
96
+ }
97
+ catch {
98
+ // File absent or malformed — start fresh; readConfig will also handle this
99
+ parsed = {};
100
+ }
101
+ const host = (typeof parsed.host === 'object' && parsed.host !== null)
102
+ ? parsed.host
103
+ : {};
104
+ // Never overwrite an existing value.
105
+ if (typeof host['kubectl_context_pinned'] === 'string' && host['kubectl_context_pinned'].length > 0) {
106
+ return { skipped: `kubectl_context_pinned already set to ${host['kubectl_context_pinned']}` };
107
+ }
108
+ const next = {
109
+ ...parsed,
110
+ host: { ...host, kubectl_context_pinned: context },
111
+ };
112
+ writeFn(configPath, JSON.stringify(next, null, 2) + '\n', { encoding: 'utf8' });
113
+ return { pinned: context };
114
+ }
37
115
  /**
38
116
  * Walk UP from `startDir` to the nearest `.git` directory; return that root
39
117
  * (or `startDir` if no .git is found en route to filesystem root).
@@ -141,6 +219,18 @@ export function registerInit(program) {
141
219
  catch (err) {
142
220
  printError(`Workspace auto-register failed: ${err instanceof Error ? err.message : String(err)}`);
143
221
  }
222
+ // B6: auto-pin kubectl context if exactly one ^k3d-olam- context detected.
223
+ const { contexts } = detectK3dOlamContexts();
224
+ if (contexts !== null) {
225
+ const pinResult = applyKubectlContextPin(contexts);
226
+ if ('pinned' in pinResult) {
227
+ printInfo('kubectl context', `${pinResult.pinned} (auto-pinned)`);
228
+ }
229
+ else if ('refused' in pinResult) {
230
+ process.stderr.write(`${pc.yellow('warn:')} ${pinResult.refused}\n`);
231
+ }
232
+ // skipped → silent
233
+ }
144
234
  console.log(`\n${pc.dim(`Next: olam create --name my-world --workspace ${repoName} --task "..."`)}`);
145
235
  }
146
236
  catch (err) {