create-walle 0.9.22 → 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 (495) hide show
  1. package/README.md +22 -0
  2. package/package.json +1 -1
  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 +1190 -182
  11. package/template/claude-task-manager/api-reviews.js +104 -13
  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 +4071 -282
  16. package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
  17. package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
  18. package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
  19. package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
  20. package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
  21. package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
  22. package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
  23. package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
  24. package/template/claude-task-manager/docs/image-paste-ux.md +10 -0
  25. package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
  26. package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
  27. package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
  28. package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
  29. package/template/claude-task-manager/docs/phone-access-design.md +53 -15
  30. package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
  31. package/template/claude-task-manager/docs/phone-setup.md +3 -0
  32. package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
  33. package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
  34. package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
  35. package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
  36. package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
  37. package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
  38. package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
  39. package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
  40. package/template/claude-task-manager/docs/session-title-authority.md +32 -0
  41. package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
  42. package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
  43. package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
  44. package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
  45. package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
  46. package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
  47. package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
  48. package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
  49. package/template/claude-task-manager/git-utils.js +751 -10
  50. package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
  51. package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
  52. package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
  53. package/template/claude-task-manager/lib/agent-presets.js +17 -1
  54. package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
  55. package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
  56. package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
  57. package/template/claude-task-manager/lib/async-semaphore.js +44 -0
  58. package/template/claude-task-manager/lib/auth-context.js +5 -0
  59. package/template/claude-task-manager/lib/auth-rate-limit.js +24 -1
  60. package/template/claude-task-manager/lib/auth-rules.js +26 -2
  61. package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
  62. package/template/claude-task-manager/lib/background-llm.js +144 -17
  63. package/template/claude-task-manager/lib/branch-inventory.js +212 -0
  64. package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
  65. package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
  66. package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
  67. package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
  68. package/template/claude-task-manager/lib/codex-zst.js +124 -0
  69. package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
  70. package/template/claude-task-manager/lib/connection-health.js +232 -0
  71. package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
  72. package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
  73. package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
  74. package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
  75. package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
  76. package/template/claude-task-manager/lib/document-review.js +109 -5
  77. package/template/claude-task-manager/lib/escalation-review.js +152 -0
  78. package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
  79. package/template/claude-task-manager/lib/headless-term-service.js +678 -0
  80. package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
  81. package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
  82. package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
  83. package/template/claude-task-manager/lib/main-db-census.js +216 -0
  84. package/template/claude-task-manager/lib/message-pagination.js +106 -4
  85. package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +669 -28
  86. package/template/claude-task-manager/lib/mobile-auth-api.js +260 -7
  87. package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
  88. package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
  89. package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
  90. package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
  91. package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
  92. package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
  93. package/template/claude-task-manager/lib/perf-tracker.js +242 -6
  94. package/template/claude-task-manager/lib/permission-match.js +76 -0
  95. package/template/claude-task-manager/lib/permission-sync.js +133 -20
  96. package/template/claude-task-manager/lib/process-title.js +35 -0
  97. package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
  98. package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
  99. package/template/claude-task-manager/lib/prompt-intent.js +132 -0
  100. package/template/claude-task-manager/lib/provider-user-context.js +34 -0
  101. package/template/claude-task-manager/lib/read-pool-client.js +313 -0
  102. package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
  103. package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
  104. package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
  105. package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
  106. package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
  107. package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
  108. package/template/claude-task-manager/lib/restart-guard.js +46 -5
  109. package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
  110. package/template/claude-task-manager/lib/restore-policy.js +13 -0
  111. package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
  112. package/template/claude-task-manager/lib/restore-runtime.js +68 -0
  113. package/template/claude-task-manager/lib/restore-storm.js +34 -0
  114. package/template/claude-task-manager/lib/resume-cwd.js +36 -0
  115. package/template/claude-task-manager/lib/resume-preflight.js +313 -0
  116. package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
  117. package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
  118. package/template/claude-task-manager/lib/scheduler.js +21 -1
  119. package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
  120. package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
  121. package/template/claude-task-manager/lib/server-listeners.js +239 -0
  122. package/template/claude-task-manager/lib/session-capture.js +42 -7
  123. package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
  124. package/template/claude-task-manager/lib/session-history.js +388 -43
  125. package/template/claude-task-manager/lib/session-host-manager.js +287 -0
  126. package/template/claude-task-manager/lib/session-image-refs.js +209 -0
  127. package/template/claude-task-manager/lib/session-jobs.js +399 -59
  128. package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
  129. package/template/claude-task-manager/lib/session-restore.js +53 -0
  130. package/template/claude-task-manager/lib/session-standup.js +87 -10
  131. package/template/claude-task-manager/lib/session-state-bus.js +14 -0
  132. package/template/claude-task-manager/lib/session-stream.js +53 -12
  133. package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
  134. package/template/claude-task-manager/lib/session-token-usage.js +494 -0
  135. package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
  136. package/template/claude-task-manager/lib/setup-network-config.js +9 -0
  137. package/template/claude-task-manager/lib/size-cap.js +45 -0
  138. package/template/claude-task-manager/lib/size-cap.test.js +62 -0
  139. package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
  140. package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
  141. package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
  142. package/template/claude-task-manager/lib/standup-attention.js +7 -3
  143. package/template/claude-task-manager/lib/status-authority.js +39 -0
  144. package/template/claude-task-manager/lib/status-hooks.js +4 -0
  145. package/template/claude-task-manager/lib/storage-migration.js +235 -0
  146. package/template/claude-task-manager/lib/structured-capture.js +298 -0
  147. package/template/claude-task-manager/lib/sync-io-census.js +163 -0
  148. package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
  149. package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
  150. package/template/claude-task-manager/lib/terminal-choice.js +364 -0
  151. package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
  152. package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
  153. package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
  154. package/template/claude-task-manager/lib/timeline-order.js +122 -0
  155. package/template/claude-task-manager/lib/transcript-store.js +348 -43
  156. package/template/claude-task-manager/lib/transport-security.js +34 -1
  157. package/template/claude-task-manager/lib/wait-state.js +184 -0
  158. package/template/claude-task-manager/lib/walle-client.js +47 -5
  159. package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
  160. package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
  161. package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
  162. package/template/claude-task-manager/lib/walle-native-health.js +403 -0
  163. package/template/claude-task-manager/lib/walle-repair.js +701 -0
  164. package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
  165. package/template/claude-task-manager/lib/walle-session-context.js +57 -21
  166. package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
  167. package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
  168. package/template/claude-task-manager/lib/walle-transcript.js +36 -0
  169. package/template/claude-task-manager/lib/worktree-active-sync.js +5 -4
  170. package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
  171. package/template/claude-task-manager/package.json +1 -1
  172. package/template/claude-task-manager/prompt-harvest.js +89 -66
  173. package/template/claude-task-manager/providers/claude-code.js +51 -3
  174. package/template/claude-task-manager/providers/cursor.js +140 -45
  175. package/template/claude-task-manager/public/css/reviews.css +541 -61
  176. package/template/claude-task-manager/public/css/setup.css +178 -0
  177. package/template/claude-task-manager/public/css/walle-session.css +865 -10
  178. package/template/claude-task-manager/public/css/walle.css +9 -0
  179. package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
  180. package/template/claude-task-manager/public/index.html +18043 -2080
  181. package/template/claude-task-manager/public/js/document-review-links.js +106 -1
  182. package/template/claude-task-manager/public/js/image-normalize.js +69 -36
  183. package/template/claude-task-manager/public/js/message-renderer.js +1252 -75
  184. package/template/claude-task-manager/public/js/prompts.js +66 -29
  185. package/template/claude-task-manager/public/js/reviews.js +871 -127
  186. package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
  187. package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
  188. package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
  189. package/template/claude-task-manager/public/js/setup.js +1238 -181
  190. package/template/claude-task-manager/public/js/stream-view.js +671 -72
  191. package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
  192. package/template/claude-task-manager/public/js/walle-session.js +2455 -158
  193. package/template/claude-task-manager/public/js/walle.js +141 -10
  194. package/template/claude-task-manager/public/m/app.css +2033 -164
  195. package/template/claude-task-manager/public/m/app.js +5633 -433
  196. package/template/claude-task-manager/public/m/claim.html +219 -19
  197. package/template/claude-task-manager/public/m/index.html +105 -16
  198. package/template/claude-task-manager/public/m/sw.js +3 -1
  199. package/template/claude-task-manager/public/manifest.json +2 -2
  200. package/template/claude-task-manager/public/prompts.html +30 -14
  201. package/template/claude-task-manager/queue-engine.js +507 -28
  202. package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
  203. package/template/claude-task-manager/server.js +13981 -2107
  204. package/template/claude-task-manager/session-integrity.js +156 -18
  205. package/template/claude-task-manager/session-search-ranking.js +1 -0
  206. package/template/claude-task-manager/session-utils.js +25 -5
  207. package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
  208. package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
  209. package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
  210. package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
  211. package/template/claude-task-manager/workers/harvest-worker.js +9 -55
  212. package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
  213. package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
  214. package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
  215. package/template/claude-task-manager/workers/session-host-process.js +146 -0
  216. package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
  217. package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
  218. package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
  219. package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
  220. package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
  221. package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
  222. package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
  223. package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
  224. package/template/docs/design/markdown-review-pane.md +206 -0
  225. package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +54 -14
  226. package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
  227. package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
  228. package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
  229. package/template/docs/private-memory-and-pii-policy.md +69 -0
  230. package/template/package.json +2 -1
  231. package/template/scripts/check-private-data.js +201 -0
  232. package/template/shared/sqlite-owner-guard.js +30 -0
  233. package/template/shared/sqlite-owner-write-queue.js +225 -0
  234. package/template/shared/sqlite-storage-policy.js +111 -0
  235. package/template/shared/sqlite-write-lock.js +428 -0
  236. package/template/wall-e/agent-runners/claude-code.js +5 -0
  237. package/template/wall-e/agent.js +166 -22
  238. package/template/wall-e/api-walle.js +505 -69
  239. package/template/wall-e/auth/provider-flows.js +11 -1
  240. package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
  241. package/template/wall-e/brain.js +1463 -136
  242. package/template/wall-e/chat/attachment-blocks.js +96 -0
  243. package/template/wall-e/chat/attachments.js +2 -1
  244. package/template/wall-e/chat/capability-resolver.js +7 -7
  245. package/template/wall-e/chat/context-messages.js +28 -0
  246. package/template/wall-e/chat/conversation-frame.js +630 -0
  247. package/template/wall-e/chat/provider-messages.js +125 -0
  248. package/template/wall-e/chat.js +926 -242
  249. package/template/wall-e/coding/acceptance-contract.js +170 -0
  250. package/template/wall-e/coding/acp-adapter.js +1 -1
  251. package/template/wall-e/coding/agent-catalog.js +3 -0
  252. package/template/wall-e/coding/artifact-store.js +93 -0
  253. package/template/wall-e/coding/capability-router.js +120 -0
  254. package/template/wall-e/coding/coding-run-controller.js +423 -0
  255. package/template/wall-e/coding/compaction-service.js +157 -12
  256. package/template/wall-e/coding/frontend-verification.js +258 -0
  257. package/template/wall-e/coding/lifecycle-hooks.js +75 -0
  258. package/template/wall-e/coding/local-preview-contract.js +157 -0
  259. package/template/wall-e/coding/permission-service.js +57 -13
  260. package/template/wall-e/coding/prompt-bundle.js +19 -1
  261. package/template/wall-e/coding/prompt-section-registry.js +227 -0
  262. package/template/wall-e/coding/provider-compat.js +15 -0
  263. package/template/wall-e/coding/runtime-events.js +224 -0
  264. package/template/wall-e/coding/runtime-mode.js +3 -0
  265. package/template/wall-e/coding/side-git-snapshot.js +160 -4
  266. package/template/wall-e/coding/snapshot-service.js +143 -1
  267. package/template/wall-e/coding/stream-processor.js +388 -34
  268. package/template/wall-e/coding/task-tool.js +141 -4
  269. package/template/wall-e/coding/tool-execution-controller.js +365 -0
  270. package/template/wall-e/coding/tool-registry.js +43 -5
  271. package/template/wall-e/coding/user-hooks.js +217 -0
  272. package/template/wall-e/coding-orchestrator.js +1224 -209
  273. package/template/wall-e/coding-prompts.js +20 -4
  274. package/template/wall-e/context/context-builder.js +15 -2
  275. package/template/wall-e/decision/confidence.js +1 -1
  276. package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
  277. package/template/wall-e/docs/external-action-controller.md +26 -6
  278. package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
  279. package/template/wall-e/embeddings.js +591 -53
  280. package/template/wall-e/external-action-controller.js +12 -0
  281. package/template/wall-e/http/auth.js +1 -0
  282. package/template/wall-e/http/chat-api.js +46 -11
  283. package/template/wall-e/http/model-admin.js +727 -56
  284. package/template/wall-e/lib/boot-profile.js +88 -0
  285. package/template/wall-e/lib/event-loop-monitor.js +93 -0
  286. package/template/wall-e/llm/anthropic.js +123 -5
  287. package/template/wall-e/llm/client.js +236 -67
  288. package/template/wall-e/llm/default-fallback.js +382 -0
  289. package/template/wall-e/llm/health.js +19 -0
  290. package/template/wall-e/llm/message-guard.js +78 -0
  291. package/template/wall-e/llm/model-catalog.js +252 -1
  292. package/template/wall-e/llm/openai.js +10 -3
  293. package/template/wall-e/llm/portkey-sync.js +489 -36
  294. package/template/wall-e/llm/provider-error.js +30 -2
  295. package/template/wall-e/llm/registry.js +5 -1
  296. package/template/wall-e/llm/request-compat.js +67 -0
  297. package/template/wall-e/loops/backfill.js +79 -23
  298. package/template/wall-e/loops/brain-optimize.js +67 -0
  299. package/template/wall-e/loops/ingest.js +25 -10
  300. package/template/wall-e/loops/question-digest.js +160 -0
  301. package/template/wall-e/loops/reflect.js +6 -4
  302. package/template/wall-e/loops/think.js +39 -12
  303. package/template/wall-e/mcp-server.js +318 -36
  304. package/template/wall-e/memory/ctm-context-client.js +52 -14
  305. package/template/wall-e/memory/ctm-operational-context.js +237 -0
  306. package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
  307. package/template/wall-e/memory/ctm-session-context.js +111 -63
  308. package/template/wall-e/prompts/coding/deepseek.txt +3 -0
  309. package/template/wall-e/prompts/coding/gemini.txt +6 -0
  310. package/template/wall-e/prompts/coding/gpt.txt +6 -0
  311. package/template/wall-e/prompts/coding/local.txt +7 -0
  312. package/template/wall-e/runtime/decision-hooks.js +115 -0
  313. package/template/wall-e/runtime/devbox-gateway.js +82 -8
  314. package/template/wall-e/runtime/prompt-manifest.js +86 -0
  315. package/template/wall-e/runtime/tool-executor.js +269 -0
  316. package/template/wall-e/runtime/tool-result-envelope.js +138 -0
  317. package/template/wall-e/runtime/transcript-projection.js +60 -0
  318. package/template/wall-e/runtime/walle-runtime.js +224 -0
  319. package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
  320. package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
  321. package/template/wall-e/server.js +2 -0
  322. package/template/wall-e/session-files.js +9 -0
  323. package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
  324. package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
  325. package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
  326. package/template/wall-e/skills/claude-code-reader.js +7 -3
  327. package/template/wall-e/skills/script-skill-runner.js +10 -0
  328. package/template/wall-e/skills/skill-planner.js +38 -0
  329. package/template/wall-e/tools/builtin-middleware.js +19 -9
  330. package/template/wall-e/tools/local-tools.js +1428 -16
  331. package/template/wall-e/tools/permission-checker.js +73 -5
  332. package/template/wall-e/tools/question-manager.js +117 -7
  333. package/template/wall-e/training/harvester.js +12 -28
  334. package/template/wall-e/training/replay.js +25 -80
  335. package/template/wall-e/eval/ab-test.js +0 -203
  336. package/template/wall-e/eval/agent-runner.js +0 -772
  337. package/template/wall-e/eval/agent-scorer.js +0 -461
  338. package/template/wall-e/eval/aggregator.js +0 -414
  339. package/template/wall-e/eval/allowed-test-commands.js +0 -34
  340. package/template/wall-e/eval/benchmark-generator.js +0 -113
  341. package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
  342. package/template/wall-e/eval/benchmarks/chat.json +0 -82
  343. package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
  344. package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
  345. package/template/wall-e/eval/benchmarks/coding.json +0 -122
  346. package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
  347. package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
  348. package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
  349. package/template/wall-e/eval/benchmarks.js +0 -669
  350. package/template/wall-e/eval/cc-replay.js +0 -719
  351. package/template/wall-e/eval/chat-eval.js +0 -525
  352. package/template/wall-e/eval/check-keys.js +0 -15
  353. package/template/wall-e/eval/check-providers.js +0 -42
  354. package/template/wall-e/eval/codex-cli-baseline.js +0 -669
  355. package/template/wall-e/eval/coding-agent-real.js +0 -570
  356. package/template/wall-e/eval/context-compactor.js +0 -251
  357. package/template/wall-e/eval/debug-agent003.js +0 -68
  358. package/template/wall-e/eval/diagnostics.js +0 -216
  359. package/template/wall-e/eval/eval-orchestrator.js +0 -642
  360. package/template/wall-e/eval/evaluate.js +0 -202
  361. package/template/wall-e/eval/evaluator.js +0 -373
  362. package/template/wall-e/eval/exporter.js +0 -212
  363. package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
  364. package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
  365. package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
  366. package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
  367. package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
  368. package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
  369. package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
  370. package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
  371. package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
  372. package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
  373. package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
  374. package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
  375. package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
  376. package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
  377. package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
  378. package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
  379. package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
  380. package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
  381. package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
  382. package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
  383. package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
  384. package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
  385. package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
  386. package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
  387. package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
  388. package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
  389. package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
  390. package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
  391. package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
  392. package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
  393. package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
  394. package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
  395. package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
  396. package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
  397. package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
  398. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
  399. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
  400. package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
  401. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
  402. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
  403. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
  404. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
  405. package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
  406. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
  407. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
  408. package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
  409. package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
  410. package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
  411. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
  412. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
  413. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
  414. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
  415. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
  416. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
  417. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
  418. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
  419. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
  420. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
  421. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
  422. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
  423. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
  424. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
  425. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
  426. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
  427. package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
  428. package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
  429. package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
  430. package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
  431. package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
  432. package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
  433. package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
  434. package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
  435. package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
  436. package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
  437. package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
  438. package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
  439. package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
  440. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
  441. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
  442. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
  443. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
  444. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
  445. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
  446. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
  447. package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
  448. package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
  449. package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
  450. package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
  451. package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
  452. package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
  453. package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
  454. package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
  455. package/template/wall-e/eval/harvester.js +0 -685
  456. package/template/wall-e/eval/head-to-head.js +0 -388
  457. package/template/wall-e/eval/humaneval-adapter.js +0 -321
  458. package/template/wall-e/eval/list-models.js +0 -31
  459. package/template/wall-e/eval/livecodebench-adapter.js +0 -291
  460. package/template/wall-e/eval/mail-integration.js +0 -443
  461. package/template/wall-e/eval/manifest.js +0 -186
  462. package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
  463. package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
  464. package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
  465. package/template/wall-e/eval/meta-harness/cli.js +0 -86
  466. package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
  467. package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
  468. package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
  469. package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
  470. package/template/wall-e/eval/meta-harness/frontier.js +0 -96
  471. package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
  472. package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
  473. package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
  474. package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
  475. package/template/wall-e/eval/meta-harness/reporting.js +0 -58
  476. package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
  477. package/template/wall-e/eval/meta-harness/validation.js +0 -81
  478. package/template/wall-e/eval/promoter.js +0 -228
  479. package/template/wall-e/eval/provider-normalizer.js +0 -33
  480. package/template/wall-e/eval/replay.js +0 -395
  481. package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
  482. package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
  483. package/template/wall-e/eval/run-coding-agent-real.js +0 -187
  484. package/template/wall-e/eval/run-eval.js +0 -435
  485. package/template/wall-e/eval/run-model-comparison.js +0 -142
  486. package/template/wall-e/eval/session-evaluator.js +0 -187
  487. package/template/wall-e/eval/session-miner.js +0 -207
  488. package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
  489. package/template/wall-e/eval/session-transcripts.js +0 -509
  490. package/template/wall-e/eval/shadow.js +0 -161
  491. package/template/wall-e/eval/swebench-adapter.js +0 -345
  492. package/template/wall-e/eval/swebench-docker.js +0 -192
  493. package/template/wall-e/eval/train.py +0 -320
  494. package/template/wall-e/eval/trainer.js +0 -232
  495. package/template/wall-e/eval/weekly-eval-loop.js +0 -241
