create-walle 0.9.21 → 0.9.23

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 (500) hide show
  1. package/README.md +27 -5
  2. package/package.json +2 -2
  3. package/template/CLAUDE.md +2 -2
  4. package/template/LICENSE +1 -1
  5. package/template/bin/ctm-dev-cleanup.js +24 -3
  6. package/template/bin/ctm-launch.sh +13 -0
  7. package/template/bin/dev.sh +156 -18
  8. package/template/bin/node-bin.sh +84 -0
  9. package/template/bin/pin-node.sh +51 -0
  10. package/template/claude-task-manager/api-prompts.js +1203 -182
  11. package/template/claude-task-manager/api-reviews.js +109 -15
  12. package/template/claude-task-manager/approval-agent.js +1360 -280
  13. package/template/claude-task-manager/bin/restart-ctm.sh +64 -23
  14. package/template/claude-task-manager/bin/storage-migration-supervisor.js +338 -0
  15. package/template/claude-task-manager/db.js +4417 -295
  16. package/template/claude-task-manager/docs/app-update-refresh-protocol.md +69 -0
  17. package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
  18. package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
  19. package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
  20. package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
  21. package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
  22. package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
  23. package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
  24. package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
  25. package/template/claude-task-manager/docs/image-paste-ux.md +13 -0
  26. package/template/claude-task-manager/docs/ipad-web-preview.md +88 -0
  27. package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
  28. package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
  29. package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
  30. package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
  31. package/template/claude-task-manager/docs/phone-access-design.md +53 -15
  32. package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
  33. package/template/claude-task-manager/docs/phone-setup.md +3 -0
  34. package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
  35. package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
  36. package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
  37. package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
  38. package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
  39. package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
  40. package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
  41. package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
  42. package/template/claude-task-manager/docs/session-title-authority.md +32 -0
  43. package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
  44. package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
  45. package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
  46. package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
  47. package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
  48. package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
  49. package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
  50. package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
  51. package/template/claude-task-manager/git-utils.js +897 -27
  52. package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
  53. package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
  54. package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
  55. package/template/claude-task-manager/lib/agent-presets.js +17 -1
  56. package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
  57. package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
  58. package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
  59. package/template/claude-task-manager/lib/async-semaphore.js +44 -0
  60. package/template/claude-task-manager/lib/auth-context.js +5 -0
  61. package/template/claude-task-manager/lib/auth-rate-limit.js +47 -4
  62. package/template/claude-task-manager/lib/auth-rules.js +29 -2
  63. package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
  64. package/template/claude-task-manager/lib/background-llm.js +144 -17
  65. package/template/claude-task-manager/lib/branch-inventory.js +212 -0
  66. package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
  67. package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
  68. package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
  69. package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
  70. package/template/claude-task-manager/lib/codex-zst.js +124 -0
  71. package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
  72. package/template/claude-task-manager/lib/connection-health.js +232 -0
  73. package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
  74. package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
  75. package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
  76. package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
  77. package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
  78. package/template/claude-task-manager/lib/document-review.js +141 -6
  79. package/template/claude-task-manager/lib/escalation-review.js +152 -0
  80. package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
  81. package/template/claude-task-manager/lib/headless-term-service.js +678 -0
  82. package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
  83. package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
  84. package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
  85. package/template/claude-task-manager/lib/main-db-census.js +216 -0
  86. package/template/claude-task-manager/lib/message-pagination.js +106 -4
  87. package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +750 -26
  88. package/template/claude-task-manager/lib/mobile-auth-api.js +274 -7
  89. package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
  90. package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
  91. package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
  92. package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
  93. package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
  94. package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
  95. package/template/claude-task-manager/lib/perf-tracker.js +242 -6
  96. package/template/claude-task-manager/lib/permission-match.js +76 -0
  97. package/template/claude-task-manager/lib/permission-sync.js +133 -20
  98. package/template/claude-task-manager/lib/process-title.js +35 -0
  99. package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
  100. package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
  101. package/template/claude-task-manager/lib/prompt-intent.js +132 -0
  102. package/template/claude-task-manager/lib/provider-user-context.js +34 -0
  103. package/template/claude-task-manager/lib/read-pool-client.js +313 -0
  104. package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
  105. package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
  106. package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
  107. package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
  108. package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
  109. package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
  110. package/template/claude-task-manager/lib/restart-guard.js +109 -0
  111. package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
  112. package/template/claude-task-manager/lib/restore-policy.js +13 -0
  113. package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
  114. package/template/claude-task-manager/lib/restore-runtime.js +68 -0
  115. package/template/claude-task-manager/lib/restore-storm.js +34 -0
  116. package/template/claude-task-manager/lib/resume-cwd.js +36 -0
  117. package/template/claude-task-manager/lib/resume-preflight.js +313 -0
  118. package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
  119. package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
  120. package/template/claude-task-manager/lib/scheduler.js +21 -1
  121. package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
  122. package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
  123. package/template/claude-task-manager/lib/server-listeners.js +239 -0
  124. package/template/claude-task-manager/lib/session-capture.js +42 -7
  125. package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
  126. package/template/claude-task-manager/lib/session-history.js +388 -43
  127. package/template/claude-task-manager/lib/session-host-manager.js +287 -0
  128. package/template/claude-task-manager/lib/session-image-refs.js +209 -0
  129. package/template/claude-task-manager/lib/session-jobs.js +399 -59
  130. package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
  131. package/template/claude-task-manager/lib/session-restore.js +53 -0
  132. package/template/claude-task-manager/lib/session-standup.js +123 -23
  133. package/template/claude-task-manager/lib/session-state-bus.js +14 -0
  134. package/template/claude-task-manager/lib/session-stream.js +64 -16
  135. package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
  136. package/template/claude-task-manager/lib/session-token-usage.js +494 -0
  137. package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
  138. package/template/claude-task-manager/lib/setup-network-config.js +9 -0
  139. package/template/claude-task-manager/lib/size-cap.js +45 -0
  140. package/template/claude-task-manager/lib/size-cap.test.js +62 -0
  141. package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
  142. package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
  143. package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
  144. package/template/claude-task-manager/lib/standup-attention.js +7 -3
  145. package/template/claude-task-manager/lib/status-authority.js +39 -0
  146. package/template/claude-task-manager/lib/status-hooks.js +4 -0
  147. package/template/claude-task-manager/lib/storage-migration.js +235 -0
  148. package/template/claude-task-manager/lib/structured-capture.js +298 -0
  149. package/template/claude-task-manager/lib/sync-io-census.js +163 -0
  150. package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
  151. package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
  152. package/template/claude-task-manager/lib/terminal-choice.js +364 -0
  153. package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
  154. package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
  155. package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
  156. package/template/claude-task-manager/lib/timeline-order.js +122 -0
  157. package/template/claude-task-manager/lib/transcript-store.js +348 -43
  158. package/template/claude-task-manager/lib/transport-security.js +84 -1
  159. package/template/claude-task-manager/lib/wait-state.js +184 -0
  160. package/template/claude-task-manager/lib/walle-client.js +47 -5
  161. package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
  162. package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
  163. package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
  164. package/template/claude-task-manager/lib/walle-native-health.js +403 -0
  165. package/template/claude-task-manager/lib/walle-repair.js +701 -0
  166. package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
  167. package/template/claude-task-manager/lib/walle-session-context.js +57 -21
  168. package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
  169. package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
  170. package/template/claude-task-manager/lib/walle-transcript.js +52 -0
  171. package/template/claude-task-manager/lib/worktree-active-sync.js +11 -7
  172. package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
  173. package/template/claude-task-manager/package.json +1 -1
  174. package/template/claude-task-manager/prompt-harvest.js +89 -66
  175. package/template/claude-task-manager/providers/claude-code.js +51 -3
  176. package/template/claude-task-manager/providers/cursor.js +140 -45
  177. package/template/claude-task-manager/public/css/reviews.css +551 -61
  178. package/template/claude-task-manager/public/css/setup.css +191 -0
  179. package/template/claude-task-manager/public/css/walle-session.css +865 -10
  180. package/template/claude-task-manager/public/css/walle.css +154 -0
  181. package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
  182. package/template/claude-task-manager/public/index.html +18516 -2058
  183. package/template/claude-task-manager/public/ipad.html +363 -0
  184. package/template/claude-task-manager/public/js/document-review-links.js +301 -0
  185. package/template/claude-task-manager/public/js/image-normalize.js +69 -36
  186. package/template/claude-task-manager/public/js/message-renderer.js +1265 -77
  187. package/template/claude-task-manager/public/js/prompts.js +66 -29
  188. package/template/claude-task-manager/public/js/reviews.js +901 -133
  189. package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
  190. package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
  191. package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
  192. package/template/claude-task-manager/public/js/setup.js +1273 -176
  193. package/template/claude-task-manager/public/js/stream-view.js +691 -73
  194. package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
  195. package/template/claude-task-manager/public/js/walle-session.js +2455 -158
  196. package/template/claude-task-manager/public/js/walle.js +455 -28
  197. package/template/claude-task-manager/public/m/app.css +2909 -262
  198. package/template/claude-task-manager/public/m/app.js +6601 -398
  199. package/template/claude-task-manager/public/m/claim.html +224 -17
  200. package/template/claude-task-manager/public/m/index.html +117 -21
  201. package/template/claude-task-manager/public/m/sw.js +3 -1
  202. package/template/claude-task-manager/public/manifest.json +2 -2
  203. package/template/claude-task-manager/public/prompts.html +30 -14
  204. package/template/claude-task-manager/queue-engine.js +507 -28
  205. package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
  206. package/template/claude-task-manager/server.js +14341 -2197
  207. package/template/claude-task-manager/session-integrity.js +160 -18
  208. package/template/claude-task-manager/session-search-ranking.js +1 -0
  209. package/template/claude-task-manager/session-utils.js +25 -5
  210. package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
  211. package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
  212. package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
  213. package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
  214. package/template/claude-task-manager/workers/harvest-worker.js +9 -55
  215. package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
  216. package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
  217. package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
  218. package/template/claude-task-manager/workers/session-host-process.js +146 -0
  219. package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
  220. package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
  221. package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
  222. package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
  223. package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
  224. package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
  225. package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
  226. package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
  227. package/template/docs/design/markdown-review-pane.md +206 -0
  228. package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +129 -38
  229. package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
  230. package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
  231. package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
  232. package/template/docs/private-memory-and-pii-policy.md +69 -0
  233. package/template/package.json +2 -1
  234. package/template/scripts/check-private-data.js +201 -0
  235. package/template/shared/sqlite-owner-guard.js +30 -0
  236. package/template/shared/sqlite-owner-write-queue.js +225 -0
  237. package/template/shared/sqlite-storage-policy.js +111 -0
  238. package/template/shared/sqlite-write-lock.js +428 -0
  239. package/template/wall-e/agent-runners/claude-code.js +5 -0
  240. package/template/wall-e/agent.js +166 -22
  241. package/template/wall-e/api-walle.js +524 -70
  242. package/template/wall-e/auth/provider-flows.js +11 -1
  243. package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
  244. package/template/wall-e/brain.js +1614 -141
  245. package/template/wall-e/chat/attachment-blocks.js +96 -0
  246. package/template/wall-e/chat/attachments.js +2 -1
  247. package/template/wall-e/chat/capability-resolver.js +7 -7
  248. package/template/wall-e/chat/context-messages.js +28 -0
  249. package/template/wall-e/chat/conversation-frame.js +630 -0
  250. package/template/wall-e/chat/provider-messages.js +125 -0
  251. package/template/wall-e/chat.js +1002 -233
  252. package/template/wall-e/coding/acceptance-contract.js +170 -0
  253. package/template/wall-e/coding/acp-adapter.js +1 -1
  254. package/template/wall-e/coding/agent-catalog.js +3 -0
  255. package/template/wall-e/coding/artifact-store.js +93 -0
  256. package/template/wall-e/coding/capability-router.js +120 -0
  257. package/template/wall-e/coding/coding-run-controller.js +423 -0
  258. package/template/wall-e/coding/compaction-service.js +157 -12
  259. package/template/wall-e/coding/frontend-verification.js +258 -0
  260. package/template/wall-e/coding/lifecycle-hooks.js +75 -0
  261. package/template/wall-e/coding/local-preview-contract.js +157 -0
  262. package/template/wall-e/coding/permission-service.js +57 -13
  263. package/template/wall-e/coding/prompt-bundle.js +19 -1
  264. package/template/wall-e/coding/prompt-section-registry.js +227 -0
  265. package/template/wall-e/coding/provider-compat.js +15 -0
  266. package/template/wall-e/coding/runtime-events.js +224 -0
  267. package/template/wall-e/coding/runtime-mode.js +3 -0
  268. package/template/wall-e/coding/side-git-snapshot.js +160 -4
  269. package/template/wall-e/coding/snapshot-service.js +143 -1
  270. package/template/wall-e/coding/stream-processor.js +388 -34
  271. package/template/wall-e/coding/task-tool.js +141 -4
  272. package/template/wall-e/coding/tool-execution-controller.js +365 -0
  273. package/template/wall-e/coding/tool-registry.js +43 -5
  274. package/template/wall-e/coding/user-hooks.js +217 -0
  275. package/template/wall-e/coding-orchestrator.js +1330 -221
  276. package/template/wall-e/coding-prompts.js +20 -4
  277. package/template/wall-e/context/context-builder.js +15 -2
  278. package/template/wall-e/decision/confidence.js +1 -1
  279. package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
  280. package/template/wall-e/docs/external-action-controller.md +26 -6
  281. package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
  282. package/template/wall-e/embeddings.js +591 -53
  283. package/template/wall-e/external-action-controller.js +12 -0
  284. package/template/wall-e/http/auth.js +1 -0
  285. package/template/wall-e/http/chat-api.js +46 -11
  286. package/template/wall-e/http/model-admin.js +836 -34
  287. package/template/wall-e/lib/boot-profile.js +88 -0
  288. package/template/wall-e/lib/event-loop-monitor.js +93 -0
  289. package/template/wall-e/lib/service-health.js +194 -0
  290. package/template/wall-e/llm/anthropic.js +130 -5
  291. package/template/wall-e/llm/client.js +266 -63
  292. package/template/wall-e/llm/default-fallback.js +382 -0
  293. package/template/wall-e/llm/health.js +19 -0
  294. package/template/wall-e/llm/message-guard.js +78 -0
  295. package/template/wall-e/llm/model-catalog.js +252 -1
  296. package/template/wall-e/llm/openai.js +26 -4
  297. package/template/wall-e/llm/portkey-sync.js +654 -0
  298. package/template/wall-e/llm/provider-error.js +30 -2
  299. package/template/wall-e/llm/registry.js +5 -1
  300. package/template/wall-e/llm/request-compat.js +67 -0
  301. package/template/wall-e/loops/backfill.js +79 -23
  302. package/template/wall-e/loops/brain-optimize.js +67 -0
  303. package/template/wall-e/loops/ingest.js +25 -10
  304. package/template/wall-e/loops/question-digest.js +160 -0
  305. package/template/wall-e/loops/reflect.js +6 -4
  306. package/template/wall-e/loops/think.js +39 -12
  307. package/template/wall-e/mcp-server.js +318 -36
  308. package/template/wall-e/memory/ctm-context-client.js +52 -14
  309. package/template/wall-e/memory/ctm-operational-context.js +237 -0
  310. package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
  311. package/template/wall-e/memory/ctm-session-context.js +111 -63
  312. package/template/wall-e/prompts/coding/deepseek.txt +3 -0
  313. package/template/wall-e/prompts/coding/gemini.txt +6 -0
  314. package/template/wall-e/prompts/coding/gpt.txt +6 -0
  315. package/template/wall-e/prompts/coding/local.txt +7 -0
  316. package/template/wall-e/runtime/decision-hooks.js +115 -0
  317. package/template/wall-e/runtime/devbox-gateway.js +82 -8
  318. package/template/wall-e/runtime/prompt-manifest.js +86 -0
  319. package/template/wall-e/runtime/tool-executor.js +269 -0
  320. package/template/wall-e/runtime/tool-result-envelope.js +138 -0
  321. package/template/wall-e/runtime/transcript-projection.js +60 -0
  322. package/template/wall-e/runtime/walle-runtime.js +224 -0
  323. package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
  324. package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
  325. package/template/wall-e/server.js +15 -0
  326. package/template/wall-e/session-files.js +9 -0
  327. package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
  328. package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
  329. package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
  330. package/template/wall-e/skills/claude-code-reader.js +7 -3
  331. package/template/wall-e/skills/script-skill-runner.js +10 -0
  332. package/template/wall-e/skills/skill-planner.js +38 -0
  333. package/template/wall-e/tools/builtin-middleware.js +19 -9
  334. package/template/wall-e/tools/local-tools.js +1428 -16
  335. package/template/wall-e/tools/permission-checker.js +73 -5
  336. package/template/wall-e/tools/question-manager.js +117 -7
  337. package/template/wall-e/training/harvester.js +12 -28
  338. package/template/wall-e/training/replay.js +25 -80
  339. package/template/website/index.html +10 -10
  340. package/template/wall-e/eval/ab-test.js +0 -203
  341. package/template/wall-e/eval/agent-runner.js +0 -772
  342. package/template/wall-e/eval/agent-scorer.js +0 -461
  343. package/template/wall-e/eval/aggregator.js +0 -414
  344. package/template/wall-e/eval/allowed-test-commands.js +0 -34
  345. package/template/wall-e/eval/benchmark-generator.js +0 -113
  346. package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
  347. package/template/wall-e/eval/benchmarks/chat.json +0 -82
  348. package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
  349. package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
  350. package/template/wall-e/eval/benchmarks/coding.json +0 -122
  351. package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
  352. package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
  353. package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
  354. package/template/wall-e/eval/benchmarks.js +0 -669
  355. package/template/wall-e/eval/cc-replay.js +0 -719
  356. package/template/wall-e/eval/chat-eval.js +0 -525
  357. package/template/wall-e/eval/check-keys.js +0 -15
  358. package/template/wall-e/eval/check-providers.js +0 -42
  359. package/template/wall-e/eval/codex-cli-baseline.js +0 -669
  360. package/template/wall-e/eval/coding-agent-real.js +0 -570
  361. package/template/wall-e/eval/context-compactor.js +0 -251
  362. package/template/wall-e/eval/debug-agent003.js +0 -68
  363. package/template/wall-e/eval/diagnostics.js +0 -216
  364. package/template/wall-e/eval/eval-orchestrator.js +0 -642
  365. package/template/wall-e/eval/evaluate.js +0 -202
  366. package/template/wall-e/eval/evaluator.js +0 -373
  367. package/template/wall-e/eval/exporter.js +0 -212
  368. package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
  369. package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
  370. package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
  371. package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
  372. package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
  373. package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
  374. package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
  375. package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
  376. package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
  377. package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
  378. package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
  379. package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
  380. package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
  381. package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
  382. package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
  383. package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
  384. package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
  385. package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
  386. package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
  387. package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
  388. package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
  389. package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
  390. package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
  391. package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
  392. package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
  393. package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
  394. package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
  395. package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
  396. package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
  397. package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
  398. package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
  399. package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
  400. package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
  401. package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
  402. package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
  403. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
  404. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
  405. package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
  406. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
  407. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
  408. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
  409. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
  410. package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
  411. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
  412. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
  413. package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
  414. package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
  415. package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
  416. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
  417. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
  418. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
  419. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
  420. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
  421. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
  422. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
  423. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
  424. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
  425. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
  426. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
  427. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
  428. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
  429. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
  430. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
  431. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
  432. package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
  433. package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
  434. package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
  435. package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
  436. package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
  437. package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
  438. package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
  439. package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
  440. package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
  441. package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
  442. package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
  443. package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
  444. package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
  445. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
  446. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
  447. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
  448. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
  449. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
  450. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
  451. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
  452. package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
  453. package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
  454. package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
  455. package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
  456. package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
  457. package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
  458. package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
  459. package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
  460. package/template/wall-e/eval/harvester.js +0 -685
  461. package/template/wall-e/eval/head-to-head.js +0 -388
  462. package/template/wall-e/eval/humaneval-adapter.js +0 -321
  463. package/template/wall-e/eval/list-models.js +0 -31
  464. package/template/wall-e/eval/livecodebench-adapter.js +0 -291
  465. package/template/wall-e/eval/mail-integration.js +0 -443
  466. package/template/wall-e/eval/manifest.js +0 -186
  467. package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
  468. package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
  469. package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
  470. package/template/wall-e/eval/meta-harness/cli.js +0 -86
  471. package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
  472. package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
  473. package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
  474. package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
  475. package/template/wall-e/eval/meta-harness/frontier.js +0 -96
  476. package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
  477. package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
  478. package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
  479. package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
  480. package/template/wall-e/eval/meta-harness/reporting.js +0 -58
  481. package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
  482. package/template/wall-e/eval/meta-harness/validation.js +0 -81
  483. package/template/wall-e/eval/promoter.js +0 -228
  484. package/template/wall-e/eval/provider-normalizer.js +0 -33
  485. package/template/wall-e/eval/replay.js +0 -395
  486. package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
  487. package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
  488. package/template/wall-e/eval/run-coding-agent-real.js +0 -187
  489. package/template/wall-e/eval/run-eval.js +0 -435
  490. package/template/wall-e/eval/run-model-comparison.js +0 -142
  491. package/template/wall-e/eval/session-evaluator.js +0 -187
  492. package/template/wall-e/eval/session-miner.js +0 -207
  493. package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
  494. package/template/wall-e/eval/session-transcripts.js +0 -509
  495. package/template/wall-e/eval/shadow.js +0 -161
  496. package/template/wall-e/eval/swebench-adapter.js +0 -345
  497. package/template/wall-e/eval/swebench-docker.js +0 -192
  498. package/template/wall-e/eval/train.py +0 -320
  499. package/template/wall-e/eval/trainer.js +0 -232
  500. package/template/wall-e/eval/weekly-eval-loop.js +0 -241
