create-walle 0.9.9 → 0.9.10

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 (529) 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/http/api-utils.js +100 -0
  322. package/template/wall-e/http/auth.js +45 -0
  323. package/template/wall-e/http/chat-api.js +377 -0
  324. package/template/wall-e/http/listening-api.js +441 -0
  325. package/template/wall-e/http/model-admin.js +586 -0
  326. package/template/wall-e/http/scheduler-api.js +49 -0
  327. package/template/wall-e/lib/activity-log.js +99 -0
  328. package/template/wall-e/lib/coalescer.js +46 -0
  329. package/template/wall-e/lib/config-watcher.js +95 -0
  330. package/template/wall-e/lib/recovery-logger.js +226 -0
  331. package/template/wall-e/lib/scheduler-failure-alert.js +127 -0
  332. package/template/wall-e/lib/scheduler.js +393 -22
  333. package/template/wall-e/listening/calendar.js +282 -0
  334. package/template/wall-e/listening/diarize.js +209 -0
  335. package/template/wall-e/listening/engine.js +299 -0
  336. package/template/wall-e/listening/notes.js +293 -0
  337. package/template/wall-e/listening/refine.js +65 -0
  338. package/template/wall-e/listening/storage.js +80 -0
  339. package/template/wall-e/listening/stt.js +251 -0
  340. package/template/wall-e/llm/anthropic.js +139 -18
  341. package/template/wall-e/llm/anthropic.plugin.json +23 -0
  342. package/template/wall-e/llm/claude-cli.js +208 -0
  343. package/template/wall-e/llm/claude-cli.plugin.json +23 -0
  344. package/template/wall-e/llm/client.js +72 -30
  345. package/template/wall-e/llm/codex-cli.js +210 -0
  346. package/template/wall-e/llm/codex-cli.plugin.json +23 -0
  347. package/template/wall-e/llm/deepseek.js +182 -0
  348. package/template/wall-e/llm/deepseek.plugin.json +22 -0
  349. package/template/wall-e/llm/google.js +104 -4
  350. package/template/wall-e/llm/google.plugin.json +22 -0
  351. package/template/wall-e/llm/index.js +1 -0
  352. package/template/wall-e/llm/lmstudio.js +40 -0
  353. package/template/wall-e/llm/lmstudio.plugin.json +23 -0
  354. package/template/wall-e/llm/mlx.plugin.json +24 -0
  355. package/template/wall-e/llm/ollama-setup.js +7 -1
  356. package/template/wall-e/llm/ollama.js +66 -8
  357. package/template/wall-e/llm/ollama.plugin.json +23 -0
  358. package/template/wall-e/llm/openai.js +30 -15
  359. package/template/wall-e/llm/openai.plugin.json +22 -0
  360. package/template/wall-e/llm/provider-detector.js +3 -6
  361. package/template/wall-e/llm/registry.js +248 -0
  362. package/template/wall-e/llm/retry.js +163 -0
  363. package/template/wall-e/llm/tool-adapter.js +50 -3
  364. package/template/wall-e/loops/backfill.js +149 -2
  365. package/template/wall-e/loops/boot.js +124 -0
  366. package/template/wall-e/loops/conversation-composer.js +129 -0
  367. package/template/wall-e/loops/deterministic-ordering.js +140 -0
  368. package/template/wall-e/loops/ingest.js +37 -0
  369. package/template/wall-e/loops/initiative.js +68 -7
  370. package/template/wall-e/loops/loop-directives.js +128 -0
  371. package/template/wall-e/loops/loop-precheck.js +96 -0
  372. package/template/wall-e/loops/loop-prompt-discipline.js +82 -0
  373. package/template/wall-e/loops/reflect.js +38 -4
  374. package/template/wall-e/loops/silent-reply-tokens.js +109 -0
  375. package/template/wall-e/loops/tasks.js +27 -2
  376. package/template/wall-e/loops/think.js +20 -4
  377. package/template/wall-e/loops/workspace-prompts.js +210 -0
  378. package/template/wall-e/mcp-server.js +146 -0
  379. package/template/wall-e/package.json +10 -2
  380. package/template/wall-e/plugins/activation-planner.js +161 -0
  381. package/template/wall-e/plugins/diagnostics.js +138 -0
  382. package/template/wall-e/plugins/manifest-loader.js +215 -0
  383. package/template/wall-e/plugins/manifest-types.js +66 -0
  384. package/template/wall-e/plugins/manifest-validator.js +241 -0
  385. package/template/wall-e/plugins/npm-scanner.js +191 -0
  386. package/template/wall-e/plugins/registry-base.js +81 -0
  387. package/template/wall-e/prompts/tool-workflows.md +51 -0
  388. package/template/wall-e/qa/README.md +59 -0
  389. package/template/wall-e/qa/scenario-format.md +75 -0
  390. package/template/wall-e/qa/scenarios/agents/instruction-followthrough.md +63 -0
  391. package/template/wall-e/qa/scenarios/channels/handoff-context-preservation.md +74 -0
  392. package/template/wall-e/qa/scenarios/character/persona-consistency.md +61 -0
  393. package/template/wall-e/runtime/devbox-gateway.js +38 -0
  394. package/template/wall-e/scripts/eval-embeddings.js +2 -5
  395. package/template/wall-e/scripts/smoke-coding-agent-jsonl.js +254 -0
  396. package/template/wall-e/search/bm25.js +97 -0
  397. package/template/wall-e/server.js +48 -8
  398. package/template/wall-e/skills/_bundled/coding-agent/run.js +42 -33
  399. package/template/wall-e/skills/_bundled/email-sync/mail-search.swift +237 -0
  400. package/template/wall-e/skills/_bundled/email-sync/run.js +81 -27
  401. package/template/wall-e/skills/_bundled/file-ingest/run.js +13 -8
  402. package/template/wall-e/skills/_bundled/glean-team-sync/run.js +1 -2
  403. package/template/wall-e/skills/_bundled/google-calendar/run.js +6 -23
  404. package/template/wall-e/skills/_bundled/gws-workspace/SKILL.md +76 -0
  405. package/template/wall-e/skills/_bundled/gws-workspace/run.js +401 -0
  406. package/template/wall-e/skills/_bundled/gws-workspace/setup.js +574 -0
  407. package/template/wall-e/skills/_bundled/listening/SKILL.md +26 -0
  408. package/template/wall-e/skills/_bundled/listening/run.js +80 -0
  409. package/template/wall-e/skills/_bundled/proactive-alerts/run.js +19 -3
  410. package/template/wall-e/skills/_bundled/slack-mentions/run.js +82 -19
  411. package/template/wall-e/skills/internal-skill-registry.js +229 -0
  412. package/template/wall-e/skills/routing-reason-codes.js +82 -0
  413. package/template/wall-e/skills/sandbox-registry.js +104 -0
  414. package/template/wall-e/skills/skill-dispatch-decision.js +192 -0
  415. package/template/wall-e/skills/skill-executor.js +49 -6
  416. package/template/wall-e/skills/skill-fallback.js +146 -0
  417. package/template/wall-e/skills/skill-harness-registry.js +173 -0
  418. package/template/wall-e/skills/skill-loader.js +151 -220
  419. package/template/wall-e/skills/skill-planner.js +382 -62
  420. package/template/wall-e/skills/skill-snapshot.js +134 -0
  421. package/template/wall-e/skills/skill-validator.js +103 -1
  422. package/template/wall-e/skills/slack-ingest.js +26 -2
  423. package/template/wall-e/skills/trigger-registry.js +120 -0
  424. package/template/wall-e/telemetry.js +17 -1
  425. package/template/wall-e/tools/builtin-middleware.js +167 -0
  426. package/template/wall-e/tools/coding-events.js +68 -0
  427. package/template/wall-e/tools/coding-middleware.js +169 -0
  428. package/template/wall-e/tools/command-registry.js +237 -0
  429. package/template/wall-e/tools/edit-replacers.js +485 -0
  430. package/template/wall-e/tools/env-service.js +148 -0
  431. package/template/wall-e/tools/event-log.js +207 -0
  432. package/template/wall-e/tools/file-tracker.js +72 -0
  433. package/template/wall-e/tools/formatter.js +397 -0
  434. package/template/wall-e/tools/local-tools.js +929 -195
  435. package/template/wall-e/tools/lsp-client.js +701 -0
  436. package/template/wall-e/tools/lsp-language.js +137 -0
  437. package/template/wall-e/tools/lsp-servers.js +869 -0
  438. package/template/wall-e/tools/npm-service.js +180 -0
  439. package/template/wall-e/tools/patch.js +503 -0
  440. package/template/wall-e/tools/permission-checker.js +137 -34
  441. package/template/wall-e/tools/permission-rules.js +476 -0
  442. package/template/wall-e/tools/port-detector.js +81 -0
  443. package/template/wall-e/tools/project-detector.js +290 -0
  444. package/template/wall-e/tools/question-manager.js +213 -0
  445. package/template/wall-e/tools/session-sharing.js +231 -0
  446. package/template/wall-e/tools/shell-analyzer.js +524 -0
  447. package/template/wall-e/tools/slack-mcp.js +1 -0
  448. package/template/wall-e/tools/smart-truncation.js +100 -0
  449. package/template/wall-e/tools/snapshot.js +479 -0
  450. package/template/wall-e/utils/dedup.js +165 -0
  451. package/template/wall-e/utils/exporter.js +163 -0
  452. package/template/wall-e/utils/heartbeat-content.js +78 -0
  453. package/template/wall-e/utils/repair.js +145 -0
  454. package/template/website/index.html +2 -3
  455. package/template/claude-task-manager/workers/vterm-worker.js +0 -179
  456. package/template/wall-e/test/eval/aggregator.test.js +0 -180
  457. package/template/wall-e/test/eval/benchmarks.test.js +0 -373
  458. package/template/wall-e/test/eval/brain-shadow.test.js +0 -359
  459. package/template/wall-e/test/eval/evaluate.test.js +0 -221
  460. package/template/wall-e/test/eval/evaluator.test.js +0 -340
  461. package/template/wall-e/test/eval/exporter.test.js +0 -353
  462. package/template/wall-e/test/eval/harvester.test.js +0 -718
  463. package/template/wall-e/test/eval/head-to-head.test.js +0 -485
  464. package/template/wall-e/test/eval/promoter.test.js +0 -175
  465. package/template/wall-e/test/eval/shadow.test.js +0 -156
  466. package/template/wall-e/test/eval/trainer.test.js +0 -314
  467. package/template/wall-e/test/evaluation/complexity.test.js +0 -101
  468. package/template/wall-e/test/evaluation/learner.test.js +0 -271
  469. package/template/wall-e/test/evaluation/quorum.test.js +0 -372
  470. package/template/wall-e/test/evaluation/router.test.js +0 -269
  471. package/template/wall-e/test/evaluation/scorecard.test.js +0 -185
  472. package/template/wall-e/test/llm/anthropic.test.js +0 -172
  473. package/template/wall-e/test/llm/brain-models.test.js +0 -182
  474. package/template/wall-e/test/llm/client.test.js +0 -200
  475. package/template/wall-e/test/llm/google.test.js +0 -37
  476. package/template/wall-e/test/llm/health.test.js +0 -426
  477. package/template/wall-e/test/llm/integration.test.js +0 -285
  478. package/template/wall-e/test/llm/ollama.test.js +0 -50
  479. package/template/wall-e/test/llm/openai.test.js +0 -48
  480. package/template/wall-e/test/llm/tool-adapter.test.js +0 -297
  481. package/template/wall-e/test/training/aggregator.test.js +0 -180
  482. package/template/wall-e/test/training/brain-shadow.test.js +0 -359
  483. package/template/wall-e/test/training/evaluate.test.js +0 -221
  484. package/template/wall-e/test/training/evaluator.test.js +0 -340
  485. package/template/wall-e/test/training/exporter.test.js +0 -353
  486. package/template/wall-e/test/training/harvester.test.js +0 -718
  487. package/template/wall-e/test/training/promoter.test.js +0 -175
  488. package/template/wall-e/test/training/shadow.test.js +0 -156
  489. package/template/wall-e/test/training/trainer.test.js +0 -314
  490. package/template/wall-e/tests/adapter-base.test.js +0 -20
  491. package/template/wall-e/tests/adapter-ctm.test.js +0 -122
  492. package/template/wall-e/tests/adapter-slack.test.js +0 -98
  493. package/template/wall-e/tests/agent-api.test.js +0 -256
  494. package/template/wall-e/tests/api-walle.test.js +0 -222
  495. package/template/wall-e/tests/backfill.test.js +0 -126
  496. package/template/wall-e/tests/brain.test.js +0 -603
  497. package/template/wall-e/tests/channels.test.js +0 -104
  498. package/template/wall-e/tests/chat.test.js +0 -103
  499. package/template/wall-e/tests/coding-agent-integration.test.js +0 -240
  500. package/template/wall-e/tests/coding-context.test.js +0 -212
  501. package/template/wall-e/tests/coding-orchestrator.test.js +0 -298
  502. package/template/wall-e/tests/coding-review.test.js +0 -141
  503. package/template/wall-e/tests/compactor.test.js +0 -321
  504. package/template/wall-e/tests/confidence.test.js +0 -134
  505. package/template/wall-e/tests/context-builder.test.js +0 -222
  506. package/template/wall-e/tests/contradiction.test.js +0 -217
  507. package/template/wall-e/tests/embeddings.test.js +0 -378
  508. package/template/wall-e/tests/event-bus.test.js +0 -74
  509. package/template/wall-e/tests/ingest.test.js +0 -113
  510. package/template/wall-e/tests/initiative.test.js +0 -354
  511. package/template/wall-e/tests/mcp-client.test.js +0 -71
  512. package/template/wall-e/tests/mcp-inject.test.js +0 -68
  513. package/template/wall-e/tests/mcp-server.test.js +0 -219
  514. package/template/wall-e/tests/ollama-setup.test.js +0 -81
  515. package/template/wall-e/tests/proactive-alerts.test.js +0 -140
  516. package/template/wall-e/tests/provider-availability.test.js +0 -231
  517. package/template/wall-e/tests/provider-detector.test.js +0 -127
  518. package/template/wall-e/tests/quorum-evaluator.test.js +0 -277
  519. package/template/wall-e/tests/reflect.test.js +0 -103
  520. package/template/wall-e/tests/scheduler.test.js +0 -546
  521. package/template/wall-e/tests/scorecard-evolution.test.js +0 -96
  522. package/template/wall-e/tests/self-critique.test.js +0 -162
  523. package/template/wall-e/tests/server.test.js +0 -111
  524. package/template/wall-e/tests/session-persistence.test.js +0 -331
  525. package/template/wall-e/tests/skills.test.js +0 -198
  526. package/template/wall-e/tests/slack-ingest.test.js +0 -103
  527. package/template/wall-e/tests/think.test.js +0 -454
  528. package/template/wall-e/tests/tier-selector.test.js +0 -109
  529. 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.10",
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
+ });