package/README.md CHANGED
@@ -55,6 +55,28 @@ against the exact Node.js binary Wall-E will use. If you switch Node versions,
55
55
  Wall-E automatically runs the needed `npm rebuild` before starting so CTM does
56
56
  not crash with a `NODE_MODULE_VERSION` mismatch.
57
57
 
58
+ ### Pinning Node (optional — for machines with more than one Node)
59
+
60
+ On a machine with a **single** Node, the auto-rebuild above is all you need.
61
+ But if you have **two or more** Node versions (e.g. a system Node *and* a
62
+ Homebrew Node, or you switch with `nvm`/`fnm`), the daemon and a background skill
63
+ can run under different majors and fight over the one compiled `better-sqlite3`
64
+ binary — each rebuild flips its ABI and the other side crash-loops with
65
+ "MCP never became ready".
66
+
67
+ To stop that, lock CTM + Wall-E to one Node:
68
+
69
+ ```bash
70
+ bash bin/pin-node.sh # pin to your current node version
71
+ bash bin/pin-node.sh 22.12.0 # …or an explicit version
72
+ bash bin/pin-node.sh --unpin # revert to the default (auto-rebuild) behavior
73
+ ```
74
+
75
+ This writes a `.node-version` so the launchers always resolve that exact Node
76
+ and the daemon refuses to start under a different major (with a clear message)
77
+ instead of silently corrupting the native binary. Existing installs adopt it the
78
+ moment you run the command — nothing else changes.
79
+
58
80
  ## Setup
