create-walle 0.9.9 → 0.9.11

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 (530) hide show
  1. package/README.md +1 -1
  2. package/bin/create-walle.js +63 -12
  3. package/package.json +1 -1
  4. package/template/CLAUDE.md +19 -0
  5. package/template/bin/dev.sh +46 -23
  6. package/template/bin/install-service.sh +50 -16
  7. package/template/bin/sqlite-snapshot.js +148 -0
  8. package/template/claude-task-manager/api-prompts.js +1057 -220
  9. package/template/claude-task-manager/api-reviews.js +12 -0
  10. package/template/claude-task-manager/approval-agent.js +406 -82
  11. package/template/claude-task-manager/bin/capture-pty.js +92 -0
  12. package/template/claude-task-manager/bin/claude-hook.js +42 -0
  13. package/template/claude-task-manager/bin/codex-notify.js +44 -0
  14. package/template/claude-task-manager/bin/ctm-hotkey.swift +118 -0
  15. package/template/claude-task-manager/bin/extract-fixture.js +142 -0
  16. package/template/claude-task-manager/bin/gemini-hook.js +41 -0
  17. package/template/claude-task-manager/bin/install-hotkey.sh +120 -0
  18. package/template/claude-task-manager/bin/restart-ctm.sh +25 -6
  19. package/template/claude-task-manager/db.js +1681 -130
  20. package/template/claude-task-manager/docs/session-management-architecture.md +554 -0
  21. package/template/claude-task-manager/fuzzy-utils.js +455 -0
  22. package/template/claude-task-manager/git-utils.js +680 -31
  23. package/template/claude-task-manager/lib/agent-capabilities.js +108 -0
  24. package/template/claude-task-manager/lib/agent-cli-cache.js +224 -0
  25. package/template/claude-task-manager/lib/agent-hooks-installer.js +416 -0
  26. package/template/claude-task-manager/lib/agent-presets.js +129 -0
  27. package/template/claude-task-manager/lib/auto-approval-verifier.js +199 -0
  28. package/template/claude-task-manager/lib/coding-agent-models.js +219 -0
  29. package/template/claude-task-manager/lib/compact-stitch.js +140 -0
  30. package/template/claude-task-manager/lib/devcontainer-wrapper.js +93 -0
  31. package/template/claude-task-manager/lib/fs-watcher.js +305 -0
  32. package/template/claude-task-manager/lib/git-status.js +130 -0
  33. package/template/claude-task-manager/lib/hook-executor.js +111 -0
  34. package/template/claude-task-manager/lib/launch-presets.js +103 -0
  35. package/template/claude-task-manager/lib/message-export.js +146 -0
  36. package/template/claude-task-manager/lib/message-pagination.js +47 -0
  37. package/template/claude-task-manager/lib/oauth-proxy-supervisor.js +133 -0
  38. package/template/claude-task-manager/lib/perf-tracker.js +58 -0
  39. package/template/claude-task-manager/lib/permission-sync.js +162 -0
  40. package/template/claude-task-manager/lib/project-config.js +122 -0
  41. package/template/claude-task-manager/lib/relink-audit.js +234 -0
  42. package/template/claude-task-manager/lib/sanitize-anthropic-auth.js +46 -0
  43. package/template/claude-task-manager/lib/scheduler.js +408 -0
  44. package/template/claude-task-manager/lib/server-config.js +73 -0
  45. package/template/claude-task-manager/lib/session-history.js +434 -0
  46. package/template/claude-task-manager/lib/session-jobs.js +582 -0
  47. package/template/claude-task-manager/lib/session-lineage.js +291 -0
  48. package/template/claude-task-manager/lib/session-state-bus.js +143 -0
  49. package/template/claude-task-manager/lib/session-stream.js +1189 -0
  50. package/template/claude-task-manager/lib/session-verify.js +215 -0
  51. package/template/claude-task-manager/lib/status-hooks-config.js +101 -0
  52. package/template/claude-task-manager/lib/status-hooks.js +101 -0
  53. package/template/claude-task-manager/lib/telemetry-receiver.js +403 -0
  54. package/template/claude-task-manager/lib/walle-client.js +176 -0
  55. package/template/claude-task-manager/lib/walle-supervisor.js +343 -0
  56. package/template/claude-task-manager/oauth-proxy.js +236 -0
  57. package/template/claude-task-manager/package.json +12 -2
  58. package/template/claude-task-manager/prompt-harvest.js +515 -48
  59. package/template/claude-task-manager/providers/aider.js +63 -0
  60. package/template/claude-task-manager/providers/amazon-q.js +56 -0
  61. package/template/claude-task-manager/providers/claude-code.js +115 -0
  62. package/template/claude-task-manager/providers/cline.js +52 -0
  63. package/template/claude-task-manager/providers/codex.js +186 -0
  64. package/template/claude-task-manager/providers/copilot.js +51 -0
  65. package/template/claude-task-manager/providers/cursor.js +67 -0
  66. package/template/claude-task-manager/providers/gemini.js +58 -0
  67. package/template/claude-task-manager/providers/index.js +65 -0
  68. package/template/claude-task-manager/providers/kimi.js +57 -0
  69. package/template/claude-task-manager/providers/opencode.js +61 -0
  70. package/template/claude-task-manager/public/css/listening.css +1481 -0
  71. package/template/claude-task-manager/public/css/prompts.css +143 -19
  72. package/template/claude-task-manager/public/css/reviews.css +212 -1
  73. package/template/claude-task-manager/public/css/setup.css +25 -0
  74. package/template/claude-task-manager/public/css/walle-session.css +175 -0
  75. package/template/claude-task-manager/public/css/walle.css +43 -2
  76. package/template/claude-task-manager/public/index.html +6928 -1568
  77. package/template/claude-task-manager/public/js/listening.js +1740 -0
  78. package/template/claude-task-manager/public/js/message-renderer.js +780 -0
  79. package/template/claude-task-manager/public/js/prompts.js +1451 -565
  80. package/template/claude-task-manager/public/js/reviewchat.js +498 -0
  81. package/template/claude-task-manager/public/js/reviews.js +152 -11
  82. package/template/claude-task-manager/public/js/session-activity-utils.js +111 -0
  83. package/template/claude-task-manager/public/js/session-search-utils.js +114 -0
  84. package/template/claude-task-manager/public/js/setup.js +1398 -28
  85. package/template/claude-task-manager/public/js/stream-view.js +1066 -0
  86. package/template/claude-task-manager/public/js/walle-core.js +177 -0
  87. package/template/claude-task-manager/public/js/walle-mcp.js +144 -0
  88. package/template/claude-task-manager/public/js/walle-session.js +428 -71
  89. package/template/claude-task-manager/public/js/walle.js +2454 -386
  90. package/template/claude-task-manager/public/prompts.html +679 -307
  91. package/template/claude-task-manager/public/setup.html +13 -1048
  92. package/template/claude-task-manager/public/sr-diagnostic.html +314 -0
  93. package/template/claude-task-manager/queue-engine.js +14 -0
  94. package/template/claude-task-manager/scripts/audit-relink.js +109 -0
  95. package/template/claude-task-manager/scripts/audit-sessions-db.js +294 -0
  96. package/template/claude-task-manager/scripts/repair-crosslinks.js +221 -0
  97. package/template/claude-task-manager/server.js +6095 -2131
  98. package/template/claude-task-manager/session-integrity.js +706 -0
  99. package/template/claude-task-manager/session-utils.js +66 -2
  100. package/template/claude-task-manager/workers/approval-blocklist.js +138 -0
  101. package/template/claude-task-manager/workers/approval-patterns.js +20 -0
  102. package/template/claude-task-manager/workers/approval-widget-validator.js +176 -0
  103. package/template/claude-task-manager/workers/conversation-import-worker.js +35 -0
  104. package/template/claude-task-manager/workers/headless-term-worker.js +444 -0
  105. package/template/claude-task-manager/workers/scrollback-worker.js +22 -6
  106. package/template/claude-task-manager/workers/session-integrity-worker.js +40 -0
  107. package/template/claude-task-manager/workers/state-detectors/base.js +54 -0
  108. package/template/claude-task-manager/workers/state-detectors/claude-code.js +39 -0
  109. package/template/claude-task-manager/workers/state-detectors/codex.js +62 -0
  110. package/template/claude-task-manager/workers/state-detectors/gemini.js +36 -0
  111. package/template/claude-task-manager/workers/state-detectors/index.js +46 -0
  112. package/template/claude-task-manager/workers/terminal-counters.js +75 -0
  113. package/template/docs/designs/2026-04-18-dictation-focus-redesign.md +358 -0
  114. package/template/package.json +4 -2
  115. package/template/wall-e/_workspace-templates/AGENTS.md +52 -0
  116. package/template/wall-e/_workspace-templates/BOOT.md +34 -0
  117. package/template/wall-e/_workspace-templates/HEARTBEAT.md +42 -0
  118. package/template/wall-e/_workspace-templates/IDENTITY.md +27 -0
  119. package/template/wall-e/_workspace-templates/SOUL.md +53 -0
  120. package/template/wall-e/_workspace-templates/TOOLS.md +34 -0
  121. package/template/wall-e/_workspace-templates/USER.md +37 -0
  122. package/template/wall-e/adapters/chatgpt.js +120 -0
  123. package/template/wall-e/adapters/chatgpt.plugin.json +17 -0
  124. package/template/wall-e/adapters/claude-web.js +75 -0
  125. package/template/wall-e/adapters/claude-web.plugin.json +17 -0
  126. package/template/wall-e/adapters/ctm.plugin.json +19 -0
  127. package/template/wall-e/adapters/plaintext.js +80 -0
  128. package/template/wall-e/adapters/plaintext.plugin.json +17 -0
  129. package/template/wall-e/adapters/registry.js +229 -0
  130. package/template/wall-e/adapters/slack.plugin.json +19 -0
  131. package/template/wall-e/agent-runners/claude-code.js +86 -0
  132. package/template/wall-e/agent-runners/codex.js +116 -0
  133. package/template/wall-e/agent-runners/contract.js +60 -0
  134. package/template/wall-e/agent-runners/gemini.js +96 -0
  135. package/template/wall-e/agent-runners/index.js +62 -0
  136. package/template/wall-e/agent-runners/multi-agent.js +202 -0
  137. package/template/wall-e/agent-runners/utils.js +165 -0
  138. package/template/wall-e/agent.js +407 -69
  139. package/template/wall-e/api-walle.js +1906 -238
  140. package/template/wall-e/auth/cooldown.js +166 -0
  141. package/template/wall-e/auth/key-rotation.js +231 -0
  142. package/template/wall-e/auth/profiles.js +144 -0
  143. package/template/wall-e/brain.js +1518 -122
  144. package/template/wall-e/channels/channel-retry.js +154 -0
  145. package/template/wall-e/channels/idle-poll-backoff.js +141 -0
  146. package/template/wall-e/channels/imessage-channel.plugin.json +21 -0
  147. package/template/wall-e/channels/registry.js +233 -0
  148. package/template/wall-e/channels/slack-channel.plugin.json +20 -0
  149. package/template/wall-e/channels/telegram-channel.plugin.json +20 -0
  150. package/template/wall-e/chat/attachment-storage.js +123 -0
  151. package/template/wall-e/chat/attachments.js +192 -0
  152. package/template/wall-e/chat/capability-resolver.js +92 -0
  153. package/template/wall-e/chat/code-review-context.js +192 -0
  154. package/template/wall-e/chat-fallback.js +174 -0
  155. package/template/wall-e/chat.js +915 -91
  156. package/template/wall-e/coding-context.js +142 -6
  157. package/template/wall-e/coding-orchestrator.js +1369 -224
  158. package/template/wall-e/coding-prompts.js +223 -0
  159. package/template/wall-e/coding-review.js +95 -51
  160. package/template/wall-e/compat.js +113 -0
  161. package/template/wall-e/context/compaction-hooks.js +117 -0
  162. package/template/wall-e/context/compactor.js +12 -0
  163. package/template/wall-e/context/context-builder.js +229 -22
  164. package/template/wall-e/context/query-sanitizer.js +81 -0
  165. package/template/wall-e/context/topic-matcher.js +36 -16
  166. package/template/wall-e/core-tasks.js +15 -3
  167. package/template/wall-e/db/write-audit.js +81 -0
  168. package/template/wall-e/dispatch/collapse-policy.js +91 -0
  169. package/template/wall-e/dispatch/source-registry.js +154 -0
  170. package/template/wall-e/docs/architecture.md +460 -0
  171. package/template/wall-e/embeddings.js +33 -3
  172. package/template/wall-e/eval/ab-test.js +203 -0
  173. package/template/wall-e/eval/agent-runner.js +629 -0
  174. package/template/wall-e/eval/agent-scorer.js +461 -0
  175. package/template/wall-e/eval/aggregator.js +310 -11
  176. package/template/wall-e/eval/benchmark-generator.js +93 -0
  177. package/template/wall-e/eval/benchmarks/chat-eval.json +586 -25
  178. package/template/wall-e/eval/benchmarks/coding-agent-real.json +1 -0
  179. package/template/wall-e/eval/benchmarks/coding-agent.json +2177 -0
  180. package/template/wall-e/eval/benchmarks/swebench-lite-30.json +212 -0
  181. package/template/wall-e/eval/benchmarks.js +119 -5
  182. package/template/wall-e/eval/cc-replay.js +718 -0
  183. package/template/wall-e/eval/chat-eval.js +18 -2
  184. package/template/wall-e/eval/check-keys.js +15 -0
  185. package/template/wall-e/eval/check-providers.js +42 -0
  186. package/template/wall-e/eval/coding-agent-real.js +568 -0
  187. package/template/wall-e/eval/context-compactor.js +251 -0
  188. package/template/wall-e/eval/debug-agent003.js +67 -0
  189. package/template/wall-e/eval/diagnostics.js +216 -0
  190. package/template/wall-e/eval/eval-orchestrator.js +430 -0
  191. package/template/wall-e/eval/fixtures/express-basic/package.json +9 -0
  192. package/template/wall-e/eval/fixtures/express-basic/server.js +115 -0
  193. package/template/wall-e/eval/fixtures/express-basic/test.js +83 -0
  194. package/template/wall-e/eval/fixtures/express-buggy/package.json +9 -0
  195. package/template/wall-e/eval/fixtures/express-buggy/server.js +113 -0
  196. package/template/wall-e/eval/fixtures/express-buggy/test.js +83 -0
  197. package/template/wall-e/eval/fixtures/express-buggy-items/package.json +9 -0
  198. package/template/wall-e/eval/fixtures/express-buggy-items/server.js +112 -0
  199. package/template/wall-e/eval/fixtures/express-buggy-items/test.js +83 -0
  200. package/template/wall-e/eval/fixtures/express-buggy-search/package.json +9 -0
  201. package/template/wall-e/eval/fixtures/express-buggy-search/server.js +121 -0
  202. package/template/wall-e/eval/fixtures/express-buggy-search/test.js +83 -0
  203. package/template/wall-e/eval/fixtures/express-rename-data/data.js +34 -0
  204. package/template/wall-e/eval/fixtures/express-rename-data/package.json +9 -0
  205. package/template/wall-e/eval/fixtures/express-rename-data/server.js +97 -0
  206. package/template/wall-e/eval/fixtures/express-rename-data/test.js +88 -0
  207. package/template/wall-e/eval/fixtures/express-xss/package.json +12 -0
  208. package/template/wall-e/eval/fixtures/express-xss/server.js +90 -0
  209. package/template/wall-e/eval/fixtures/express-xss/test.js +67 -0
  210. package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +9 -0
  211. package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +9 -0
  212. package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +13 -0
  213. package/template/wall-e/eval/fixtures/fullstack-app/package.json +11 -0
  214. package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +137 -0
  215. package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +46 -0
  216. package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +121 -0
  217. package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +71 -0
  218. package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +80 -0
  219. package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +46 -0
  220. package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +45 -0
  221. package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +38 -0
  222. package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +23 -0
  223. package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +46 -0
  224. package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +99 -0
  225. package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +94 -0
  226. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +19 -0
  227. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +19 -0
  228. package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +50 -0
  229. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +69 -0
  230. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +23 -0
  231. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +88 -0
  232. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +75 -0
  233. package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +198 -0
  234. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +34 -0
  235. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +26 -0
  236. package/template/wall-e/eval/fixtures/fullstack-app/server.js +8 -0
  237. package/template/wall-e/eval/fixtures/fullstack-app/test.js +12 -0
  238. package/template/wall-e/eval/fixtures/monorepo-basic/package.json +8 -0
  239. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +58 -0
  240. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +46 -0
  241. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +8 -0
  242. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +64 -0
  243. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +56 -0
  244. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +116 -0
  245. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +61 -0
  246. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +62 -0
  247. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +43 -0
  248. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +11 -0
  249. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +44 -0
  250. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +43 -0
  251. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +12 -0
  252. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +5 -0
  253. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +55 -0
  254. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +29 -0
  255. package/template/wall-e/eval/fixtures/monorepo-basic/test.js +46 -0
  256. package/template/wall-e/eval/fixtures/node-cli/index.js +78 -0
  257. package/template/wall-e/eval/fixtures/node-cli/package.json +10 -0
  258. package/template/wall-e/eval/fixtures/node-cli/test.js +57 -0
  259. package/template/wall-e/eval/fixtures/node-typed/package.json +8 -0
  260. package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +31 -0
  261. package/template/wall-e/eval/fixtures/node-typed/src/utils.js +33 -0
  262. package/template/wall-e/eval/fixtures/node-typed/test.js +36 -0
  263. package/template/wall-e/eval/fixtures/python-flask/app.py +14 -0
  264. package/template/wall-e/eval/fixtures/python-flask/requirements.txt +2 -0
  265. package/template/wall-e/eval/fixtures/python-flask/test_app.py +25 -0
  266. package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +105 -0
  267. package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +101 -0
  268. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +20 -0
  269. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +32 -0
  270. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +64 -0
  271. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +6 -0
  272. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +31 -0
  273. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +18 -0
  274. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +34 -0
  275. package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +104 -0
  276. package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +73 -0
  277. package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +134 -0
  278. package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +99 -0
  279. package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +63 -0
  280. package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +70 -0
  281. package/template/wall-e/eval/fixtures/wall-e-subset/package.json +10 -0
  282. package/template/wall-e/eval/fixtures/wall-e-subset/test.js +86 -0
  283. package/template/wall-e/eval/harvester.js +177 -21
  284. package/template/wall-e/eval/head-to-head.js +38 -11
  285. package/template/wall-e/eval/humaneval-adapter.js +296 -0
  286. package/template/wall-e/eval/list-models.js +31 -0
  287. package/template/wall-e/eval/livecodebench-adapter.js +267 -0
  288. package/template/wall-e/eval/mail-integration.js +443 -0
  289. package/template/wall-e/eval/promoter.js +82 -0
  290. package/template/wall-e/eval/replay.js +14 -0
  291. package/template/wall-e/eval/run-agent-benchmarks.js +314 -0
  292. package/template/wall-e/eval/run-coding-agent-real.js +187 -0
  293. package/template/wall-e/eval/run-eval.js +425 -0
  294. package/template/wall-e/eval/run-model-comparison.js +141 -0
  295. package/template/wall-e/eval/session-evaluator.js +187 -0
  296. package/template/wall-e/eval/session-miner.js +207 -0
  297. package/template/wall-e/eval/session-transcripts.js +456 -0
  298. package/template/wall-e/eval/shadow.js +19 -2
  299. package/template/wall-e/eval/swebench-adapter.js +238 -0
  300. package/template/wall-e/eval/swebench-docker.js +192 -0
  301. package/template/wall-e/eval/weekly-eval-loop.js +241 -0
  302. package/template/wall-e/evaluation/agent-router.js +76 -0
  303. package/template/wall-e/evaluation/coding-quorum.js +325 -0
  304. package/template/wall-e/evaluation/index.js +2 -0
  305. package/template/wall-e/evaluation/learner.js +2 -1
  306. package/template/wall-e/evaluation/phase-detector.js +129 -0
  307. package/template/wall-e/evaluation/quorum-evaluator.js +1 -0
  308. package/template/wall-e/evaluation/quorum.js +3 -0
  309. package/template/wall-e/evaluation/router.js +26 -9
  310. package/template/wall-e/evaluation/scorecard.js +7 -0
  311. package/template/wall-e/evaluation/tier-selector.js +2 -1
  312. package/template/wall-e/extraction/contradiction.js +148 -4
  313. package/template/wall-e/extraction/entity-normalizer.js +488 -0
  314. package/template/wall-e/extraction/exchange-chunker.js +83 -0
  315. package/template/wall-e/extraction/heuristic-extractor.js +184 -0
  316. package/template/wall-e/extraction/i18n/en.json +18 -0
  317. package/template/wall-e/extraction/i18n/zh.json +17 -0
  318. package/template/wall-e/extraction/indexer.js +171 -0
  319. package/template/wall-e/extraction/knowledge-extractor.js +1 -0
  320. package/template/wall-e/extraction/noise-stripper.js +63 -0
  321. package/template/wall-e/fly.toml +1 -0
  322. package/template/wall-e/http/api-utils.js +100 -0
  323. package/template/wall-e/http/auth.js +46 -0
  324. package/template/wall-e/http/chat-api.js +377 -0
  325. package/template/wall-e/http/listening-api.js +441 -0
  326. package/template/wall-e/http/model-admin.js +586 -0
  327. package/template/wall-e/http/scheduler-api.js +49 -0
  328. package/template/wall-e/lib/activity-log.js +99 -0
  329. package/template/wall-e/lib/coalescer.js +46 -0
  330. package/template/wall-e/lib/config-watcher.js +95 -0
  331. package/template/wall-e/lib/recovery-logger.js +226 -0
  332. package/template/wall-e/lib/scheduler-failure-alert.js +127 -0
  333. package/template/wall-e/lib/scheduler.js +393 -22
  334. package/template/wall-e/listening/calendar.js +282 -0
  335. package/template/wall-e/listening/diarize.js +209 -0
  336. package/template/wall-e/listening/engine.js +299 -0
  337. package/template/wall-e/listening/notes.js +293 -0
  338. package/template/wall-e/listening/refine.js +65 -0
  339. package/template/wall-e/listening/storage.js +80 -0
  340. package/template/wall-e/listening/stt.js +251 -0
  341. package/template/wall-e/llm/anthropic.js +139 -18
  342. package/template/wall-e/llm/anthropic.plugin.json +23 -0
  343. package/template/wall-e/llm/claude-cli.js +208 -0
  344. package/template/wall-e/llm/claude-cli.plugin.json +23 -0
  345. package/template/wall-e/llm/client.js +72 -30
  346. package/template/wall-e/llm/codex-cli.js +210 -0
  347. package/template/wall-e/llm/codex-cli.plugin.json +23 -0
  348. package/template/wall-e/llm/deepseek.js +182 -0
  349. package/template/wall-e/llm/deepseek.plugin.json +22 -0
  350. package/template/wall-e/llm/google.js +104 -4
  351. package/template/wall-e/llm/google.plugin.json +22 -0
  352. package/template/wall-e/llm/index.js +1 -0
  353. package/template/wall-e/llm/lmstudio.js +40 -0
  354. package/template/wall-e/llm/lmstudio.plugin.json +23 -0
  355. package/template/wall-e/llm/mlx.plugin.json +24 -0
  356. package/template/wall-e/llm/ollama-setup.js +7 -1
  357. package/template/wall-e/llm/ollama.js +66 -8
  358. package/template/wall-e/llm/ollama.plugin.json +23 -0
  359. package/template/wall-e/llm/openai.js +30 -15
  360. package/template/wall-e/llm/openai.plugin.json +22 -0
  361. package/template/wall-e/llm/provider-detector.js +3 -6
  362. package/template/wall-e/llm/registry.js +248 -0
  363. package/template/wall-e/llm/retry.js +163 -0
  364. package/template/wall-e/llm/tool-adapter.js +50 -3
  365. package/template/wall-e/loops/backfill.js +149 -2
  366. package/template/wall-e/loops/boot.js +124 -0
  367. package/template/wall-e/loops/conversation-composer.js +129 -0
  368. package/template/wall-e/loops/deterministic-ordering.js +140 -0
  369. package/template/wall-e/loops/ingest.js +37 -0
  370. package/template/wall-e/loops/initiative.js +68 -7
  371. package/template/wall-e/loops/loop-directives.js +128 -0
  372. package/template/wall-e/loops/loop-precheck.js +96 -0
  373. package/template/wall-e/loops/loop-prompt-discipline.js +82 -0
  374. package/template/wall-e/loops/reflect.js +38 -4
  375. package/template/wall-e/loops/silent-reply-tokens.js +109 -0
  376. package/template/wall-e/loops/tasks.js +27 -2
  377. package/template/wall-e/loops/think.js +20 -4
  378. package/template/wall-e/loops/workspace-prompts.js +210 -0
  379. package/template/wall-e/mcp-server.js +146 -0
  380. package/template/wall-e/package.json +10 -2
  381. package/template/wall-e/plugins/activation-planner.js +161 -0
  382. package/template/wall-e/plugins/diagnostics.js +138 -0
  383. package/template/wall-e/plugins/manifest-loader.js +215 -0
  384. package/template/wall-e/plugins/manifest-types.js +66 -0
  385. package/template/wall-e/plugins/manifest-validator.js +241 -0
  386. package/template/wall-e/plugins/npm-scanner.js +191 -0
  387. package/template/wall-e/plugins/registry-base.js +81 -0
  388. package/template/wall-e/prompts/tool-workflows.md +51 -0
  389. package/template/wall-e/qa/README.md +59 -0
  390. package/template/wall-e/qa/scenario-format.md +75 -0
  391. package/template/wall-e/qa/scenarios/agents/instruction-followthrough.md +63 -0
  392. package/template/wall-e/qa/scenarios/channels/handoff-context-preservation.md +74 -0
  393. package/template/wall-e/qa/scenarios/character/persona-consistency.md +61 -0
  394. package/template/wall-e/runtime/devbox-gateway.js +38 -0
  395. package/template/wall-e/scripts/eval-embeddings.js +2 -5
  396. package/template/wall-e/scripts/smoke-coding-agent-jsonl.js +254 -0
  397. package/template/wall-e/search/bm25.js +97 -0
  398. package/template/wall-e/server.js +48 -8
  399. package/template/wall-e/skills/_bundled/coding-agent/run.js +42 -33
  400. package/template/wall-e/skills/_bundled/email-sync/mail-search.swift +237 -0
  401. package/template/wall-e/skills/_bundled/email-sync/run.js +81 -27
  402. package/template/wall-e/skills/_bundled/file-ingest/run.js +13 -8
  403. package/template/wall-e/skills/_bundled/glean-team-sync/run.js +1 -2
  404. package/template/wall-e/skills/_bundled/google-calendar/run.js +6 -23
  405. package/template/wall-e/skills/_bundled/gws-workspace/SKILL.md +76 -0
  406. package/template/wall-e/skills/_bundled/gws-workspace/run.js +401 -0
  407. package/template/wall-e/skills/_bundled/gws-workspace/setup.js +574 -0
  408. package/template/wall-e/skills/_bundled/listening/SKILL.md +26 -0
  409. package/template/wall-e/skills/_bundled/listening/run.js +80 -0
  410. package/template/wall-e/skills/_bundled/proactive-alerts/run.js +19 -3
  411. package/template/wall-e/skills/_bundled/slack-mentions/run.js +82 -19
  412. package/template/wall-e/skills/internal-skill-registry.js +229 -0
  413. package/template/wall-e/skills/routing-reason-codes.js +82 -0
  414. package/template/wall-e/skills/sandbox-registry.js +104 -0
  415. package/template/wall-e/skills/skill-dispatch-decision.js +192 -0
  416. package/template/wall-e/skills/skill-executor.js +49 -6
  417. package/template/wall-e/skills/skill-fallback.js +146 -0
  418. package/template/wall-e/skills/skill-harness-registry.js +173 -0
  419. package/template/wall-e/skills/skill-loader.js +151 -220
  420. package/template/wall-e/skills/skill-planner.js +382 -62
  421. package/template/wall-e/skills/skill-snapshot.js +134 -0
  422. package/template/wall-e/skills/skill-validator.js +103 -1
  423. package/template/wall-e/skills/slack-ingest.js +26 -2
  424. package/template/wall-e/skills/trigger-registry.js +120 -0
  425. package/template/wall-e/telemetry.js +17 -1
  426. package/template/wall-e/tools/builtin-middleware.js +167 -0
  427. package/template/wall-e/tools/coding-events.js +68 -0
  428. package/template/wall-e/tools/coding-middleware.js +169 -0
  429. package/template/wall-e/tools/command-registry.js +237 -0
  430. package/template/wall-e/tools/edit-replacers.js +485 -0
  431. package/template/wall-e/tools/env-service.js +148 -0
  432. package/template/wall-e/tools/event-log.js +207 -0
  433. package/template/wall-e/tools/file-tracker.js +72 -0
  434. package/template/wall-e/tools/formatter.js +397 -0
  435. package/template/wall-e/tools/local-tools.js +929 -195
  436. package/template/wall-e/tools/lsp-client.js +701 -0
  437. package/template/wall-e/tools/lsp-language.js +137 -0
  438. package/template/wall-e/tools/lsp-servers.js +869 -0
  439. package/template/wall-e/tools/npm-service.js +180 -0
  440. package/template/wall-e/tools/patch.js +503 -0
  441. package/template/wall-e/tools/permission-checker.js +137 -34
  442. package/template/wall-e/tools/permission-rules.js +476 -0
  443. package/template/wall-e/tools/port-detector.js +81 -0
  444. package/template/wall-e/tools/project-detector.js +290 -0
  445. package/template/wall-e/tools/question-manager.js +213 -0
  446. package/template/wall-e/tools/session-sharing.js +231 -0
  447. package/template/wall-e/tools/shell-analyzer.js +524 -0
  448. package/template/wall-e/tools/slack-mcp.js +1 -0
  449. package/template/wall-e/tools/smart-truncation.js +100 -0
  450. package/template/wall-e/tools/snapshot.js +479 -0
  451. package/template/wall-e/utils/dedup.js +165 -0
  452. package/template/wall-e/utils/exporter.js +163 -0
  453. package/template/wall-e/utils/heartbeat-content.js +78 -0
  454. package/template/wall-e/utils/repair.js +145 -0
  455. package/template/website/index.html +2 -3
  456. package/template/claude-task-manager/workers/vterm-worker.js +0 -179
  457. package/template/wall-e/test/eval/aggregator.test.js +0 -180
  458. package/template/wall-e/test/eval/benchmarks.test.js +0 -373
  459. package/template/wall-e/test/eval/brain-shadow.test.js +0 -359
  460. package/template/wall-e/test/eval/evaluate.test.js +0 -221
  461. package/template/wall-e/test/eval/evaluator.test.js +0 -340
  462. package/template/wall-e/test/eval/exporter.test.js +0 -353
  463. package/template/wall-e/test/eval/harvester.test.js +0 -718
  464. package/template/wall-e/test/eval/head-to-head.test.js +0 -485
  465. package/template/wall-e/test/eval/promoter.test.js +0 -175
  466. package/template/wall-e/test/eval/shadow.test.js +0 -156
  467. package/template/wall-e/test/eval/trainer.test.js +0 -314
  468. package/template/wall-e/test/evaluation/complexity.test.js +0 -101
  469. package/template/wall-e/test/evaluation/learner.test.js +0 -271
  470. package/template/wall-e/test/evaluation/quorum.test.js +0 -372
  471. package/template/wall-e/test/evaluation/router.test.js +0 -269
  472. package/template/wall-e/test/evaluation/scorecard.test.js +0 -185
  473. package/template/wall-e/test/llm/anthropic.test.js +0 -172
  474. package/template/wall-e/test/llm/brain-models.test.js +0 -182
  475. package/template/wall-e/test/llm/client.test.js +0 -200
  476. package/template/wall-e/test/llm/google.test.js +0 -37
  477. package/template/wall-e/test/llm/health.test.js +0 -426
  478. package/template/wall-e/test/llm/integration.test.js +0 -285
  479. package/template/wall-e/test/llm/ollama.test.js +0 -50
  480. package/template/wall-e/test/llm/openai.test.js +0 -48
  481. package/template/wall-e/test/llm/tool-adapter.test.js +0 -297
  482. package/template/wall-e/test/training/aggregator.test.js +0 -180
  483. package/template/wall-e/test/training/brain-shadow.test.js +0 -359
  484. package/template/wall-e/test/training/evaluate.test.js +0 -221
  485. package/template/wall-e/test/training/evaluator.test.js +0 -340
  486. package/template/wall-e/test/training/exporter.test.js +0 -353
  487. package/template/wall-e/test/training/harvester.test.js +0 -718
  488. package/template/wall-e/test/training/promoter.test.js +0 -175
  489. package/template/wall-e/test/training/shadow.test.js +0 -156
  490. package/template/wall-e/test/training/trainer.test.js +0 -314
  491. package/template/wall-e/tests/adapter-base.test.js +0 -20
  492. package/template/wall-e/tests/adapter-ctm.test.js +0 -122
  493. package/template/wall-e/tests/adapter-slack.test.js +0 -98
  494. package/template/wall-e/tests/agent-api.test.js +0 -256
  495. package/template/wall-e/tests/api-walle.test.js +0 -222
  496. package/template/wall-e/tests/backfill.test.js +0 -126
  497. package/template/wall-e/tests/brain.test.js +0 -603
  498. package/template/wall-e/tests/channels.test.js +0 -104
  499. package/template/wall-e/tests/chat.test.js +0 -103
  500. package/template/wall-e/tests/coding-agent-integration.test.js +0 -240
  501. package/template/wall-e/tests/coding-context.test.js +0 -212
  502. package/template/wall-e/tests/coding-orchestrator.test.js +0 -298
  503. package/template/wall-e/tests/coding-review.test.js +0 -141
  504. package/template/wall-e/tests/compactor.test.js +0 -321
  505. package/template/wall-e/tests/confidence.test.js +0 -134
  506. package/template/wall-e/tests/context-builder.test.js +0 -222
  507. package/template/wall-e/tests/contradiction.test.js +0 -217
  508. package/template/wall-e/tests/embeddings.test.js +0 -378
  509. package/template/wall-e/tests/event-bus.test.js +0 -74
  510. package/template/wall-e/tests/ingest.test.js +0 -113
  511. package/template/wall-e/tests/initiative.test.js +0 -354
  512. package/template/wall-e/tests/mcp-client.test.js +0 -71
  513. package/template/wall-e/tests/mcp-inject.test.js +0 -68
  514. package/template/wall-e/tests/mcp-server.test.js +0 -219
  515. package/template/wall-e/tests/ollama-setup.test.js +0 -81
  516. package/template/wall-e/tests/proactive-alerts.test.js +0 -140
  517. package/template/wall-e/tests/provider-availability.test.js +0 -231
  518. package/template/wall-e/tests/provider-detector.test.js +0 -127
  519. package/template/wall-e/tests/quorum-evaluator.test.js +0 -277
  520. package/template/wall-e/tests/reflect.test.js +0 -103
  521. package/template/wall-e/tests/scheduler.test.js +0 -546
  522. package/template/wall-e/tests/scorecard-evolution.test.js +0 -96
  523. package/template/wall-e/tests/self-critique.test.js +0 -162
  524. package/template/wall-e/tests/server.test.js +0 -111
  525. package/template/wall-e/tests/session-persistence.test.js +0 -331
  526. package/template/wall-e/tests/skills.test.js +0 -198
  527. package/template/wall-e/tests/slack-ingest.test.js +0 -103
  528. package/template/wall-e/tests/think.test.js +0 -454
  529. package/template/wall-e/tests/tier-selector.test.js +0 -109
  530. package/template/wall-e/tests/user-signals.test.js +0 -73