@@ -1,10 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  const fs = require('fs');
4
+ const http = require('http');
4
5
  const net = require('net');
5
6
  const os = require('os');
6
7
  const path = require('path');
7
8
  const { spawn, execFile } = require('child_process');
9
+ const { processTitle: formatProcessTitle, processTitleCandidates } = require('./process-title');
10
+ const {
11
+ checkWalleNativeDeps,
12
+ rebuildWalleNativeDeps,
13
+ shouldRebuildNativeDeps,
14
+ } = require('./walle-native-health');
8
15
 
9
16
  const RESTART_DELAY_MS = 5000;
10
17
  const RESTART_BURST = 5;
@@ -73,15 +80,318 @@ function createWalleSupervisor({
73
80
  telemetry = { track() {} },
74
81
  isDisabled = () => !!process.env.WALLE_DISABLED,
75
82
  processOps = defaultProcessOps,
83
+ nativeDeps = { check: checkWalleNativeDeps, rebuild: rebuildWalleNativeDeps, shouldRebuild: shouldRebuildNativeDeps },
84
+ spawnProcess = spawn,
85
+ nativeCheckIntervalMs = 60000,
86
+ mcpReadyTimeoutMs = 30000,
87
+ mcpReadyRetryMs = 250,
88
+ mcpReadyProbe = null,
89
+ // How often getStatus() may re-probe a running Wall-E whose last verdict is
90
+ // not-ready, to self-heal a stale startup timeout (a too-short probe vs a slow
91
+ // brain boot). Throttled so frequent status polls don't hammer the MCP endpoint.
92
+ mcpReadySelfHealIntervalMs = 3000,
76
93
  }) {
77
94
  let intentionallyStopped = false;
78
95
  let starting = false;
79
96
  let child = null;
80
97
  let childPid = null;
81
98
  let restartHistory = [];
99
+ let lastNativeHealth = null;
100
+ let lastNativeHealthAt = 0;
101
+ let lastStartError = null;
102
+ let lastMcpReady = null;
103
+ let lastSelfHealProbeAt = 0;
82
104
 
83
105
  const pidFile = () => path.join(configDir, 'walle.pid');
84
- const processTitle = () => `walle-${instanceTag || 'primary'}`;
106
+ const processTitle = () => formatProcessTitle('walle', instanceTag || 'primary');
107
+ const processTitles = () => processTitleCandidates('walle', instanceTag || 'primary');
108
+ const walleDir = () => path.join(ctmDir, '..', 'wall-e');
109
+
110
+ function _nativeErrorPayload(health) {
111
+ const h = health || lastNativeHealth || {};
112
+ return {
113
+ ok: false,
114
+ code: h.code || 'walle_native_dependency_failed',
115
+ message: h.message || 'Wall-E native dependency check failed.',
116
+ nativeDependency: h,
117
+ };
118
+ }
119
+
120
+ function requestMcpJson(message, { timeoutMs = 1000 } = {}) {
121
+ const body = JSON.stringify(message);
122
+ return new Promise((resolve, reject) => {
123
+ const req = http.request({
124
+ hostname: '127.0.0.1',
125
+ port: wallePort,
126
+ path: '/mcp',
127
+ method: 'POST',
128
+ headers: {
129
+ 'Content-Type': 'application/json',
130
+ 'Content-Length': Buffer.byteLength(body),
131
+ 'MCP-Protocol-Version': '2025-06-18',
132
+ ...(walleToken ? { Authorization: `Bearer ${walleToken}` } : {}),
133
+ },
134
+ timeout: timeoutMs,
135
+ }, (res) => {
136
+ let raw = '';
137
+ res.setEncoding('utf8');
138
+ res.on('data', chunk => { raw += chunk; });
139
+ res.on('end', () => {
140
+ if (res.statusCode < 200 || res.statusCode >= 300) {
141
+ reject(new Error(`Wall-E MCP returned HTTP ${res.statusCode}: ${raw.slice(0, 300)}`));
142
+ return;
143
+ }
144
+ try {
145
+ const parsed = raw.trim() ? JSON.parse(raw) : null;
146
+ if (parsed?.error) reject(new Error(`Wall-E MCP JSON-RPC error: ${parsed.error.message || parsed.error.code}`));
147
+ else resolve(parsed);
148
+ } catch (err) {
149
+ reject(new Error(`Wall-E MCP returned invalid JSON: ${err.message}`));
150
+ }
151
+ });
152
+ });
153
+ req.on('timeout', () => req.destroy(new Error('Wall-E MCP readiness request timed out')));
154
+ req.on('error', reject);
155
+ req.end(body);
156
+ });
157
+ }
158
+
159
+ async function defaultMcpReadyProbe() {
160
+ const init = await requestMcpJson({
161
+ jsonrpc: '2.0',
162
+ id: 1,
163
+ method: 'initialize',
164
+ params: {
165
+ protocolVersion: '2025-06-18',
166
+ capabilities: {},
167
+ clientInfo: { name: 'ctm-walle-supervisor', version: '1.0.0' },
168
+ },
169
+ });
170
+ if (init?.result?.serverInfo?.name !== 'wall-e') {
171
+ throw new Error('Wall-E MCP initialize did not return serverInfo.name=wall-e');
172
+ }
173
+ const tools = await requestMcpJson({
174
+ jsonrpc: '2.0',
175
+ id: 2,
176
+ method: 'tools/list',
177
+ params: {},
178
+ });
179
+ const list = tools?.result?.tools;
180
+ if (!Array.isArray(list) || !list.some(tool => tool?.name === 'walle_memory_status')) {
181
+ throw new Error('Wall-E MCP tools/list did not include walle_memory_status');
182
+ }
183
+ const status = await requestMcpJson({
184
+ jsonrpc: '2.0',
185
+ id: 3,
186
+ method: 'tools/call',
187
+ params: { name: 'walle_memory_status', arguments: {} },
188
+ });
189
+ const result = status?.result || {};
190
+ if (result.isError) {
191
+ throw new Error('Wall-E MCP walle_memory_status returned an error result');
192
+ }
193
+ let structured = result.structuredContent;
194
+ if (!structured && Array.isArray(result.content)) {
195
+ const text = result.content.find(item => item?.type === 'text' && item.text)?.text;
196
+ if (text) {
197
+ try { structured = JSON.parse(text); } catch {}
198
+ }
199
+ }
200
+ if (!structured || typeof structured !== 'object') {
201
+ throw new Error('Wall-E MCP walle_memory_status did not return structured health');
202
+ }
203
+ if (structured.ok === false) {
204
+ throw new Error(`Wall-E MCP walle_memory_status is not healthy: ${structured.code || structured.error || 'unknown'}`);
205
+ }
206
+ return { ok: true, toolCount: list.length, memoryStatusOk: true };
207
+ }
208
+
209
+ async function waitForMcpReady(pid, source, options = {}) {
210
+ const timeoutMs = Math.max(0, Number(options.timeoutMs ?? mcpReadyTimeoutMs));
211
+ const retryMs = Math.max(25, Number(options.retryMs ?? mcpReadyRetryMs));
212
+ const deadline = Date.now() + timeoutMs;
213
+ const startedAt = Date.now();
214
+ const probe = mcpReadyProbe || defaultMcpReadyProbe;
215
+ let attempts = 0;
216
+ let lastErr = null;
217
+
218
+ while (attempts === 0 || Date.now() <= deadline) {
219
+ attempts += 1;
220
+ if (pid && !isAlive(pid)) {
221
+ lastMcpReady = {
222
+ ok: false,
223
+ code: 'walle_exited_before_mcp_ready',
224
+ message: `Wall-E process ${pid} exited before MCP became ready.`,
225
+ pid,
226
+ source,
227
+ attempts,
228
+ elapsedMs: Date.now() - startedAt,
229
+ };
230
+ lastStartError = {
231
+ ok: false,
232
+ code: lastMcpReady.code,
233
+ message: lastMcpReady.message,
234
+ };
235
+ return lastMcpReady;
236
+ }
237
+ try {
238
+ const result = await probe({
239
+ pid,
240
+ port: wallePort,
241
+ token: walleToken,
242
+ source,
243
+ requestMcpJson,
244
+ });
245
+ if (result && typeof result === 'object' && result.ok === false) {
246
+ const probeErr = new Error(result.message || result.error || result.code || 'Wall-E MCP readiness probe failed');
247
+ probeErr.code = result.code || 'walle_mcp_ready_failed';
248
+ throw probeErr;
249
+ }
250
+ lastMcpReady = {
251
+ ok: true,
252
+ code: 'ok',
253
+ message: 'Wall-E MCP is ready.',
254
+ pid,
255
+ source,
256
+ attempts,
257
+ elapsedMs: Date.now() - startedAt,
258
+ ...(result && typeof result === 'object' ? result : {}),
259
+ };
260
+ lastStartError = null;
261
+ return lastMcpReady;
262
+ } catch (err) {
263
+ lastErr = err;
264
+ }
265
+ if (Date.now() > deadline) break;
266
+ await sleep(retryMs);
267
+ }
268
+
269
+ lastMcpReady = {
270
+ ok: false,
271
+ code: 'walle_mcp_ready_timeout',
272
+ message: `Wall-E process ${pid || 'unknown'} did not become MCP-ready within ${timeoutMs}ms: ${lastErr?.message || 'unknown error'}`,
273
+ pid: pid || null,
274
+ source,
275
+ attempts,
276
+ elapsedMs: Date.now() - startedAt,
277
+ lastError: lastErr ? { message: lastErr.message, code: lastErr.code || '' } : null,
278
+ };
279
+ lastStartError = {
280
+ ok: false,
281
+ code: lastMcpReady.code,
282
+ message: lastMcpReady.message,
283
+ };
284
+ try {
285
+ telemetry.track('walle_mcp_ready_failed', {
286
+ source: source || 'unknown',
287
+ code: lastMcpReady.code,
288
+ attempts,
289
+ elapsed_ms: lastMcpReady.elapsedMs,
290
+ message: String(lastMcpReady.message || '').slice(0, 240),
291
+ });
292
+ } catch {}
293
+ return lastMcpReady;
294
+ }
295
+
296
+ async function getNativeDependencyStatus({ force = false } = {}) {
297
+ const now = Date.now();
298
+ if (!force && lastNativeHealth && now - lastNativeHealthAt < nativeCheckIntervalMs) {
299
+ return lastNativeHealth;
300
+ }
301
+ try {
302
+ lastNativeHealth = await nativeDeps.check({
303
+ walleDir: walleDir(),
304
+ nodePath: process.execPath,
305
+ });
306
+ } catch (err) {
307
+ lastNativeHealth = {
308
+ ok: false,
309
+ code: 'native_dependency_check_failed',
310
+ message: err.message || String(err),
311
+ error: { message: err.message || String(err) },
312
+ };
313
+ }
314
+ lastNativeHealthAt = now;
315
+ return lastNativeHealth;
316
+ }
317
+
318
+ async function ensureNativeDependenciesReady(source, { allowRebuild = true } = {}) {
319
+ let health = await getNativeDependencyStatus({ force: true });
320
+ if (health.ok) {
321
+ lastStartError = null;
322
+ return { ok: true, health };
323
+ }
324
+
325
+ if (allowRebuild && nativeDeps.shouldRebuild(health)) {
326
+ let rebuild = null;
327
+ try {
328
+ rebuild = await nativeDeps.rebuild({
329
+ walleDir: walleDir(),
330
+ nodePath: process.execPath,
331
+ });
332
+ } catch (err) {
333
+ rebuild = {
334
+ ok: false,
335
+ code: 'native_dependency_rebuild_failed',
336
+ message: err.message || String(err),
337
+ };
338
+ }
339
+ health = {
340
+ ...(await getNativeDependencyStatus({ force: true })),
341
+ rebuild_attempted: true,
342
+ rebuild,
343
+ };
344
+ }
345
+
346
+ if (!health.ok) {
347
+ lastStartError = _nativeErrorPayload(health);
348
+ try {
349
+ telemetry.track('walle_native_dependency_failed', {
350
+ source: source || 'unknown',
351
+ code: health.code || 'unknown',
352
+ message: String(health.message || '').slice(0, 240),
353
+ node: health.node || {},
354
+ rebuild_attempted: !!health.rebuild_attempted,
355
+ rebuild_ok: !!health.rebuild?.ok,
356
+ });
357
+ } catch {}
358
+ return { ok: false, health };
359
+ }
360
+
361
+ lastStartError = null;
362
+ return { ok: true, health };
363
+ }
364
+
365
+ async function statusWithDiagnostics(base, { checkNative = false } = {}) {
366
+ let nativeDependency = lastNativeHealth;
367
+ if (checkNative) nativeDependency = await getNativeDependencyStatus({ force: false });
368
+ // Self-heal a stale MCP-not-ready verdict. A startup probe can time out before a
369
+ // large brain finishes booting (e.g. the first daily-backup VACUUM), leaving a
370
+ // sticky false "MCP never became ready" even though the daemon is now serving. If
371
+ // the process is running but the last verdict is not-ok, re-probe (throttled) — a
372
+ // successful mcpReadyProbeOnce() clears it; a failed probe leaves the verdict intact.
373
+ if (base.running && base.pid && (!lastMcpReady || lastMcpReady.ok === false)) {
374
+ const now = Date.now();
375
+ if (now - lastSelfHealProbeAt >= mcpReadySelfHealIntervalMs) {
376
+ lastSelfHealProbeAt = now;
377
+ try { await mcpReadyProbeOnce({ pid: base.pid, source: 'watchdog', timeoutMs: 2500 }); } catch {}
378
+ }
379
+ }
380
+ const stoppedNativeFailure = nativeDependency && nativeDependency.ok === false ? nativeDependency : null;
381
+ const effectiveError = base.running ? null : (lastStartError || (stoppedNativeFailure ? _nativeErrorPayload(stoppedNativeFailure) : null));
382
+ return {
383
+ ...base,
384
+ code: effectiveError ? effectiveError.code : null,
385
+ error: effectiveError ? effectiveError.message : null,
386
+ nativeDependency: nativeDependency || null,
387
+ lastStartError: lastStartError || null,
388
+ mcpReady: lastMcpReady || null,
389
+ };
390
+ }
391
+
392
+ function sleep(ms) {
393
+ return new Promise(resolve => setTimeout(resolve, ms));
394
+ }
85
395
 
86
396
  function waitForPortFree() {
87
397
  return new Promise((resolve) => {
@@ -110,11 +420,10 @@ function createWalleSupervisor({
110
420
  if (savedPid && savedPid !== myPid) pidSet.add(savedPid);
111
421
  } catch {}
112
422
 
113
- const title = processTitle();
114
- const discovered = await Promise.all([
423
+ const discovered = await Promise.all(processTitles().flatMap(title => [
115
424
  processOps.findPidsByExactCommand ? processOps.findPidsByExactCommand(title) : [],
116
425
  processOps.findListeningPidsByExactCommand ? processOps.findListeningPidsByExactCommand(wallePort, title) : [],
117
- ]);
426
+ ]));
118
427
  for (const p of discovered.flat()) {
119
428
  if (p && p !== myPid) pidSet.add(p);
120
429
  }
@@ -194,6 +503,12 @@ function createWalleSupervisor({
194
503
  return waitForPortFree();
195
504
  }
196
505
 
506
+ async function stopForProcessExit(reason = 'process-exit') {
507
+ intentionallyStopped = true;
508
+ try { telemetry.track('walle_stop_for_process_exit', { reason, port: wallePort }); } catch {}
509
+ return killAll();
510
+ }
511
+
197
512
  function inCrashLoop() {
198
513
  const now = Date.now();
199
514
  restartHistory = restartHistory.filter(t => now - t < RESTART_WINDOW_MS);
@@ -201,8 +516,8 @@ function createWalleSupervisor({
201
516
  }
202
517
 
203
518
  function spawnWalle(source) {
204
- const walleDir = path.join(ctmDir, '..', 'wall-e');
205
- const agentScript = path.join(walleDir, 'agent.js');
519
+ const dir = walleDir();
520
+ const agentScript = path.join(dir, 'agent.js');
206
521
  let stderrTarget = 'ignore';
207
522
  let crashLogFd = null;
208
523
  try {
@@ -218,17 +533,20 @@ function createWalleSupervisor({
218
533
  CTM_API_BASE_URL: `http://127.0.0.1:${ctmPort}`,
219
534
  WALL_E_PORT: String(wallePort),
220
535
  WALLE_INSTANCE_TAG: instanceTag,
536
+ WALL_E_PROCESS_ROLE: 'walle-daemon',
221
537
  };
538
+ delete childEnv.CTM_PROCESS_ROLE;
222
539
  if (walleToken) childEnv.WALL_E_API_TOKEN = walleToken;
223
540
 
224
- const nextChild = spawn(
541
+ const nextChild = spawnProcess(
225
542
  process.execPath,
226
543
  [agentScript],
227
544
  {
228
- cwd: walleDir,
545
+ cwd: dir,
229
546
  detached: true,
230
547
  stdio: ['ignore', 'ignore', stderrTarget],
231
548
  env: childEnv,
549
+ argv0: processTitle(),
232
550
  }
233
551
  );
234
552
  nextChild.unref();
@@ -248,6 +566,11 @@ function createWalleSupervisor({
248
566
  restartHistory.push(Date.now());
249
567
  if (inCrashLoop()) {
250
568
  console.error(`[wall-e] Crash loop detected (${RESTART_BURST} restarts in ${RESTART_WINDOW_MS / 1000}s) - giving up. Use /api/start/walle to retry.`);
569
+ lastStartError = {
570
+ ok: false,
571
+ code: 'walle_crash_loop',
572
+ message: `Wall-E crashed ${RESTART_BURST} times in ${RESTART_WINDOW_MS / 1000}s and the supervisor stopped retrying.`,
573
+ };
251
574
  try { telemetry.track('walle_crash_loop', { lastPid: myPid, code, signal }); } catch {}
252
575
  intentionallyStopped = true;
253
576
  return;
@@ -271,48 +594,47 @@ function createWalleSupervisor({
271
594
  let stalePid = null;
272
595
 
273
596
  if (childPid && isAlive(childPid)) {
274
- return {
597
+ return statusWithDiagnostics({
275
598
  running: true,
276
599
  pid: childPid,
277
600
  pidSource: 'child',
278
601
  stalePid: savedPid && savedPid !== childPid ? savedPid : null,
279
602
  repairedPidFile: savedPid !== childPid ? writePidFile(childPid) : false,
280
- };
603
+ });
281
604
  }
282
605
 
283
606
  if (savedPid && isAlive(savedPid)) {
284
- return { running: true, pid: savedPid, pidSource: 'pid_file' };
607
+ return statusWithDiagnostics({ running: true, pid: savedPid, pidSource: 'pid_file' });
285
608
  }
286
609
  if (savedPid) stalePid = savedPid;
287
610
 
288
- const title = processTitle();
289
611
  let discovered = [];
290
612
  try {
291
- const results = await Promise.all([
613
+ const results = await Promise.all(processTitles().flatMap(title => [
292
614
  processOps.findPidsByExactCommand ? processOps.findPidsByExactCommand(title) : [],
293
615
  processOps.findListeningPidsByExactCommand ? processOps.findListeningPidsByExactCommand(wallePort, title) : [],
294
- ]);
616
+ ]));
295
617
  discovered = [...new Set(results.flat().filter(pid => pid && isAlive(pid)))];
296
618
  } catch {}
297
619
 
298
620
  if (discovered.length > 0) {
299
621
  const pid = discovered[0];
300
- return {
622
+ return statusWithDiagnostics({
301
623
  running: true,
302
624
  pid,
303
625
  pidSource: 'discovered',
304
626
  stalePid,
305
627
  repairedPidFile: writePidFile(pid),
306
- };
628
+ });
307
629
  }
308
630
 
309
- return {
631
+ return statusWithDiagnostics({
310
632
  running: false,
311
633
  pid: null,
312
634
  pidSource: stalePid ? 'stale_pid_file' : 'none',
313
635
  stalePid,
314
636
  removedStalePidFile: stalePid ? removePidFile() : false,
315
- };
637
+ }, { checkNative: true });
316
638
  }
317
639
 
318
640
  function apiStop(req, res) {
@@ -321,77 +643,227 @@ function createWalleSupervisor({
321
643
  killAll().then(() => writeJson(res, 200, { ok: true, message: 'Wall-E stopped' }));
322
644
  }
323
645
 
324
- function apiStart(req, res) {
646
+ async function apiStart(req, res) {
325
647
  if (starting) {
326
648
  return writeJson(res, 409, { ok: false, message: 'Wall-E start already in progress' });
327
649
  }
328
650
  starting = true;
329
651
  intentionallyStopped = false;
330
652
  restartHistory = [];
331
- if (childPid) {
332
- try {
333
- process.kill(childPid, 0);
334
- starting = false;
335
- return writeJson(res, 200, { ok: true, message: 'Wall-E is already running on port ' + wallePort });
336
- } catch {}
337
- }
338
-
339
- let orphanPid = null;
340
653
  try {
341
- const saved = parseInt(fs.readFileSync(pidFile(), 'utf8').trim(), 10);
342
- if (saved) {
343
- process.kill(saved, 0);
344
- orphanPid = saved;
654
+ if (childPid && isAlive(childPid)) {
655
+ const readyStatus = await mcpReadyProbeOnce({ pid: childPid, source: 'start_api_existing', timeoutMs: 2500 });
656
+ if (readyStatus.ok) {
657
+ return writeJson(res, 200, {
658
+ ok: true,
659
+ message: 'Wall-E is already running and MCP-ready on port ' + wallePort,
660
+ pid: childPid,
661
+ nativeDependency: lastNativeHealth || null,
662
+ mcpReady: readyStatus,
663
+ });
664
+ }
665
+ return writeJson(res, 503, {
666
+ ok: false,
667
+ code: readyStatus.code,
668
+ message: readyStatus.message,
669
+ pid: childPid,
670
+ nativeDependency: lastNativeHealth || null,
671
+ mcpReady: readyStatus,
672
+ });
345
673
  }
346
- } catch {}
347
674
 
348
- if (orphanPid) {
349
- console.log(`[wall-e] Found orphan process on port ${wallePort}: ${orphanPid} - killing before fresh start`);
350
- try { process.kill(orphanPid, 'SIGTERM'); } catch {}
351
- setTimeout(() => {
675
+ const ready = await ensureNativeDependenciesReady('start_api');
676
+ if (!ready.ok) {
677
+ return writeJson(res, 503, {
678
+ ..._nativeErrorPayload(ready.health),
679
+ ok: false,
680
+ message: `Wall-E cannot start because its native dependencies are not loadable: ${ready.health.message}`,
681
+ });
682
+ }
683
+
684
+ let orphanPid = null;
685
+ try {
686
+ const saved = parseInt(fs.readFileSync(pidFile(), 'utf8').trim(), 10);
687
+ if (saved && isAlive(saved)) orphanPid = saved;
688
+ } catch {}
689
+
690
+ if (orphanPid) {
691
+ console.log(`[wall-e] Found orphan process on port ${wallePort}: ${orphanPid} - killing before fresh start`);
692
+ try { processOps.kill(orphanPid, 'SIGTERM'); } catch {}
693
+ await sleep(3000);
352
694
  try {
353
- process.kill(orphanPid, 0);
354
- process.kill(orphanPid, 'SIGKILL');
695
+ processOps.kill(orphanPid, 0);
696
+ processOps.kill(orphanPid, 'SIGKILL');
355
697
  } catch {}
356
- setTimeout(() => {
357
- let pid = null;
358
- try { pid = spawnWalle('start_api_after_orphan_kill'); }
359
- finally { starting = false; }
360
- writeJson(res, 200, { ok: true, message: 'Wall-E starting on port ' + wallePort + ' (killed orphan)...', pid });
361
- }, 2000);
362
- }, 3000);
363
- return;
364
- }
698
+ await sleep(2000);
699
+ const pid = spawnWalle('start_api_after_orphan_kill');
700
+ const readyStatus = await waitForMcpReady(pid, 'start_api_after_orphan_kill');
701
+ if (readyStatus.ok) {
702
+ return writeJson(res, 200, {
703
+ ok: true,
704
+ message: 'Wall-E started and MCP is ready on port ' + wallePort + ' (killed orphan).',
705
+ pid,
706
+ nativeDependency: ready.health,
707
+ mcpReady: readyStatus,
708
+ });
709
+ }
710
+ return writeJson(res, 503, {
711
+ ok: false,
712
+ code: readyStatus.code,
713
+ message: readyStatus.message,
714
+ pid,
715
+ nativeDependency: ready.health,
716
+ mcpReady: readyStatus,
717
+ });
718
+ }
365
719
 
366
- let pid = null;
367
- try { pid = spawnWalle('start_api'); }
368
- finally { starting = false; }
369
- writeJson(res, 200, { ok: true, message: 'Wall-E starting on port ' + wallePort + '...', pid });
720
+ const pid = spawnWalle('start_api');
721
+ const readyStatus = await waitForMcpReady(pid, 'start_api');
722
+ if (readyStatus.ok) {
723
+ return writeJson(res, 200, {
724
+ ok: true,
725
+ message: 'Wall-E started and MCP is ready on port ' + wallePort + '.',
726
+ pid,
727
+ nativeDependency: ready.health,
728
+ mcpReady: readyStatus,
729
+ });
730
+ }
731
+ return writeJson(res, 503, {
732
+ ok: false,
733
+ code: readyStatus.code,
734
+ message: readyStatus.message,
735
+ pid,
736
+ nativeDependency: ready.health,
737
+ mcpReady: readyStatus,
738
+ });
739
+ } catch (err) {
740
+ lastStartError = {
741
+ ok: false,
742
+ code: 'walle_spawn_failed',
743
+ message: err.message || String(err),
744
+ };
745
+ return writeJson(res, 500, lastStartError);
746
+ } finally {
747
+ starting = false;
748
+ }
370
749
  }
371
750
 
372
751
  function restartQuiet() {
373
- intentionallyStopped = true;
374
- killAll().then(() => {
375
- setTimeout(() => {
752
+ ensureNativeDependenciesReady('config_change').then((ready) => {
753
+ if (!ready.ok) {
754
+ console.error(`[setup] Wall-E restart blocked: ${ready.health.message}`);
755
+ return null;
756
+ }
757
+ intentionallyStopped = true;
758
+ return killAll().then(() => sleep(2000)).then(() => {
376
759
  intentionallyStopped = false;
377
760
  const pid = spawnWalle('config_change');
378
- console.log('[setup] Restarted Wall-E (PID ' + pid + ') to pick up new API config');
379
- }, 2000);
761
+ return waitForMcpReady(pid, 'config_change').then((readyStatus) => {
762
+ if (readyStatus.ok) {
763
+ console.log('[setup] Restarted Wall-E (PID ' + pid + ') and MCP is ready to pick up new API config');
764
+ } else {
765
+ console.error(`[setup] Wall-E restarted for config change but MCP readiness failed: ${readyStatus.message}`);
766
+ }
767
+ return pid;
768
+ });
769
+ });
770
+ }).catch((err) => {
771
+ intentionallyStopped = false;
772
+ lastStartError = {
773
+ ok: false,
774
+ code: 'walle_restart_failed',
775
+ message: err.message || String(err),
776
+ };
777
+ console.error(`[setup] Wall-E restart failed: ${lastStartError.message}`);
380
778
  });
381
779
  }
382
780
 
383
- function apiRestart(req, res) {
781
+ async function apiRestart(req, res) {
782
+ const ready = await ensureNativeDependenciesReady('restart_api');
783
+ if (!ready.ok) {
784
+ return writeJson(res, 503, {
785
+ ..._nativeErrorPayload(ready.health),
786
+ ok: false,
787
+ message: `Wall-E cannot restart because its native dependencies are not loadable: ${ready.health.message}`,
788
+ });
789
+ }
384
790
  intentionallyStopped = true;
385
- killAll().then(() => {
791
+ try {
792
+ await killAll();
386
793
  intentionallyStopped = false;
387
794
  const pid = spawnWalle('restart_api');
388
- writeJson(res, 200, { ok: true, message: 'Wall-E restarting...', pid });
389
- });
795
+ const readyStatus = await waitForMcpReady(pid, 'restart_api');
796
+ if (readyStatus.ok) {
797
+ return writeJson(res, 200, {
798
+ ok: true,
799
+ message: 'Wall-E restarted and MCP is ready.',
800
+ pid,
801
+ nativeDependency: ready.health,
802
+ mcpReady: readyStatus,
803
+ });
804
+ }
805
+ return writeJson(res, 503, {
806
+ ok: false,
807
+ code: readyStatus.code,
808
+ message: readyStatus.message,
809
+ pid,
810
+ nativeDependency: ready.health,
811
+ mcpReady: readyStatus,
812
+ });
813
+ } catch (err) {
814
+ intentionallyStopped = false;
815
+ lastStartError = {
816
+ ok: false,
817
+ code: 'walle_restart_failed',
818
+ message: err.message || String(err),
819
+ };
820
+ return writeJson(res, 500, lastStartError);
821
+ }
822
+ }
823
+
824
+ // One-shot, no-retry MCP readiness probe for external health watchdogs.
825
+ // Unlike waitForMcpReady (which loops until a deadline), this performs a
826
+ // single probe. A successful probe is authoritative enough to clear stale
827
+ // startup/MCP errors left behind by an earlier timeout; otherwise service
828
+ // status can keep reporting a dead Wall-E after the daemon has recovered.
829
+ async function mcpReadyProbeOnce({ timeoutMs = 2000, source = 'watchdog', pid = childPid } = {}) {
830
+ const probe = mcpReadyProbe || defaultMcpReadyProbe;
831
+ try {
832
+ const result = await probe({
833
+ pid,
834
+ port: wallePort,
835
+ token: walleToken,
836
+ source,
837
+ requestMcpJson: (message, opts = {}) => requestMcpJson(message, { timeoutMs, ...opts }),
838
+ });
839
+ if (result && typeof result === 'object' && result.ok === false) {
840
+ return { ok: false, code: result.code || 'walle_mcp_ready_failed', message: result.message || result.error || 'Wall-E MCP readiness probe failed' };
841
+ }
842
+ lastMcpReady = { ok: true, code: 'ok', message: 'Wall-E MCP is ready.', pid, source, ...(result && typeof result === 'object' ? result : {}) };
843
+ lastStartError = null;
844
+ return lastMcpReady;
845
+ } catch (err) {
846
+ return { ok: false, code: err.code || 'walle_mcp_probe_failed', message: err.message || String(err), pid, source };
847
+ }
390
848
  }
391
849
 
392
- function bootStart() {
850
+ async function bootStart() {
393
851
  if (intentionallyStopped || isDisabled()) return Promise.resolve(null);
394
- return killAll().then(() => spawnWalle('boot'));
852
+ const ready = await ensureNativeDependenciesReady('boot');
853
+ if (!ready.ok) {
854
+ console.error(`[wall-e] Boot start blocked: ${ready.health.message}`);
855
+ return null;
856
+ }
857
+ await killAll();
858
+ const pid = spawnWalle('boot');
859
+ waitForMcpReady(pid, 'boot').then((readyStatus) => {
860
+ if (!readyStatus.ok) {
861
+ console.error(`[wall-e] Boot start MCP readiness failed: ${readyStatus.message}`);
862
+ }
863
+ }).catch((err) => {
864
+ console.error(`[wall-e] Boot start MCP readiness check threw: ${err.message}`);
865
+ });
866
+ return pid;
395
867
  }
396
868
 
397
869
  return {
@@ -400,10 +872,14 @@ function createWalleSupervisor({
400
872
  apiStop,
401
873
  bootStart,
402
874
  getStatus,
875
+ getNativeDependencyStatus,
403
876
  isIntentionallyStopped: () => intentionallyStopped,
404
877
  killAll,
878
+ mcpReadyProbeOnce,
405
879
  restartQuiet,
880
+ stopForProcessExit,
406
881
  spawnWalle,
882
+ waitForMcpReady,
407
883
  };
408
884
  }
409
885