59
81
 
60
82
  On first launch, the browser setup page guides you through:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-walle",
3
- "version": "0.9.22",
3
+ "version": "0.9.23",
4
4
  "description": "CTM + Wall-E \u2014 AI coding dashboard and personal digital twin agent. Multi-agent terminal for Claude Code, Codex, Gemini, Aider, OpenCode, and more, plus prompt editor, task queue, remote phone and tablet access, code/doc review, and an agent that learns from Slack, email & calendar.",
5
5
  "bin": {
6
6
  "create-walle": "bin/create-walle.js"
@@ -19,8 +19,8 @@ kills all active sessions. This applies to ALL operations: curl, fetch, restart,
19
19
 
20
20
  When developing CTM or Wall-E code:
21
21
  1. Use the `/ctm-dev` skill (or run it manually)
22
- 2. Pick a random port pair: `DEV_CTM_PORT=$((4100 + RANDOM % 900))`
23
- 3. Start a dev instance: `DEV_CTM_PORT=$port DEV_WALLE_PORT=$((port+1)) bash bin/dev.sh`
22
+ 2. Start a dev instance: `bash bin/dev.sh --fresh` or `bash bin/dev.sh --refresh`
23
+ 3. Read the printed `Dev CTM:` URL and use that port for all curl/browser tests
24
24
  4. Test ONLY against your dev port, never 3456
25
25
  5. Only restart primary when the user explicitly asks — and ask for confirmation first
26
26
 
package/template/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Juncao Li
3
+ Copyright (c) 2026 Wall-E contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -2,6 +2,12 @@
2
2
  'use strict';
3
3
 
4
4
  const { execFileSync } = require('child_process');
5
+ const {
6
+ CTM_PROCESS_NAME,
7
+ WALLE_PROCESS_NAME,
8
+ legacyProcessTitle,
9
+ processTitle,
10
+ } = require('../claude-task-manager/lib/process-title');
5
11
 
6
12
  const DEFAULT_MAX_AGE_MIN = 24 * 60;
7
13
  const PROTECTED_PORTS = new Set([3456, 3457]);
@@ -107,21 +113,36 @@ function processDetails(pid, lsof = lsofBinary()) {
107
113
 
108
114
  function isProtectedProcess(proc, details = {}) {
109
115
  if (/^(ctm|walle)-primary\b/.test(proc.command)) return true;
116
+ if (proc.command === CTM_PROCESS_NAME || proc.command === WALLE_PROCESS_NAME) return true;
110
117
  return (details.ports || []).some(port => PROTECTED_PORTS.has(Number(port)));
111
118
  }
112
119
 
113
120
  function titleKind(command) {
121
+ const ctmName = CTM_PROCESS_NAME.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
122
+ const walleName = WALLE_PROCESS_NAME.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
114
123
  if (/^ctm-dev-\d+\b/.test(command)) return 'ctm-dev';
124
+ if (new RegExp(`^${ctmName}\\s+dev-\\d+\\b`).test(command)) return 'ctm-dev';
115
125
  if (/^walle-dev-\d+\b/.test(command)) return 'walle-dev';
126
+ if (new RegExp(`^${walleName}\\s+dev-\\d+\\b`).test(command)) return 'walle-dev';
116
127
  if (/^ctm-(?:badge-test|render-test|e2e|test)(?:[-\w]*)?\b/.test(command)) return 'ctm-test';
128
+ if (new RegExp(`^${ctmName}\\s+(?:badge-test|render-test|e2e|test)(?:[-\\w]*)?\\b`).test(command)) return 'ctm-test';
117
129
  if (/^walle-(?:staging|render-test|e2e|test)(?:[-\w]*)?\b/.test(command)) return 'walle-test';
130
+ if (new RegExp(`^${walleName}\\s+(?:staging|render-test|e2e|test)(?:[-\\w]*)?\\b`).test(command)) return 'walle-test';
118
131
  return null;
119
132
  }
120
133
 
121
134
  function commandMatchesExactPort(command, port, wallePort) {
122
135
  if (PROTECTED_PORTS.has(Number(port)) || PROTECTED_PORTS.has(Number(wallePort))) return false;
123
- if (port && (command === `ctm-dev-${port}` || command === `walle-dev-${port}`)) return true;
124
- if (wallePort && command === `walle-dev-${Number(wallePort) - 1}`) return true;
136
+ if (port && (
137
+ command === legacyProcessTitle('ctm', `dev-${port}`)
138
+ || command === processTitle('ctm', `dev-${port}`)
139
+ || command === legacyProcessTitle('walle', `dev-${port}`)
140
+ || command === processTitle('walle', `dev-${port}`)
141
+ )) return true;
142
+ if (wallePort && (
143
+ command === legacyProcessTitle('walle', `dev-${Number(wallePort) - 1}`)
144
+ || command === processTitle('walle', `dev-${Number(wallePort) - 1}`)
145
+ )) return true;
125
146
  return false;
126
147
  }
127
148
 
@@ -235,7 +256,7 @@ function main(argv = process.argv.slice(2)) {
235
256
  console.log([
236
257
  'Usage: node bin/ctm-dev-cleanup.js [--kill] [--stale] [--max-age-min N] [--port N --wall-e-port N] [--json]',
237
258
  '',
238
- 'Dry-runs by default. Never targets ctm-primary/walle-primary or ports 3456/3457.',
259
+ `Dry-runs by default. Never targets ${CTM_PROCESS_NAME}/${WALLE_PROCESS_NAME} or ports 3456/3457.`,
239
260
  ].join('\n'));
240
261
  return 0;
241
262
  }
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+ # launchd entrypoint for the CTM primary.
3
+ #
4
+ # Resolves the pinned Node via bin/node-bin.sh (ignoring ambient PATH, so a
5
+ # `brew upgrade node` or a v26-first shell can't flip the ABI) and exec's the
6
+ # server. `exec` replaces this shell with the node process, so launchd's
7
+ # KeepAlive supervises node directly. Because the runtime is chosen from
8
+ # .node-version, a deliberate Node upgrade is just "edit .node-version" — the
9
+ # LaunchAgent plist never needs to change.
10
+ set -euo pipefail
11
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
12
+ NODE_BIN="$(bash "$ROOT/bin/node-bin.sh")"
13
+ exec "$NODE_BIN" "$ROOT/claude-task-manager/server.js" "$@"
@@ -3,16 +3,129 @@
3
3
  # Primary instance stays untouched. Ctrl+C to stop.
4
4
  #
5
5
  # Usage:
6
- # bash bin/dev.sh # Start dev instance with fresh empty DBs
7
- # bash bin/dev.sh --refresh # Explicitly copy production DBs before starting
8
- # bash bin/dev.sh --fresh # Reset to empty DBs before starting
6
+ # bash bin/dev.sh # Pick ports and start with fresh empty DBs
7
+ # bash bin/dev.sh --refresh # Pick ports and copy production DBs before starting
8
+ # bash bin/dev.sh --fresh # Pick ports and reset to empty DBs before starting
9
+ # bash bin/dev.sh --reuse # Pick ports and reuse existing DBs in WALLE_DEV_DIR
10
+ # bash bin/dev.sh --refresh --no-images # Copy DBs only; skip image assets
11
+ # DEV_CTM_PORT=4456 bash bin/dev.sh # Use an explicit port pair
9
12
 
10
13
  set -e
11
14
  ROOT="$(cd "$(dirname "$0")/.." && pwd)"
12
- DEV_DIR="${WALLE_DEV_DIR:-/tmp/walle-dev}"
13
- DEV_CTM_PORT="${DEV_CTM_PORT:-4000}"
14
- DEV_WALLE_PORT="${DEV_WALLE_PORT:-4001}"
15
+ # Resolve the pinned Node binary (ignores ambient PATH) so a dev instance can
16
+ # never run under a different Node major and rebuild the shared better-sqlite3
17
+ # to a mismatched ABI — which would crash-loop the primary daemon.
18
+ NODE_BIN="$(bash "$ROOT/bin/node-bin.sh")" || { echo "[dev] could not resolve the pinned Node (see bin/node-bin.sh)" >&2; exit 1; }
19
+ MODE="fresh"
20
+ PRINT_CONFIG=0
21
+ COPY_IMAGES=1
22
+ KEEP_DATA_ON_EXIT="${CTM_DEV_KEEP_DATA:-0}"
23
+
24
+ usage() {
25
+ cat <<'EOF'
26
+ Usage: bash bin/dev.sh [--fresh|--refresh|--reuse] [--no-images] [--keep-data] [--print-config]
27
+
28
+ Starts an isolated CTM/Wall-E dev instance on random non-primary ports.
29
+
30
+ Options:
31
+ --fresh Reset dev SQLite DBs before start (default)
32
+ --refresh Snapshot production CTM/Wall-E DBs before start
33
+ --reuse Reuse existing DBs in WALLE_DEV_DIR and keep data on exit
34
+ --no-images With --refresh, skip copying CTM image assets
35
+ --keep-data Do not remove the dev data dir when the launcher exits
36
+ --print-config Print resolved ports/data dir and exit
37
+ EOF
38
+ }
39
+
40
+ while [[ $# -gt 0 ]]; do
41
+ case "$1" in
42
+ --fresh)
43
+ MODE="fresh"
44
+ ;;
45
+ --refresh)
46
+ MODE="refresh"
47
+ ;;
48
+ --reuse|--keep)
49
+ MODE="reuse"
50
+ KEEP_DATA_ON_EXIT=1
51
+ ;;
52
+ --no-images)
53
+ COPY_IMAGES=0
54
+ ;;
55
+ --keep-data)
56
+ KEEP_DATA_ON_EXIT=1
57
+ ;;
58
+ --print-config)
59
+ PRINT_CONFIG=1
60
+ ;;
61
+ --help|-h)
62
+ usage
63
+ exit 0
64
+ ;;
65
+ *)
66
+ echo "[dev] Unknown option: $1" >&2
67
+ usage >&2
68
+ exit 2
69
+ ;;
70
+ esac
71
+ shift
72
+ done
73
+
74
+ is_integer() {
75
+ [[ "$1" =~ ^[0-9]+$ ]]
76
+ }
77
+
78
+ assert_safe_port() {
79
+ local name="$1"
80
+ local port="$2"
81
+ if ! is_integer "$port"; then
82
+ echo "[dev] $name must be an integer port, got: $port" >&2
83
+ exit 1
84
+ fi
85
+ if [[ "$port" == "3456" || "$port" == "3457" ]]; then
86
+ echo "[dev] Refusing to use primary CTM/Wall-E port $port" >&2
87
+ exit 1
88
+ fi
89
+ }
90
+
91
+ port_is_free() {
92
+ local port="$1"
93
+ [[ -z "$(lsof -ti ":$port" -sTCP:LISTEN 2>/dev/null || true)" ]]
94
+ }
95
+
96
+ pick_ctm_port() {
97
+ local attempt candidate
98
+ for attempt in $(seq 1 80); do
99
+ candidate=$((4100 + RANDOM % 898))
100
+ if port_is_free "$candidate" && port_is_free "$((candidate + 1))" && port_is_free "$((candidate + 2))"; then
101
+ echo "$candidate"
102
+ return 0
103
+ fi
104
+ done
105
+ echo "[dev] Could not find a free dev port pair in 4100-4999" >&2
106
+ exit 1
107
+ }
108
+
109
+ if [[ -z "${DEV_CTM_PORT:-}" ]]; then
110
+ DEV_CTM_PORT="$(pick_ctm_port)"
111
+ else
112
+ assert_safe_port "DEV_CTM_PORT" "$DEV_CTM_PORT"
113
+ fi
114
+
115
+ DEV_WALLE_PORT="${DEV_WALLE_PORT:-$((DEV_CTM_PORT + 1))}"
15
116
  DEV_OAUTH_PROXY_PORT="${DEV_OAUTH_PROXY_PORT:-$((DEV_CTM_PORT + 2))}"