package/README.md CHANGED
@@ -23,7 +23,7 @@ An always-on AI agent that learns from your Slack, email, calendar, and coding s
23
23
  - **Second Brain** — Automatically ingests your digital life into a searchable memory store with full-text search, knowledge extraction, and pattern detection
24
24
  - **Proactive Intelligence** — Surfaces time-sensitive items, suggests actions, and delivers morning briefings and weekly reflections without being asked
25
25
  - **Chat with Tools** — Talk to Wall-E in the browser — it can search your memories, look up people, run skills, and call external tools via MCP (Slack, Glean, etc.)
26
- - **17 Bundled Skills** — Morning briefing, weekly reflection, proactive alerts, Slack monitoring, email sync, calendar integration, coding agent, model evaluation, and more
26
+ - **19 Bundled Skills** — Morning briefing, weekly reflection, proactive alerts, Slack monitoring, email sync, calendar integration, coding agent, model training, model pricing sync, and more
27
27
  - **Multi-Model** — Works with Claude, GPT, Gemini, and local models via Ollama with smart routing
28
28
  - **Skill Management GUI** — Search, filter, create, edit, and monitor skills from the browser with rich cards, config forms, execution history, export/import, and pre-flight validation
29
29
  - **Multi-Device** — Share your brain across machines via Dropbox or iCloud