117
+ assert_safe_port "DEV_WALLE_PORT" "$DEV_WALLE_PORT"
118
+ assert_safe_port "DEV_OAUTH_PROXY_PORT" "$DEV_OAUTH_PROXY_PORT"
119
+
120
+ DEV_DIR="${WALLE_DEV_DIR:-/tmp/walle-dev-$DEV_CTM_PORT}"
121
+
122
+ if [[ "$PRINT_CONFIG" == "1" ]]; then
123
+ echo "DEV_CTM_PORT=$DEV_CTM_PORT"
124
+ echo "DEV_WALLE_PORT=$DEV_WALLE_PORT"
125
+ echo "DEV_OAUTH_PROXY_PORT=$DEV_OAUTH_PROXY_PORT"
126
+ echo "WALLE_DEV_DIR=$DEV_DIR"
127
+ exit 0
128
+ fi
16
129
 
17
130
  # Source production .env to find DB paths. DEV_SOURCE_* lets worktrees without
18
131
  # their own .env refresh from the primary repo's configured data directory.
@@ -31,47 +144,55 @@ cleanup_processes() {
31
144
  if [[ "${1:-}" == "--stale" ]]; then
32
145
  stale_args=(--stale --max-age-min "${CTM_DEV_STALE_MAX_MIN:-1440}")
33
146
  fi
34
- node "$ROOT/bin/ctm-dev-cleanup.js" \
147
+ "$NODE_BIN" "$ROOT/bin/ctm-dev-cleanup.js" \
35
148
  --kill \
36
149
  --port "$DEV_CTM_PORT" \
37
150
  --wall-e-port "$DEV_WALLE_PORT" \
38
151
  "${stale_args[@]}" >/dev/null 2>&1 || true
39
152
  pkill -f "ctm-dev-$DEV_CTM_PORT" 2>/dev/null || true
153
+ pkill -f "Coding Task Manager dev-$DEV_CTM_PORT" 2>/dev/null || true
40
154
  pkill -f "walle-dev-$DEV_CTM_PORT" 2>/dev/null || true
155
+ pkill -f "Wall-E dev-$DEV_CTM_PORT" 2>/dev/null || true
41
156
  lsof -ti ":$DEV_CTM_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
42
157
  lsof -ti ":$DEV_WALLE_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
43
158
  lsof -ti ":$DEV_OAUTH_PROXY_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
44
159
  }
45
160
 
46
161
  cleanup_dev() {
47
- node "$ROOT/bin/ctm-dev-cleanup.js" \
162
+ "$NODE_BIN" "$ROOT/bin/ctm-dev-cleanup.js" \
48
163
  --kill \
49
164
  --port "$DEV_CTM_PORT" \
50
165
  --wall-e-port "$DEV_WALLE_PORT" >/dev/null 2>&1 || true
51
166
  cleanup_processes
52
167
  # Remove dev data directory to prevent /tmp bloat (each copy is ~2-6 GB)
53
- if [[ "$DEV_DIR" == /tmp/walle-* && -d "$DEV_DIR" ]]; then
168
+ if [[ "$KEEP_DATA_ON_EXIT" != "1" && "$DEV_DIR" == /tmp/walle-* && -d "$DEV_DIR" ]]; then
54
169
  echo "[dev] Cleaning up $DEV_DIR ..."
55
170
  rm -rf "$DEV_DIR"
171
+ elif [[ "$KEEP_DATA_ON_EXIT" == "1" && -d "$DEV_DIR" ]]; then
172
+ echo "[dev] Keeping dev data $DEV_DIR"
56
173
  fi
57
174
  }
58
175
 
59
176
  cleanup_processes --stale
60
177
 
61
- # Handle flags
62
- if [[ "$1" == "--fresh" || -z "$1" ]]; then
178
+ # Handle launch mode
179
+ if [[ "$MODE" == "fresh" ]]; then
63
180
  echo "[dev] Starting with fresh (empty) databases"