@@ -144,12 +144,14 @@ function install(targetDir) {
144
144
  console.log(` Installing dependencies...\n`);
145
145
  npmInstall(targetDir);
146
146
 
147
+ compileHotkeyDaemon(targetDir);
148
+
147
149
  // .env
148
150
  const envLines = [
149
151
  `# Wall-E configuration — generated ${new Date().toISOString().split('T')[0]}`,
150
152
  `# Finish setup at http://localhost:${port}/setup.html`,
151
153
  '',
152
- `WALLE_OWNER_NAME=${ownerName}`,
154
+ `WALLE_OWNER_NAME="${ownerName.replace(/"/g, '\\"')}"`,
153
155
  '# ANTHROPIC_API_KEY=',
154
156
  '',
155
157
  '# AI Provider: anthropic, openai, google, ollama',
@@ -247,6 +249,8 @@ function update() {
247
249
  console.log(` Installing dependencies...\n`);
248
250
  npmInstall(dir);
249
251
 
252
+ compileHotkeyDaemon(dir);
253
+
250
254
  // 7. Start again
251
255
  console.log(`\n Starting Wall-E...`);
252
256
  startForegroundOrService(dir, port);
@@ -331,9 +335,8 @@ function stopQuiet(dir, port) {
331
335
  while (Date.now() < deadline) {
332
336
  try {
333
337
  execFileSync('curl', ['-s', '--max-time', '1', `http://localhost:${port}/api/services/status`], { encoding: 'utf8', timeout: 2000 });
334
- // Still running — busy-wait briefly
335
- const waitUntil = Date.now() + 500;
336
- while (Date.now() < waitUntil) { /* spin */ }
338
+ // Still running — sleep briefly (avoid CPU spin)
339
+ try { execFileSync('sleep', ['0.5'], { timeout: 2000 }); } catch {}
337
340
  } catch {
338
341
  break; // Port is free
339
342
  }
@@ -370,15 +373,18 @@ function installService(walleDir, port) {
370
373
  fs.mkdirSync(plistDir, { recursive: true });
371
374
  const plistPath = path.join(plistDir, `${LABEL}.plist`);
372
375
 
373
- let envDict = ` <key>PATH</key>\n <string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>\n`;
374
- envDict += ` <key>HOME</key>\n <string>${process.env.HOME}</string>\n`;
376
+ const xmlEsc = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
377
+ const nodeBinDir = path.dirname(nodePath);
378
+ let envDict = ` <key>PATH</key>\n <string>${xmlEsc(nodeBinDir)}:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>\n`;
379
+ envDict += ` <key>HOME</key>\n <string>${xmlEsc(process.env.HOME)}</string>\n`;
375
380
  envDict += ` <key>CTM_PORT</key>\n <string>${port}</string>\n`;
381
+ envDict += ` <key>CTM_MANAGED_BY_LAUNCHD</key>\n <string>1</string>\n`;
376
382
  try {
377
383
  const envFile = fs.readFileSync(path.join(walleDir, '.env'), 'utf8');
378
384
  for (const line of envFile.split('\n')) {
379
385
  const m = line.match(/^\s*([^#=\s]+)\s*=\s*(.+?)\s*$/);
380
386
  if (m && m[1] !== 'CTM_PORT' && m[1] !== 'PATH' && m[1] !== 'HOME') {
381
- envDict += ` <key>${m[1]}</key>\n <string>${m[2]}</string>\n`;
387
+ envDict += ` <key>${xmlEsc(m[1])}</key>\n <string>${xmlEsc(m[2])}</string>\n`;
382
388
  }
383
389
  }
384
390
  } catch {}
@@ -402,11 +408,16 @@ ${envDict} </dict>
402
408
  <key>RunAtLoad</key>
403
409
  <true/>
404
410
  <key>KeepAlive</key>
405
- <true/>
411
+ <dict>
412
+ <key>SuccessfulExit</key>
413
+ <false/>
414
+ </dict>
415
+ <key>ThrottleInterval</key>
416
+ <integer>5</integer>
406
417
  <key>StandardOutPath</key>
407
- <string>${logDir}/walle.log</string>
418
+ <string>${logDir}/ctm.log</string>
408
419
  <key>StandardErrorPath</key>
409
- <string>${logDir}/walle.err</string>
420
+ <string>${logDir}/ctm.err</string>
410
421
  </dict>
411
422
  </plist>`;
412
423
 
@@ -414,10 +425,34 @@ ${envDict} </dict>
414
425
  try { execFileSync('launchctl', ['unload', plistPath], { stdio: 'ignore' }); } catch {}
415
426
  execFileSync('launchctl', ['load', plistPath]);
416
427
  } else {
417
- const child = spawn(process.execPath, ['claude-task-manager/server.js'], {
428
+ // Linux/other: spawn with a restart-on-crash wrapper shell script
429
+ const watchdogScript = path.join(walleDir, 'bin', 'watchdog.sh');
430
+ const watchdogContent = `#!/bin/bash
431
+ # Auto-restart CTM on crash. Clean exit (code 0) stops the watchdog.
432
+ CRASHES=0
433
+ while true; do
434
+ "${process.execPath}" claude-task-manager/server.js >> "${logDir}/ctm.log" 2>> "${logDir}/ctm.err"
435
+ EXIT_CODE=$?
436
+ if [ $EXIT_CODE -eq 0 ]; then
437
+ echo "[watchdog] Clean exit (code 0), stopping." >> "${logDir}/ctm.log"
438
+ break
439
+ fi
440
+ CRASHES=$((CRASHES + 1))
441
+ echo "[watchdog] CTM exited with code $EXIT_CODE (crash #$CRASHES), restarting in 5s..." >> "${logDir}/ctm.log"
442
+ if [ $CRASHES -ge 5 ]; then
443
+ echo "[watchdog] Too many crashes ($CRASHES), giving up." >> "${logDir}/ctm.log"
444
+ break
445
+ fi
446
+ sleep 5
447
+ done
448
+ `;
449
+ fs.mkdirSync(path.join(walleDir, 'bin'), { recursive: true });
450
+ fs.writeFileSync(watchdogScript, watchdogContent, { mode: 0o755 });
451
+
452
+ const child = spawn('bash', [watchdogScript], {
418
453
  cwd: walleDir,
419
454
  detached: true,
420
- stdio: ['ignore', fs.openSync(path.join(logDir, 'walle.log'), 'a'), fs.openSync(path.join(logDir, 'walle.err'), 'a')],
455
+ stdio: 'ignore',
421
456
  env: { ...process.env, CTM_PORT: port },
422
457
  });
423
458
  child.unref();
@@ -505,6 +540,22 @@ function detectTimezone() {
505
540
  return 'UTC';
506
541
  }
507
542
 
543
+ function compileHotkeyDaemon(walleDir) {
544
+ if (process.platform !== 'darwin') return; // macOS only
545
+ const swiftSource = path.join(walleDir, 'claude-task-manager', 'bin', 'ctm-hotkey.swift');
546
+ if (!fs.existsSync(swiftSource)) return;
547
+ const binary = path.join(process.env.HOME, '.local', 'bin', 'ctm-hotkey');
548
+ try {
549
+ fs.mkdirSync(path.dirname(binary), { recursive: true });
550
+ execFileSync('swiftc', ['-O', '-o', binary, swiftSource, '-framework', 'Cocoa'], { timeout: 120000, stdio: 'pipe' });
551
+ fs.chmodSync(binary, 0o755);
552
+ console.log(` ${GREEN}Compiled hotkey daemon${RESET} ${DIM}(${binary})${RESET}`);
553
+ } catch {
554
+ // swiftc not available or compilation failed — non-fatal
555
+ console.log(` ${DIM}Skipped hotkey daemon (Swift compiler not available)${RESET}`);
556
+ }
557
+ }
558
+
508
559
  function copyRecursive(src, dest) {
509
560
  const stat = fs.statSync(src);
510
561
  if (stat.isDirectory()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-walle",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
4
4
  "description": "CTM + Wall-E \u2014 AI coding dashboard and personal digital twin agent. Multi-agent terminal for Claude Code, Codex, Gemini & Aider, plus prompt editor, task queue, and an agent that learns from Slack, email & calendar.",
5
5
  "bin": {
6
6
  "create-walle": "bin/create-walle.js"
@@ -24,6 +24,18 @@ When developing CTM or Wall-E code:
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
 
27
+ ## Testing
28
+
29
+ Both projects use Node.js built-in test runner with `--test-force-exit` to prevent hangs:
30
+ - **Wall-E**: `cd wall-e && npm test`
31
+ - **CTM**: `cd claude-task-manager && npm test`
32
+
33
+ When writing new tests, follow these rules to avoid handle leaks and cross-test contamination:
34
+ - **Never set `process.env` at module top level** — set in `before()`, restore in `after()`
35
+ - **Close every DB connection you open** — store `readDb` handles in module scope, close in `after()`/teardown
36
+ - **Call `brain.closeDb()` before `brain.initDb()`** in tests that reinitialize the brain singleton
37
+ - **Don't change `journal_mode`** on readonly connections (causes SQLITE_BUSY against WAL dbs)
38
+
27
39
  ## Publishing to npm (create-walle)
28
40
 
29
41
  When publishing with `/publish`:
@@ -32,3 +44,10 @@ When publishing with `/publish`:
32
44
  3. Bump version in both `create-walle/package.json` AND root `package.json`
33
45
  4. Run `bash build.sh` and verify file count
34
46
  5. Ask for confirmation before `npm publish`
47
+
48
+ ## Architecture reference
49
+
50
+ For Wall-E architecture (loops, brain DB, scheduler, skills, channels, anti-patterns):
51
+ read `wall-e/docs/architecture.md` before making non-trivial changes. The
52
+ "Non-goals" section is a guardrail — coordinate via data, not via
53
+ manager-of-managers.
@@ -3,50 +3,64 @@
3
3
  # Primary instance stays untouched. Ctrl+C to stop.
4
4
  #
5
5
  # Usage:
6
- # bash bin/dev.sh # Start dev instance (snapshot DBs on first run)
7
- # bash bin/dev.sh --refresh # Re-copy production DBs before starting
8
- # bash bin/dev.sh --fresh # Start with empty DBs
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
9
9
 
10
10
  set -e
11
11
  ROOT="$(cd "$(dirname "$0")/.." && pwd)"
12
12
  DEV_DIR="${WALLE_DEV_DIR:-/tmp/walle-dev}"
13
13
  DEV_CTM_PORT="${DEV_CTM_PORT:-4000}"
14
14
  DEV_WALLE_PORT="${DEV_WALLE_PORT:-4001}"
15
+ DEV_OAUTH_PROXY_PORT="${DEV_OAUTH_PROXY_PORT:-$((DEV_CTM_PORT + 2))}"
15
16
 
16
- # Source production .env to find DB paths
17
- PROD_CTM_DIR="$HOME/.walle/data"
18
- PROD_WALLE_DIR="$HOME/.walle/data"
17
+ # Source production .env to find DB paths. DEV_SOURCE_* lets worktrees without
18
+ # their own .env refresh from the primary repo's configured data directory.
19
+ PROD_CTM_DIR="${DEV_SOURCE_CTM_DATA_DIR:-$HOME/.walle/data}"
20
+ PROD_WALLE_DIR="${DEV_SOURCE_WALL_E_DATA_DIR:-$HOME/.walle/data}"
19
21
  if [[ -f "$ROOT/.env" ]]; then
20
22
  eval "$(grep -E '^(CTM_DATA_DIR|WALL_E_DATA_DIR)=' "$ROOT/.env" 2>/dev/null)" || true
21
- [[ -n "$CTM_DATA_DIR" ]] && PROD_CTM_DIR="$CTM_DATA_DIR"
22
- [[ -n "$WALL_E_DATA_DIR" ]] && PROD_WALLE_DIR="$WALL_E_DATA_DIR"
23
+ [[ -z "$DEV_SOURCE_CTM_DATA_DIR" && -n "$CTM_DATA_DIR" ]] && PROD_CTM_DIR="$CTM_DATA_DIR"
24
+ [[ -z "$DEV_SOURCE_WALL_E_DATA_DIR" && -n "$WALL_E_DATA_DIR" ]] && PROD_WALLE_DIR="$WALL_E_DATA_DIR"
23
25
  fi
24
26
 
25
27
  mkdir -p "$DEV_DIR"
26
28
 
29
+ cleanup_processes() {
30
+ pkill -f "ctm-dev-$DEV_CTM_PORT" 2>/dev/null || true
31
+ pkill -f "walle-dev-$DEV_CTM_PORT" 2>/dev/null || true
32
+ lsof -ti ":$DEV_CTM_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
33
+ lsof -ti ":$DEV_WALLE_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
34
+ lsof -ti ":$DEV_OAUTH_PROXY_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
35
+ }
36
+
37
+ cleanup_dev() {
38
+ cleanup_processes
39
+ # Remove dev data directory to prevent /tmp bloat (each copy is ~2-6 GB)
40
+ if [[ "$DEV_DIR" == /tmp/walle-* && -d "$DEV_DIR" ]]; then
41
+ echo "[dev] Cleaning up $DEV_DIR ..."
42
+ rm -rf "$DEV_DIR"
43
+ fi
44
+ }
45
+
46
+ cleanup_processes
47
+
27
48
  # Handle flags
28
- if [[ "$1" == "--fresh" ]]; then
49
+ if [[ "$1" == "--fresh" || -z "$1" ]]; then
29
50
  echo "[dev] Starting with fresh (empty) databases"
30
51
  rm -f "$DEV_DIR"/*.db "$DEV_DIR"/*.db-wal "$DEV_DIR"/*.db-shm
31
- elif [[ "$1" == "--refresh" || ! -f "$DEV_DIR/task-manager.db" ]]; then
32
- echo "[dev] Copying production databases to $DEV_DIR ..."
33
- # Copy CTM DB
34
- if [[ -f "$PROD_CTM_DIR/task-manager.db" ]]; then
35
- cp "$PROD_CTM_DIR/task-manager.db" "$DEV_DIR/task-manager.db"
36
- echo " CTM: $PROD_CTM_DIR/task-manager.db → $DEV_DIR/"
37
- fi
38
- # Copy Wall-E brain
39
- if [[ -f "$PROD_WALLE_DIR/wall-e-brain.db" ]]; then
40
- cp "$PROD_WALLE_DIR/wall-e-brain.db" "$DEV_DIR/wall-e-brain.db"
41
- echo " Brain: $PROD_WALLE_DIR/wall-e-brain.db → $DEV_DIR/"
42
- fi
43
- # Clean WAL files (they're specific to the source process)
52
+ elif [[ "$1" == "--refresh" ]]; then
53
+ echo "[dev] Snapshotting production databases to $DEV_DIR ..."
54
+ node "$ROOT/bin/sqlite-snapshot.js" "$PROD_CTM_DIR/task-manager.db" "$DEV_DIR/task-manager.db" "CTM"
55
+ node "$ROOT/bin/sqlite-snapshot.js" "$PROD_WALLE_DIR/wall-e-brain.db" "$DEV_DIR/wall-e-brain.db" "Brain"
56
+ # Ensure the dev instance owns its WAL files from first open.
44
57
  rm -f "$DEV_DIR"/*.db-wal "$DEV_DIR"/*.db-shm
45
58
  fi
46
59
 
47
60
  echo ""
48
61
  echo " Dev CTM: http://localhost:$DEV_CTM_PORT"
49
62
  echo " Dev Wall-E: port $DEV_WALLE_PORT"
63
+ echo " Dev OAuth: port $DEV_OAUTH_PROXY_PORT"
50
64
  echo " Dev data: $DEV_DIR"
51
65
  echo " Source: $ROOT"
52
66
  echo ""
@@ -59,14 +73,23 @@ export WALL_E_PORT="$DEV_WALLE_PORT"
59
73
  export CTM_DATA_DIR="$DEV_DIR"
60
74
  export WALL_E_DATA_DIR="$DEV_DIR"
61
75
  export CTM_HOST="127.0.0.1"
76
+ export CTM_INSTANCE_TAG="dev-$DEV_CTM_PORT"
77
+ export OAUTH_PROXY_PORT="$DEV_OAUTH_PROXY_PORT"
62
78
 
63
79
  # Source the rest of .env (API keys, owner name, etc.)
64
80
  if [[ -f "$ROOT/.env" ]]; then
65
81
  set -a
66
- source <(grep -v '^#' "$ROOT/.env" | grep -vE '^(CTM_PORT|WALL_E_PORT|CTM_DATA_DIR|WALL_E_DATA_DIR|CTM_HOST)=' | grep '=')
82
+ source <(grep -v '^#' "$ROOT/.env" | grep -vE '^(CTM_PORT|WALL_E_PORT|CTM_DATA_DIR|WALL_E_DATA_DIR|CTM_HOST|CTM_INSTANCE_TAG|OAUTH_PROXY_PORT)=' | grep '=')
67
83
  set +a
68
84
  fi
69
85
 
86
+ trap cleanup_dev EXIT
87
+
88
+ # Clean up stale dev/e2e data dirs older than 24h (from crashed sessions)
89
+ find /tmp -maxdepth 1 -name "walle-dev-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
90
+ find /tmp -maxdepth 1 -name "walle-e2e-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
91
+ find /tmp -maxdepth 1 -name "ctm-dev-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
92
+
70
93
  # Run in foreground so Ctrl+C stops it cleanly
71
94
  cd "$ROOT"
72
95
  exec node claude-task-manager/server.js
@@ -1,5 +1,6 @@
1
1
  #!/bin/bash
2
- # Install Wall-E as a macOS Launch Agent so it starts automatically on login.
2
+ # Install CTM + Wall-E as a macOS Launch Agent so it starts automatically on login
3
+ # and auto-restarts on crash (but NOT on clean exit).
3
4
  # Usage: bash bin/install-service.sh [--uninstall]
4
5
 
5
6
  set -e
@@ -7,22 +8,40 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
8
  ROOT="$(dirname "$SCRIPT_DIR")"
8
9
  LABEL="com.walle.server"
9
10
  PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
10
- PORT="${CTM_PORT:-4567}"
11
+ PORT="${CTM_PORT:-3456}"
11
12
 
12
13
  if [[ "$1" == "--uninstall" ]]; then
13
- launchctl unload "$PLIST" 2>/dev/null || true
14
+ launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || \
15
+ launchctl unload "$PLIST" 2>/dev/null || true
14
16
  rm -f "$PLIST"
15
- echo "Wall-E service uninstalled."
17
+ echo "CTM service uninstalled."
16
18
  exit 0
17
19
  fi
18
20
 
19
- # Source .env to get the port
21
+ # Source .env for port and data dir overrides
22
+ ENV_VARS=""
20
23
  if [[ -f "$ROOT/.env" ]]; then
21
- export $(grep -v '^#' "$ROOT/.env" | grep '=' | xargs)
22
- PORT="${CTM_PORT:-4567}"
24
+ while IFS='' read -r line || [[ -n "$line" ]]; do
25
+ [[ -z "$line" || "$line" == \#* ]] && continue
26
+ key="${line%%=*}"
27
+ value="${line#*=}"
28
+ key=$(echo "$key" | xargs)
29
+ value=$(echo "$value" | xargs | sed 's/^["'"'"']//;s/["'"'"']$//')
30
+ [[ -z "$key" ]] && continue
31
+ case "$key" in
32
+ CTM_PORT) PORT="$value" ;;
33
+ esac
34
+ # XML-escape for plist safety
35
+ esc_key=$(echo "$key" | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g')
36
+ esc_val=$(echo "$value" | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g')
37
+ ENV_VARS="$ENV_VARS
38
+ <key>$esc_key</key>
39
+ <string>$esc_val</string>"
40
+ done < "$ROOT/.env"
23
41
  fi
24
42
 
25
43
  NODE=$(which node)
44
+ NODE_BIN_DIR=$(dirname "$NODE")
26
45
  LOG_DIR="$HOME/.walle/logs"
27
46
  mkdir -p "$LOG_DIR"
28
47
 
@@ -43,30 +62,45 @@ cat > "$PLIST" << EOF
43
62
  <key>EnvironmentVariables</key>
44
63
  <dict>
45
64
  <key>PATH</key>
46
- <string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
65
+ <string>$NODE_BIN_DIR:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
47
66
  <key>HOME</key>
48
67
  <string>$HOME</string>
49
68
  <key>CTM_PORT</key>
50
69
  <string>$PORT</string>
70
+ <key>CTM_MANAGED_BY_LAUNCHD</key>
71
+ <string>1</string>$ENV_VARS
51
72
  </dict>
52
73
  <key>RunAtLoad</key>
53
74
  <true/>
54
75
  <key>KeepAlive</key>
55
- <true/>
76
+ <dict>
77
+ <key>SuccessfulExit</key>
78
+ <false/>
79
+ </dict>
80
+ <key>ThrottleInterval</key>
81
+ <integer>5</integer>
56
82
  <key>StandardOutPath</key>
57
- <string>$LOG_DIR/walle.log</string>
83
+ <string>$LOG_DIR/ctm.log</string>
58
84
  <key>StandardErrorPath</key>
59
- <string>$LOG_DIR/walle.err</string>
85
+ <string>$LOG_DIR/ctm.err</string>
60
86
  </dict>
61
87
  </plist>
62
88
  EOF
63
89
 
64
- launchctl unload "$PLIST" 2>/dev/null || true
65
- launchctl load "$PLIST"
90
+ # Load the service (unload first if previously loaded, wait for clean exit)
91
+ launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || \
92
+ launchctl unload "$PLIST" 2>/dev/null || true
93
+ sleep 1 # Let old process release port before bootstrapping new one
94
+ launchctl bootstrap "gui/$(id -u)" "$PLIST" 2>/dev/null || \
95
+ launchctl load "$PLIST"
66
96
 
67
- echo "Wall-E installed as a macOS service."
97
+ echo "CTM installed as a macOS Launch Agent."
68
98
  echo ""
69
- echo " Status: launchctl list | grep walle"
70
- echo " Logs: tail -f ~/.walle/logs/walle.log"
99
+ echo " Status: launchctl list $LABEL"
100
+ echo " Logs: tail -f ~/.walle/logs/ctm.log"
101
+ echo " Errors: tail -f ~/.walle/logs/ctm.err"
71
102
  echo " Dashboard: http://localhost:$PORT"
72
103
  echo " Uninstall: bash bin/install-service.sh --uninstall"
104
+ echo ""
105
+ echo " Auto-restarts on crash. Clean exit (SIGTERM/SIGINT) stops the service."
106
+ echo " To manually stop: launchctl kill SIGTERM gui/$(id -u)/$LABEL"
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { spawn } = require('child_process');
7
+
8
+ function loadBetterSqlite() {
9
+ try { return require('../claude-task-manager/node_modules/better-sqlite3'); } catch {}
10
+ try { return require('../wall-e/node_modules/better-sqlite3'); } catch {}
11
+ return require('better-sqlite3');
12
+ }
13
+
14
+ const Database = loadBetterSqlite();
15
+
16
+ function removeFile(file) {
17
+ try { fs.rmSync(file, { force: true }); } catch {}
18
+ }
19
+
20
+ function removeDbFamily(file) {
21
+ removeFile(file);
22
+ removeFile(file + '-wal');
23
+ removeFile(file + '-shm');
24
+ }
25
+
26
+ function loadOptionalVec(db) {
27
+ try {
28
+ const sqliteVec = require('../wall-e/node_modules/sqlite-vec');
29
+ sqliteVec.load(db);
30
+ } catch {}
31
+ }
32
+
33
+ function logDebug(label, message) {
34
+ if (process.env.SQLITE_SNAPSHOT_DEBUG === '1') {
35
+ console.warn(` ${label}: ${message}`);
36
+ }
37
+ }
38
+
39
+ function quickCheck(dbPath) {
40
+ let db;
41
+ try {
42
+ db = new Database(dbPath, { readonly: true, fileMustExist: true });
43
+ loadOptionalVec(db);
44
+ const rows = db.pragma('quick_check');
45
+ const value = rows?.[0] ? Object.values(rows[0])[0] : '';
46
+ return value === 'ok' ? { ok: true } : { ok: false, error: String(value || 'quick_check failed') };
47
+ } catch (err) {
48
+ return { ok: false, error: err.message };
49
+ } finally {
50
+ try { if (db) db.close(); } catch {}
51
+ }
52
+ }
53
+
54
+ async function sqliteBackup(src, dest) {
55
+ const db = new Database(src, { readonly: true, fileMustExist: true });
56
+ try {
57
+ loadOptionalVec(db);
58
+ await db.backup(dest);
59
+ } finally {
60
+ db.close();
61
+ }
62
+ }
63
+
64
+ function pipeRecover(input, output) {
65
+ return new Promise((resolve, reject) => {
66
+ removeFile(output);
67
+ const sqlite = process.env.SQLITE3_BIN || '/usr/bin/sqlite3';
68
+ const recover = spawn(sqlite, [input, '.recover'], { stdio: ['ignore', 'pipe', 'inherit'] });
69
+ const apply = spawn(sqlite, [output], { stdio: ['pipe', 'ignore', 'inherit'] });
70
+ let recoverCode = null;
71
+ let applyCode = null;
72
+ let settled = false;
73
+ const fail = (err) => {
74
+ if (settled) return;
75
+ settled = true;
76
+ reject(err);
77
+ };
78
+ const maybeDone = () => {
79
+ if (settled || recoverCode === null || applyCode === null) return;
80
+ if (recoverCode !== 0) return fail(new Error(`sqlite3 .recover exited ${recoverCode}`));
81
+ if (applyCode !== 0) return fail(new Error(`sqlite3 restore exited ${applyCode}`));
82
+ settled = true;
83
+ resolve();
84
+ };
85
+ recover.stdout.pipe(apply.stdin);
86
+ recover.on('error', fail);
87
+ apply.on('error', fail);
88
+ recover.on('close', (code) => {
89
+ recoverCode = code;
90
+ if (code !== 0) try { apply.stdin.destroy(); } catch {}
91
+ maybeDone();
92
+ });
93
+ apply.on('close', (code) => {
94
+ applyCode = code;
95
+ maybeDone();
96
+ });
97
+ });
98
+ }
99
+
100
+ async function main() {
101
+ const [src, dest, label = 'SQLite'] = process.argv.slice(2);
102
+ if (!src || !dest) {
103
+ console.error('Usage: sqlite-snapshot.js <source.db> <dest.db> [label]');
104
+ process.exit(2);
105
+ }
106
+ if (!fs.existsSync(src)) {
107
+ console.log(` ${label}: source missing (${src}) - starting fresh`);
108
+ removeDbFamily(dest);
109
+ return;
110
+ }
111
+
112
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
113
+ removeDbFamily(dest);
114
+ const tmp = `${dest}.tmp-${process.pid}`;
115
+ const recovered = `${dest}.recovered-${process.pid}`;
116
+ removeDbFamily(tmp);
117
+ removeDbFamily(recovered);
118
+
119
+ try {
120
+ await sqliteBackup(src, tmp);
121
+ const check = quickCheck(tmp);
122
+ if (check.ok) {
123
+ fs.renameSync(tmp, dest);
124
+ console.log(` ${label}: snapshotted ${src} -> ${dest}`);
125
+ return;
126
+ }
127
+
128
+ logDebug(label, `snapshot quick_check failed: ${check.error.slice(0, 160)}`);
129
+ console.log(` ${label}: snapshot required recovery - attempting sqlite .recover`);
130
+ await pipeRecover(tmp, recovered);
131
+ const recoveredCheck = quickCheck(recovered);
132
+ if (!recoveredCheck.ok) throw new Error(`recovered DB failed quick_check: ${recoveredCheck.error.slice(0, 160)}`);
133
+ fs.renameSync(recovered, dest);
134
+ console.log(` ${label}: recovered snapshot written to ${dest}`);
135
+ } catch (err) {
136
+ logDebug(label, `unable to create healthy snapshot: ${err.message}`);
137
+ console.warn(` ${label}: unable to create healthy snapshot - starting fresh`);
138
+ removeDbFamily(dest);
139
+ } finally {
140
+ removeDbFamily(tmp);
141
+ removeDbFamily(recovered);
142
+ }
143
+ }
144
+
145
+ main().catch((err) => {
146
+ console.error(`sqlite snapshot failed: ${err.stack || err.message}`);
147
+ process.exit(1);
148
+ });