64
181
  rm -f "$DEV_DIR"/*.db "$DEV_DIR"/*.db-wal "$DEV_DIR"/*.db-shm
65
- elif [[ "$1" == "--refresh" ]]; then
182
+ elif [[ "$MODE" == "refresh" ]]; then
66
183
  echo "[dev] Snapshotting production databases to $DEV_DIR ..."
67
- node "$ROOT/bin/sqlite-snapshot.js" "$PROD_CTM_DIR/task-manager.db" "$DEV_DIR/task-manager.db" "CTM"
68
- node "$ROOT/bin/sqlite-snapshot.js" "$PROD_WALLE_DIR/wall-e-brain.db" "$DEV_DIR/wall-e-brain.db" "Brain"
69
- if [[ -d "$PROD_CTM_DIR/images" ]]; then
184
+ "$NODE_BIN" "$ROOT/bin/sqlite-snapshot.js" "$PROD_CTM_DIR/task-manager.db" "$DEV_DIR/task-manager.db" "CTM"
185
+ "$NODE_BIN" "$ROOT/bin/sqlite-snapshot.js" "$PROD_WALLE_DIR/wall-e-brain.db" "$DEV_DIR/wall-e-brain.db" "Brain"
186
+ if [[ "$COPY_IMAGES" == "1" && -d "$PROD_CTM_DIR/images" ]]; then
70
187
  echo " Images: syncing $PROD_CTM_DIR/images -> $DEV_DIR/images"
71
- node "$ROOT/bin/sync-images.js" "$PROD_CTM_DIR/images" "$DEV_DIR/images"
188
+ "$NODE_BIN" "$ROOT/bin/sync-images.js" "$PROD_CTM_DIR/images" "$DEV_DIR/images"
189
+ elif [[ "$COPY_IMAGES" != "1" ]]; then
190
+ echo " Images: skipped (--no-images)"
72
191
  fi
73
192
  # Ensure the dev instance owns its WAL files from first open.
74
193
  rm -f "$DEV_DIR"/*.db-wal "$DEV_DIR"/*.db-shm
194
+ elif [[ "$MODE" == "reuse" ]]; then
195
+ echo "[dev] Reusing existing databases in $DEV_DIR"
75
196
  fi
76
197
 
77
198
  echo ""
@@ -127,6 +248,16 @@ export CTM_SESSION_MEMORY_API_BASE_URL="http://127.0.0.1:$DEV_CTM_PORT"
127
248
  export WALLE_MCP_AUTO_CONFIG="${WALLE_MCP_AUTO_CONFIG:-0}"
128
249
  export CTM_SKIP_DOTENV="1"
129
250
 
251
+ CTM_DEV_CHILD_PID=""
252
+ forward_signal() {
253
+ local signal="$1"
254
+ if [[ -n "$CTM_DEV_CHILD_PID" ]]; then
255
+ kill -"$signal" "$CTM_DEV_CHILD_PID" 2>/dev/null || true
256
+ fi
257
+ }
258
+
259
+ trap 'forward_signal INT' INT
260
+ trap 'forward_signal TERM' TERM
130
261
  trap cleanup_dev EXIT
131
262
 
132
263
  # Clean up stale dev/e2e data dirs older than 24h (from crashed sessions)
@@ -134,6 +265,13 @@ find /tmp -maxdepth 1 -name "walle-dev-*" -type d -mmin +1440 -exec rm -rf {} +
134
265
  find /tmp -maxdepth 1 -name "walle-e2e-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
135
266
  find /tmp -maxdepth 1 -name "ctm-dev-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
136
267
 
137
- # Run in foreground so Ctrl+C stops it cleanly
268
+ # Run in foreground so Ctrl+C stops it cleanly while keeping the shell trap alive.
138
269
  cd "$ROOT"
139
- exec node claude-task-manager/server.js
270
+ "$NODE_BIN" claude-task-manager/server.js &
271
+ CTM_DEV_CHILD_PID="$!"
272
+ set +e
273
+ wait "$CTM_DEV_CHILD_PID"
274
+ status="$?"
275
+ set -e
276
+ CTM_DEV_CHILD_PID=""
277
+ exit "$status"
@@ -0,0 +1,84 @@
1
+ #!/bin/bash
2
+ # Resolve the canonical pinned Node binary for CTM + Wall-E and print its
3
+ # ABSOLUTE, immutable path on stdout. Exits non-zero (diagnostic on stderr) when
4
+ # the pinned version cannot be located.
5
+ #
6
+ # The pin lives in <repo-root>/.node-version (single source of truth). This
7
+ # resolver deliberately IGNORES ambient PATH so a Homebrew upgrade that repoints
8
+ # /opt/homebrew/bin/node, or a v26-first shell, can never select the wrong ABI
9
+ # for the shared native modules (better-sqlite3, sqlite-vec, tree-sitter).
10
+ #
11
+ # In a non-owner / shipped create-walle install the pin file is absent, so this
12
+ # degrades to the PATH `node` and never constrains other users.
13
+ set -euo pipefail
14
+
15
+ find_repo_root() {
16
+ local dir="$1"
17
+ while [[ "$dir" != "/" ]]; do
18
+ if [[ -f "$dir/.node-version" && -d "$dir/wall-e" && -d "$dir/claude-task-manager" ]]; then
19
+ printf '%s\n' "$dir"
20
+ return 0
21
+ fi
22
+ dir="$(dirname "$dir")"
23
+ done
24
+ return 1
25
+ }
26
+
27
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
28
+ ROOT="$(find_repo_root "$SCRIPT_DIR" || true)"
29
+
30
+ if [[ -z "${ROOT:-}" ]]; then
31
+ # No pin (non-owner / shipped context): fall back to PATH node.
32
+ if command -v node >/dev/null 2>&1; then
33
+ command -v node
34
+ exit 0
35
+ fi
36
+ echo "[node-bin] no .node-version pin found and no node on PATH" >&2
37
+ exit 1
38
+ fi
39
+
40
+ PIN="$(tr -d 'v[:space:]' < "$ROOT/.node-version")"
41
+ if [[ -z "$PIN" ]]; then
42
+ echo "[node-bin] empty .node-version pin at $ROOT" >&2
43
+ exit 1
44
+ fi
45
+
46
+ candidates=(
47
+ "/opt/homebrew/Cellar/node/$PIN/bin/node"
48
+ "/usr/local/Cellar/node/$PIN/bin/node"
49
+ "$HOME/.fnm/node-versions/v$PIN/installation/bin/node"
50
+ "$HOME/.local/share/fnm/node-versions/v$PIN/installation/bin/node"
51
+ "$HOME/.nvm/versions/node/v$PIN/bin/node"
52
+ )
53
+
54
+ for c in "${candidates[@]}"; do
55
+ if [[ -x "$c" ]]; then
56
+ got="$("$c" --version 2>/dev/null | tr -d 'v[:space:]')"
57
+ if [[ "$got" == "$PIN" ]]; then
58
+ printf '%s\n' "$c"
59
+ exit 0
60
+ fi
61
+ fi
62
+ done
63
+
64
+ # Last resort: the ambient `node` IF it already equals the pin. Covers system
65
+ # installs (nodejs.org pkg, distro packages) where node lives outside Cellar/
66
+ # fnm/nvm. We still gate on an exact version match, so this never selects a
67
+ # mismatched ABI — it just avoids a false "not found" for non-manager installs.
68
+ if command -v node >/dev/null 2>&1; then
69
+ got="$(node --version 2>/dev/null | tr -d 'v[:space:]')"
70
+ if [[ "$got" == "$PIN" ]]; then
71
+ command -v node
72
+ exit 0
73
+ fi
74
+ fi
75
+
76
+ {
77
+ echo "[node-bin] Pinned Node v$PIN not found. CTM + Wall-E require it so the"
78
+ echo " shared native modules (better-sqlite3, sqlite-vec, tree-sitter) keep a"
79
+ echo " stable ABI. Install it, e.g.:"
80
+ echo " brew install node@${PIN%%.*} # or: fnm install $PIN / nvm install $PIN"
81
+ echo " Looked in:"
82
+ printf ' %s\n' "${candidates[@]}"
83
+ } >&2
84
+ exit 1
@@ -0,0 +1,51 @@
1
+ #!/bin/bash
2
+ # Opt into the CTM + Wall-E Node version pin.
3
+ #
4
+ # Writes <repo-root>/.node-version (and .nvmrc) so the runtime guard + launchers
5
+ # lock onto ONE Node — eliminating the better-sqlite3 ABI ping-pong that happens
6
+ # on machines with more than one Node (e.g. system + Homebrew, or nvm/fnm
7
+ # switching). Pins to the CURRENTLY-RUNNING node by default, which is by
8
+ # definition the version your install already works under.
9
+ #
10
+ # This is OPTIONAL and OFF by default for npx/create-walle installs: a
11
+ # single-Node machine never hits the ABI flip, so most users never need it.
12
+ #
13
+ # Usage:
14
+ # bash bin/pin-node.sh # pin to the current `node` version
15
+ # bash bin/pin-node.sh 22.12.0 # pin to an explicit version
16
+ # bash bin/pin-node.sh --unpin # remove the pin (back to permissive)
17
+ set -euo pipefail
18
+
19
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
20
+ if [[ ! -d "$ROOT/wall-e" || ! -d "$ROOT/claude-task-manager" ]]; then
21
+ echo "[pin-node] $ROOT does not look like a CTM + Wall-E checkout (missing wall-e/ or claude-task-manager/)." >&2
22
+ exit 1
23
+ fi
24
+
25
+ if [[ "${1:-}" == "--unpin" ]]; then
26
+ rm -f "$ROOT/.node-version" "$ROOT/.nvmrc"
27
+ echo "[pin-node] Removed .node-version / .nvmrc — Node version is now unpinned (guard is a no-op)."
28
+ exit 0
29
+ fi
30
+
31
+ VERSION="${1:-}"
32
+ if [[ -z "$VERSION" ]]; then
33
+ if ! command -v node >/dev/null 2>&1; then
34
+ echo "[pin-node] No node on PATH and no version given. Pass one: bash bin/pin-node.sh 22.12.0" >&2
35
+ exit 1
36
+ fi
37
+ VERSION="$(node --version | tr -d 'v[:space:]')"
38
+ fi
39
+
40
+ # Sanity: a bare semver-ish string.
41
+ if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
42
+ echo "[pin-node] '$VERSION' is not a valid Node version (expected e.g. 22.12.0)." >&2
43
+ exit 1
44
+ fi
45
+
46
+ printf '%s\n' "$VERSION" > "$ROOT/.node-version"
47
+ printf '%s\n' "$VERSION" > "$ROOT/.nvmrc"
48
+ echo "[pin-node] Pinned CTM + Wall-E to Node v$VERSION (.node-version + .nvmrc at $ROOT)."
49
+ echo "[pin-node] The boot guard now hard-fails any launch under a different Node major,"
50
+ echo "[pin-node] and bin/node-bin.sh resolves this version for the launchers."
51
+ echo "[pin-node] Undo with: bash bin/pin-node.sh --unpin"