create-walle 0.9.21 → 0.9.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (500) hide show
  1. package/README.md +27 -5
  2. package/package.json +2 -2
  3. package/template/CLAUDE.md +2 -2
  4. package/template/LICENSE +1 -1
  5. package/template/bin/ctm-dev-cleanup.js +24 -3
  6. package/template/bin/ctm-launch.sh +13 -0
  7. package/template/bin/dev.sh +156 -18
  8. package/template/bin/node-bin.sh +84 -0
  9. package/template/bin/pin-node.sh +51 -0
  10. package/template/claude-task-manager/api-prompts.js +1203 -182
  11. package/template/claude-task-manager/api-reviews.js +109 -15
  12. package/template/claude-task-manager/approval-agent.js +1360 -280
  13. package/template/claude-task-manager/bin/restart-ctm.sh +64 -23
  14. package/template/claude-task-manager/bin/storage-migration-supervisor.js +338 -0
  15. package/template/claude-task-manager/db.js +4417 -295
  16. package/template/claude-task-manager/docs/app-update-refresh-protocol.md +69 -0
  17. package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
  18. package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
  19. package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
  20. package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
  21. package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
  22. package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
  23. package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
  24. package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
  25. package/template/claude-task-manager/docs/image-paste-ux.md +13 -0
  26. package/template/claude-task-manager/docs/ipad-web-preview.md +88 -0
  27. package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
  28. package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
  29. package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
  30. package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
  31. package/template/claude-task-manager/docs/phone-access-design.md +53 -15
  32. package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
  33. package/template/claude-task-manager/docs/phone-setup.md +3 -0
  34. package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
  35. package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
  36. package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
  37. package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
  38. package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
  39. package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
  40. package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
  41. package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
  42. package/template/claude-task-manager/docs/session-title-authority.md +32 -0
  43. package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
  44. package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
  45. package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
  46. package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
  47. package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
  48. package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
  49. package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
  50. package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
  51. package/template/claude-task-manager/git-utils.js +897 -27
  52. package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
  53. package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
  54. package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
  55. package/template/claude-task-manager/lib/agent-presets.js +17 -1
  56. package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
  57. package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
  58. package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
  59. package/template/claude-task-manager/lib/async-semaphore.js +44 -0
  60. package/template/claude-task-manager/lib/auth-context.js +5 -0
  61. package/template/claude-task-manager/lib/auth-rate-limit.js +47 -4
  62. package/template/claude-task-manager/lib/auth-rules.js +29 -2
  63. package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
  64. package/template/claude-task-manager/lib/background-llm.js +144 -17
  65. package/template/claude-task-manager/lib/branch-inventory.js +212 -0
  66. package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
  67. package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
  68. package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
  69. package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
  70. package/template/claude-task-manager/lib/codex-zst.js +124 -0
  71. package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
  72. package/template/claude-task-manager/lib/connection-health.js +232 -0
  73. package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
  74. package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
  75. package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
  76. package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
  77. package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
  78. package/template/claude-task-manager/lib/document-review.js +141 -6
  79. package/template/claude-task-manager/lib/escalation-review.js +152 -0
  80. package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
  81. package/template/claude-task-manager/lib/headless-term-service.js +678 -0
  82. package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
  83. package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
  84. package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
  85. package/template/claude-task-manager/lib/main-db-census.js +216 -0
  86. package/template/claude-task-manager/lib/message-pagination.js +106 -4
  87. package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +750 -26
  88. package/template/claude-task-manager/lib/mobile-auth-api.js +274 -7
  89. package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
  90. package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
  91. package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
  92. package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
  93. package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
  94. package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
  95. package/template/claude-task-manager/lib/perf-tracker.js +242 -6
  96. package/template/claude-task-manager/lib/permission-match.js +76 -0
  97. package/template/claude-task-manager/lib/permission-sync.js +133 -20
  98. package/template/claude-task-manager/lib/process-title.js +35 -0
  99. package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
  100. package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
  101. package/template/claude-task-manager/lib/prompt-intent.js +132 -0
  102. package/template/claude-task-manager/lib/provider-user-context.js +34 -0
  103. package/template/claude-task-manager/lib/read-pool-client.js +313 -0
  104. package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
  105. package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
  106. package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
  107. package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
  108. package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
  109. package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
  110. package/template/claude-task-manager/lib/restart-guard.js +109 -0
  111. package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
  112. package/template/claude-task-manager/lib/restore-policy.js +13 -0
  113. package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
  114. package/template/claude-task-manager/lib/restore-runtime.js +68 -0
  115. package/template/claude-task-manager/lib/restore-storm.js +34 -0
  116. package/template/claude-task-manager/lib/resume-cwd.js +36 -0
  117. package/template/claude-task-manager/lib/resume-preflight.js +313 -0
  118. package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
  119. package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
  120. package/template/claude-task-manager/lib/scheduler.js +21 -1
  121. package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
  122. package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
  123. package/template/claude-task-manager/lib/server-listeners.js +239 -0
  124. package/template/claude-task-manager/lib/session-capture.js +42 -7
  125. package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
  126. package/template/claude-task-manager/lib/session-history.js +388 -43
  127. package/template/claude-task-manager/lib/session-host-manager.js +287 -0
  128. package/template/claude-task-manager/lib/session-image-refs.js +209 -0
  129. package/template/claude-task-manager/lib/session-jobs.js +399 -59
  130. package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
  131. package/template/claude-task-manager/lib/session-restore.js +53 -0
  132. package/template/claude-task-manager/lib/session-standup.js +123 -23
  133. package/template/claude-task-manager/lib/session-state-bus.js +14 -0
  134. package/template/claude-task-manager/lib/session-stream.js +64 -16
  135. package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
  136. package/template/claude-task-manager/lib/session-token-usage.js +494 -0
  137. package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
  138. package/template/claude-task-manager/lib/setup-network-config.js +9 -0
  139. package/template/claude-task-manager/lib/size-cap.js +45 -0
  140. package/template/claude-task-manager/lib/size-cap.test.js +62 -0
  141. package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
  142. package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
  143. package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
  144. package/template/claude-task-manager/lib/standup-attention.js +7 -3
  145. package/template/claude-task-manager/lib/status-authority.js +39 -0
  146. package/template/claude-task-manager/lib/status-hooks.js +4 -0
  147. package/template/claude-task-manager/lib/storage-migration.js +235 -0
  148. package/template/claude-task-manager/lib/structured-capture.js +298 -0
  149. package/template/claude-task-manager/lib/sync-io-census.js +163 -0
  150. package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
  151. package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
  152. package/template/claude-task-manager/lib/terminal-choice.js +364 -0
  153. package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
  154. package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
  155. package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
  156. package/template/claude-task-manager/lib/timeline-order.js +122 -0
  157. package/template/claude-task-manager/lib/transcript-store.js +348 -43
  158. package/template/claude-task-manager/lib/transport-security.js +84 -1
  159. package/template/claude-task-manager/lib/wait-state.js +184 -0
  160. package/template/claude-task-manager/lib/walle-client.js +47 -5
  161. package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
  162. package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
  163. package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
  164. package/template/claude-task-manager/lib/walle-native-health.js +403 -0
  165. package/template/claude-task-manager/lib/walle-repair.js +701 -0
  166. package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
  167. package/template/claude-task-manager/lib/walle-session-context.js +57 -21
  168. package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
  169. package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
  170. package/template/claude-task-manager/lib/walle-transcript.js +52 -0
  171. package/template/claude-task-manager/lib/worktree-active-sync.js +11 -7
  172. package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
  173. package/template/claude-task-manager/package.json +1 -1
  174. package/template/claude-task-manager/prompt-harvest.js +89 -66
  175. package/template/claude-task-manager/providers/claude-code.js +51 -3
  176. package/template/claude-task-manager/providers/cursor.js +140 -45
  177. package/template/claude-task-manager/public/css/reviews.css +551 -61
  178. package/template/claude-task-manager/public/css/setup.css +191 -0
  179. package/template/claude-task-manager/public/css/walle-session.css +865 -10
  180. package/template/claude-task-manager/public/css/walle.css +154 -0
  181. package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
  182. package/template/claude-task-manager/public/index.html +18516 -2058
  183. package/template/claude-task-manager/public/ipad.html +363 -0
  184. package/template/claude-task-manager/public/js/document-review-links.js +301 -0
  185. package/template/claude-task-manager/public/js/image-normalize.js +69 -36
  186. package/template/claude-task-manager/public/js/message-renderer.js +1265 -77
  187. package/template/claude-task-manager/public/js/prompts.js +66 -29
  188. package/template/claude-task-manager/public/js/reviews.js +901 -133
  189. package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
  190. package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
  191. package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
  192. package/template/claude-task-manager/public/js/setup.js +1273 -176
  193. package/template/claude-task-manager/public/js/stream-view.js +691 -73
  194. package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
  195. package/template/claude-task-manager/public/js/walle-session.js +2455 -158
  196. package/template/claude-task-manager/public/js/walle.js +455 -28
  197. package/template/claude-task-manager/public/m/app.css +2909 -262
  198. package/template/claude-task-manager/public/m/app.js +6601 -398
  199. package/template/claude-task-manager/public/m/claim.html +224 -17
  200. package/template/claude-task-manager/public/m/index.html +117 -21
  201. package/template/claude-task-manager/public/m/sw.js +3 -1
  202. package/template/claude-task-manager/public/manifest.json +2 -2
  203. package/template/claude-task-manager/public/prompts.html +30 -14
  204. package/template/claude-task-manager/queue-engine.js +507 -28
  205. package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
  206. package/template/claude-task-manager/server.js +14341 -2197
  207. package/template/claude-task-manager/session-integrity.js +160 -18
  208. package/template/claude-task-manager/session-search-ranking.js +1 -0
  209. package/template/claude-task-manager/session-utils.js +25 -5
  210. package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
  211. package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
  212. package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
  213. package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
  214. package/template/claude-task-manager/workers/harvest-worker.js +9 -55
  215. package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
  216. package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
  217. package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
  218. package/template/claude-task-manager/workers/session-host-process.js +146 -0
  219. package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
  220. package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
  221. package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
  222. package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
  223. package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
  224. package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
  225. package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
  226. package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
  227. package/template/docs/design/markdown-review-pane.md +206 -0
  228. package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +129 -38
  229. package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
  230. package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
  231. package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
  232. package/template/docs/private-memory-and-pii-policy.md +69 -0
  233. package/template/package.json +2 -1
  234. package/template/scripts/check-private-data.js +201 -0
  235. package/template/shared/sqlite-owner-guard.js +30 -0
  236. package/template/shared/sqlite-owner-write-queue.js +225 -0
  237. package/template/shared/sqlite-storage-policy.js +111 -0
  238. package/template/shared/sqlite-write-lock.js +428 -0
  239. package/template/wall-e/agent-runners/claude-code.js +5 -0
  240. package/template/wall-e/agent.js +166 -22
  241. package/template/wall-e/api-walle.js +524 -70
  242. package/template/wall-e/auth/provider-flows.js +11 -1
  243. package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
  244. package/template/wall-e/brain.js +1614 -141
  245. package/template/wall-e/chat/attachment-blocks.js +96 -0
  246. package/template/wall-e/chat/attachments.js +2 -1
  247. package/template/wall-e/chat/capability-resolver.js +7 -7
  248. package/template/wall-e/chat/context-messages.js +28 -0
  249. package/template/wall-e/chat/conversation-frame.js +630 -0
  250. package/template/wall-e/chat/provider-messages.js +125 -0
  251. package/template/wall-e/chat.js +1002 -233
  252. package/template/wall-e/coding/acceptance-contract.js +170 -0
  253. package/template/wall-e/coding/acp-adapter.js +1 -1
  254. package/template/wall-e/coding/agent-catalog.js +3 -0
  255. package/template/wall-e/coding/artifact-store.js +93 -0
  256. package/template/wall-e/coding/capability-router.js +120 -0
  257. package/template/wall-e/coding/coding-run-controller.js +423 -0
  258. package/template/wall-e/coding/compaction-service.js +157 -12
  259. package/template/wall-e/coding/frontend-verification.js +258 -0
  260. package/template/wall-e/coding/lifecycle-hooks.js +75 -0
  261. package/template/wall-e/coding/local-preview-contract.js +157 -0
  262. package/template/wall-e/coding/permission-service.js +57 -13
  263. package/template/wall-e/coding/prompt-bundle.js +19 -1
  264. package/template/wall-e/coding/prompt-section-registry.js +227 -0
  265. package/template/wall-e/coding/provider-compat.js +15 -0
  266. package/template/wall-e/coding/runtime-events.js +224 -0
  267. package/template/wall-e/coding/runtime-mode.js +3 -0
  268. package/template/wall-e/coding/side-git-snapshot.js +160 -4
  269. package/template/wall-e/coding/snapshot-service.js +143 -1
  270. package/template/wall-e/coding/stream-processor.js +388 -34
  271. package/template/wall-e/coding/task-tool.js +141 -4
  272. package/template/wall-e/coding/tool-execution-controller.js +365 -0
  273. package/template/wall-e/coding/tool-registry.js +43 -5
  274. package/template/wall-e/coding/user-hooks.js +217 -0
  275. package/template/wall-e/coding-orchestrator.js +1330 -221
  276. package/template/wall-e/coding-prompts.js +20 -4
  277. package/template/wall-e/context/context-builder.js +15 -2
  278. package/template/wall-e/decision/confidence.js +1 -1
  279. package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
  280. package/template/wall-e/docs/external-action-controller.md +26 -6
  281. package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
  282. package/template/wall-e/embeddings.js +591 -53
  283. package/template/wall-e/external-action-controller.js +12 -0
  284. package/template/wall-e/http/auth.js +1 -0
  285. package/template/wall-e/http/chat-api.js +46 -11
  286. package/template/wall-e/http/model-admin.js +836 -34
  287. package/template/wall-e/lib/boot-profile.js +88 -0
  288. package/template/wall-e/lib/event-loop-monitor.js +93 -0
  289. package/template/wall-e/lib/service-health.js +194 -0
  290. package/template/wall-e/llm/anthropic.js +130 -5
  291. package/template/wall-e/llm/client.js +266 -63
  292. package/template/wall-e/llm/default-fallback.js +382 -0
  293. package/template/wall-e/llm/health.js +19 -0
  294. package/template/wall-e/llm/message-guard.js +78 -0
  295. package/template/wall-e/llm/model-catalog.js +252 -1
  296. package/template/wall-e/llm/openai.js +26 -4
  297. package/template/wall-e/llm/portkey-sync.js +654 -0
  298. package/template/wall-e/llm/provider-error.js +30 -2
  299. package/template/wall-e/llm/registry.js +5 -1
  300. package/template/wall-e/llm/request-compat.js +67 -0
  301. package/template/wall-e/loops/backfill.js +79 -23
  302. package/template/wall-e/loops/brain-optimize.js +67 -0
  303. package/template/wall-e/loops/ingest.js +25 -10
  304. package/template/wall-e/loops/question-digest.js +160 -0
  305. package/template/wall-e/loops/reflect.js +6 -4
  306. package/template/wall-e/loops/think.js +39 -12
  307. package/template/wall-e/mcp-server.js +318 -36
  308. package/template/wall-e/memory/ctm-context-client.js +52 -14
  309. package/template/wall-e/memory/ctm-operational-context.js +237 -0
  310. package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
  311. package/template/wall-e/memory/ctm-session-context.js +111 -63
  312. package/template/wall-e/prompts/coding/deepseek.txt +3 -0
  313. package/template/wall-e/prompts/coding/gemini.txt +6 -0
  314. package/template/wall-e/prompts/coding/gpt.txt +6 -0
  315. package/template/wall-e/prompts/coding/local.txt +7 -0
  316. package/template/wall-e/runtime/decision-hooks.js +115 -0
  317. package/template/wall-e/runtime/devbox-gateway.js +82 -8
  318. package/template/wall-e/runtime/prompt-manifest.js +86 -0
  319. package/template/wall-e/runtime/tool-executor.js +269 -0
  320. package/template/wall-e/runtime/tool-result-envelope.js +138 -0
  321. package/template/wall-e/runtime/transcript-projection.js +60 -0
  322. package/template/wall-e/runtime/walle-runtime.js +224 -0
  323. package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
  324. package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
  325. package/template/wall-e/server.js +15 -0
  326. package/template/wall-e/session-files.js +9 -0
  327. package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
  328. package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
  329. package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
  330. package/template/wall-e/skills/claude-code-reader.js +7 -3
  331. package/template/wall-e/skills/script-skill-runner.js +10 -0
  332. package/template/wall-e/skills/skill-planner.js +38 -0
  333. package/template/wall-e/tools/builtin-middleware.js +19 -9
  334. package/template/wall-e/tools/local-tools.js +1428 -16
  335. package/template/wall-e/tools/permission-checker.js +73 -5
  336. package/template/wall-e/tools/question-manager.js +117 -7
  337. package/template/wall-e/training/harvester.js +12 -28
  338. package/template/wall-e/training/replay.js +25 -80
  339. package/template/website/index.html +10 -10
  340. package/template/wall-e/eval/ab-test.js +0 -203
  341. package/template/wall-e/eval/agent-runner.js +0 -772
  342. package/template/wall-e/eval/agent-scorer.js +0 -461
  343. package/template/wall-e/eval/aggregator.js +0 -414
  344. package/template/wall-e/eval/allowed-test-commands.js +0 -34
  345. package/template/wall-e/eval/benchmark-generator.js +0 -113
  346. package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
  347. package/template/wall-e/eval/benchmarks/chat.json +0 -82
  348. package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
  349. package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
  350. package/template/wall-e/eval/benchmarks/coding.json +0 -122
  351. package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
  352. package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
  353. package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
  354. package/template/wall-e/eval/benchmarks.js +0 -669
  355. package/template/wall-e/eval/cc-replay.js +0 -719
  356. package/template/wall-e/eval/chat-eval.js +0 -525
  357. package/template/wall-e/eval/check-keys.js +0 -15
  358. package/template/wall-e/eval/check-providers.js +0 -42
  359. package/template/wall-e/eval/codex-cli-baseline.js +0 -669
  360. package/template/wall-e/eval/coding-agent-real.js +0 -570
  361. package/template/wall-e/eval/context-compactor.js +0 -251
  362. package/template/wall-e/eval/debug-agent003.js +0 -68
  363. package/template/wall-e/eval/diagnostics.js +0 -216
  364. package/template/wall-e/eval/eval-orchestrator.js +0 -642
  365. package/template/wall-e/eval/evaluate.js +0 -202
  366. package/template/wall-e/eval/evaluator.js +0 -373
  367. package/template/wall-e/eval/exporter.js +0 -212
  368. package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
  369. package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
  370. package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
  371. package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
  372. package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
  373. package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
  374. package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
  375. package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
  376. package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
  377. package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
  378. package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
  379. package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
  380. package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
  381. package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
  382. package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
  383. package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
  384. package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
  385. package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
  386. package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
  387. package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
  388. package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
  389. package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
  390. package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
  391. package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
  392. package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
  393. package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
  394. package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
  395. package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
  396. package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
  397. package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
  398. package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
  399. package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
  400. package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
  401. package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
  402. package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
  403. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
  404. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
  405. package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
  406. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
  407. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
  408. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
  409. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
  410. package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
  411. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
  412. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
  413. package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
  414. package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
  415. package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
  416. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
  417. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
  418. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
  419. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
  420. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
  421. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
  422. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
  423. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
  424. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
  425. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
  426. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
  427. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
  428. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
  429. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
  430. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
  431. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
  432. package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
  433. package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
  434. package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
  435. package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
  436. package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
  437. package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
  438. package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
  439. package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
  440. package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
  441. package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
  442. package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
  443. package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
  444. package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
  445. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
  446. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
  447. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
  448. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
  449. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
  450. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
  451. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
  452. package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
  453. package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
  454. package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
  455. package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
  456. package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
  457. package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
  458. package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
  459. package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
  460. package/template/wall-e/eval/harvester.js +0 -685
  461. package/template/wall-e/eval/head-to-head.js +0 -388
  462. package/template/wall-e/eval/humaneval-adapter.js +0 -321
  463. package/template/wall-e/eval/list-models.js +0 -31
  464. package/template/wall-e/eval/livecodebench-adapter.js +0 -291
  465. package/template/wall-e/eval/mail-integration.js +0 -443
  466. package/template/wall-e/eval/manifest.js +0 -186
  467. package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
  468. package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
  469. package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
  470. package/template/wall-e/eval/meta-harness/cli.js +0 -86
  471. package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
  472. package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
  473. package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
  474. package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
  475. package/template/wall-e/eval/meta-harness/frontier.js +0 -96
  476. package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
  477. package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
  478. package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
  479. package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
  480. package/template/wall-e/eval/meta-harness/reporting.js +0 -58
  481. package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
  482. package/template/wall-e/eval/meta-harness/validation.js +0 -81
  483. package/template/wall-e/eval/promoter.js +0 -228
  484. package/template/wall-e/eval/provider-normalizer.js +0 -33
  485. package/template/wall-e/eval/replay.js +0 -395
  486. package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
  487. package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
  488. package/template/wall-e/eval/run-coding-agent-real.js +0 -187
  489. package/template/wall-e/eval/run-eval.js +0 -435
  490. package/template/wall-e/eval/run-model-comparison.js +0 -142
  491. package/template/wall-e/eval/session-evaluator.js +0 -187
  492. package/template/wall-e/eval/session-miner.js +0 -207
  493. package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
  494. package/template/wall-e/eval/session-transcripts.js +0 -509
  495. package/template/wall-e/eval/shadow.js +0 -161
  496. package/template/wall-e/eval/swebench-adapter.js +0 -345
  497. package/template/wall-e/eval/swebench-docker.js +0 -192
  498. package/template/wall-e/eval/train.py +0 -320
  499. package/template/wall-e/eval/trainer.js +0 -232
  500. package/template/wall-e/eval/weekly-eval-loop.js +0 -241
@@ -0,0 +1,418 @@
1
+ # Coding Agent Hooks Architecture
2
+
3
+ Date: 2026-05-28
4
+
5
+ ## Purpose
6
+
7
+ CTM runs several external coding agents as terminal sessions: Claude Code,
8
+ Codex, and Gemini CLI. Those agents own their terminal UI and provider runtime,
9
+ but CTM needs reliable lifecycle signals to render status, drive mobile status
10
+ lanes, preserve session context, and eventually trigger memory capture at the
11
+ right boundaries.
12
+
13
+ Hooks are the bridge. They are small user-approved entries in each agent's own
14
+ configuration that call back into CTM when an agent starts, stops, waits, or
15
+ uses tools. They complement, but do not replace, transcripts, PTY activity,
16
+ OpenTelemetry, and CTM's own session database.
17
+
18
+ ## External Contracts
19
+
20
+ ### Claude Code
21
+
22
+ Claude Code supports hooks in JSON settings files. Its docs describe a
23
+ read-only `/hooks` browser, user/project/local/plugin/session/built-in hook
24
+ sources, and command hooks that receive JSON on stdin. Common input fields
25
+ include `session_id`, `transcript_path`, `cwd`, and `permission_mode`.
26
+
27
+ CTM uses user-level `~/.claude/settings.json` so the integration applies to
28
+ Claude Code sessions launched through CTM without requiring project files to be
29
+ modified.
30
+
31
+ Source: https://code.claude.com/docs/en/hooks
32
+
33
+ ### Codex
34
+
35
+ Codex has a different contract. CTM uses two surfaces:
36
+
37
+ - OTLP log export, configured through an `[otel]` block.
38
+ - The top-level `notify = [...]` command array, which Codex invokes on agent
39
+ turn completion.
40
+
41
+ The Codex source defines `notify` as an optional command vector and shows it
42
+ invoked with an `agent-turn-complete` JSON payload. Current Codex config docs
43
+ also expose lifecycle-hook policy controls such as `allow_managed_hooks_only`
44
+ for managed environments.
45
+
46
+ Sources:
47
+
48
+ - https://github.com/openai/codex/blob/main/codex-rs/core/src/config/mod.rs
49
+ - https://github.com/openai/codex/blob/main/docs/config.md
50
+
51
+ ### Gemini CLI
52
+
53
+ Gemini CLI uses JSON settings files, with user-level config at
54
+ `~/.gemini/settings.json` and project-level config at `.gemini/settings.json`.
55
+ Its hook settings include events such as `BeforeAgent`, `AfterAgent`,
56
+ `Notification`, `SessionStart`, `SessionEnd`, `BeforeTool`, and `AfterTool`.
57
+ The hook-writing guide emphasizes the same basic execution model CTM relies on:
58
+ hooks receive JSON on stdin, should log to stderr, and should reserve stdout for
59
+ JSON hook output.
60
+
61
+ Sources:
62
+
63
+ - https://github.com/google-gemini/gemini-cli/blob/main/docs/reference/configuration.md
64
+ - https://github.com/google-gemini/gemini-cli/blob/main/docs/hooks/writing-hooks.md
65
+
66
+ ### OpenTelemetry
67
+
68
+ OpenTelemetry OTLP defines HTTP endpoints such as `/v1/logs` for log export.
69
+ The OTLP exporter configuration supports environment variables including
70
+ `OTEL_EXPORTER_OTLP_ENDPOINT` and `OTEL_EXPORTER_OTLP_PROTOCOL`; `http/json` is
71
+ a valid protocol value.
72
+
73
+ CTM uses this for low-latency agent status when an agent supports OTLP logs.
74
+
75
+ Sources:
76
+
77
+ - https://opentelemetry.io/docs/specs/otlp/
78
+ - https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/
79
+
80
+ ## Current CTM Implementation
81
+
82
+ ### UI
83
+
84
+ The AI Providers page has a **Coding Agents** tab. It checks:
85
+
86
+ - CLI availability through `/api/models/available-agents`.
87
+ - Hook install status through `/api/otel/status`.
88
+
89
+ The card state is derived in `public/index.html`:
90
+
91
+ - `Ready`: CLI detected and CTM hooks installed.
92
+ - `Enable live status`: CLI detected but CTM has not found the integration for
93
+ the current CTM port.
94
+ - `Not found`: CLI is not on PATH.
95
+ - `Path changed` or `Config needs attention`: cached path or config inspection
96
+ failed.
97
+
98
+ When coding agents are detected but hooks are missing, CTM shows one
99
+ **Enable live status** prompt for every detected runtime that needs the current
100
+ CTM port. The modal shows each target config path and a sanitized change
101
+ summary from `/api/otel/plan-install`, then applies the idempotent installer
102
+ only after the user approves. When hooks are already present, the card offers
103
+ **Refresh live status** for the same idempotent repair path.
104
+
105
+ The proactive prompt is allowed when the user opens the Coding Agents tab or
106
+ when a fresh coding-agent session emits `session.needsSetup`. Passive page load
107
+ still must not write config or install hooks.
108
+
109
+ Relevant code:
110
+
111
+ - `claude-task-manager/public/index.html`
112
+ - `_modelsCodingAgentStatusFor`
113
+ - `_ensureModelsAgentStatus`
114
+ - `installCodingAgentHooks`
115
+ - `renderModelsCodingAgentRoutes`
116
+
117
+ ### Installer
118
+
119
+ `claude-task-manager/lib/agent-hooks-installer.js` is the local authority for
120
+ config writes. It has a plan/apply split:
121
+
122
+ - `planInstall(agent, port)` reads the user's config and builds the proposed
123
+ next text.
124
+ - `install(agent, port)` applies the plan.
125
+ - `planUninstall(agent, port)` removes CTM-owned entries.
126
+ - `isInstalled(agent, port)` checks whether the current CTM integration marker
127
+ is present.
128
+
129
+ The installer is deliberately idempotent. Re-running install should avoid
130
+ duplicates, and uninstall should remove only CTM-owned entries while preserving
131
+ user-owned config.
132
+
133
+ Current target files:
134
+
135
+ - Claude Code: `~/.claude/settings.json`
136
+ - Codex: `~/.codex/config.toml`
137
+ - Gemini CLI: `~/.gemini/settings.json`
138
+
139
+ Current hook commands point at CTM scripts under `claude-task-manager/bin`:
140
+
141
+ - `claude-hook.js`
142
+ - `codex-notify.js`
143
+ - `gemini-hook.js`
144
+
145
+ ### Agent Presets
146
+
147
+ `claude-task-manager/lib/agent-presets.js` is the source of truth for each
148
+ agent's lifecycle events:
149
+
150
+ Claude Code:
151
+
152
+ - `SessionStart` -> `claude-hook start`
153
+ - `UserPromptSubmit` -> `claude-hook start`
154
+ - `Stop` -> `claude-hook stop`
155
+ - `Notification` -> `claude-hook idle`
156
+ - `PreToolUse` -> `claude-hook menu`
157
+
158
+ Codex:
159
+
160
+ - `notify` -> `codex-notify stop`
161
+ - OTLP env vars point logs at the CTM port.
162
+
163
+ Gemini CLI:
164
+
165
+ - `BeforeAgent` -> `gemini-hook start`
166
+ - `AfterAgent` -> `gemini-hook stop`
167
+ - `SessionEnd` -> `gemini-hook stop`
168
+ - `BeforeTool` -> `gemini-hook menu`
169
+
170
+ The same file also builds per-session environment variables, including
171
+ `CTM_SESSION_ID`, `CTM_PORT`, and, where supported, OTLP endpoint settings.
172
+
173
+ ### Server Ingress
174
+
175
+ CTM only accepts hook/OTLP ingress from loopback. The local server handles:
176
+
177
+ - `/v1/logs` and `/api/otlp/v1/logs` -> `telemetryReceiver.handleLogs`
178
+ - `/hook/claude/{start|stop|idle|menu}` -> `telemetryReceiver.hookClaude`
179
+ - `/hook/codex/stop` -> `telemetryReceiver.hookCodexStop`
180
+ - `/hook/gemini/{start|stop|menu}` -> `telemetryReceiver.hookGemini`
181
+
182
+ The same receiver then broadcasts `session.status` over CTM's existing websocket
183
+ fan-out. This is important: hooks enter through a small local ingress, but they
184
+ reuse the normal session status contract instead of creating a parallel UI
185
+ state model.
186
+
187
+ Relevant code:
188
+
189
+ - `claude-task-manager/server.js`
190
+ - hook/OTLP ingress near the local-only hook server block
191
+ - `/api/otel/status`, `/api/otel/plan-install`, `/api/otel/install`,
192
+ `/api/otel/uninstall`
193
+ - session creation watchdog that prompts setup only when hooks are missing
194
+ and the spawn is not a resume
195
+
196
+ ### Tests
197
+
198
+ Existing tests cover the safety properties that matter most:
199
+
200
+ - `claude-task-manager/tests/agent-hooks-installer.test.js`
201
+ - writes plausible Claude/Gemini settings
202
+ - writes Codex `[otel]` plus top-level `notify = [...]`
203
+ - install is idempotent
204
+ - uninstall preserves user-owned config
205
+ - legacy Codex `[notify]` section is repaired to the top-level array shape
206
+
207
+ - `claude-task-manager/tests/agent-presets.test.js`
208
+ - agent detection
209
+ - OTLP/env construction
210
+ - inherited session identity sanitation
211
+
212
+ ## End-to-End Flow
213
+
214
+ ```text
215
+ User opens AI Providers -> Coding Agents
216
+ |
217
+ +-- UI GET /api/models/available-agents
218
+ | -> CTM discovers claude/codex/gemini binaries
219
+ |
220
+ +-- UI GET /api/otel/status
221
+ -> CTM checks whether the relevant config contains CTM's current hook marker
222
+
223
+ User clicks Enable live status in the consent modal
224
+ |
225
+ +-- UI POST /api/otel/install?agent=<id>
226
+ -> agent-hooks-installer reads user config
227
+ -> patches only CTM-owned entries
228
+ -> writes the agent config file
229
+
230
+ User launches an agent through CTM
231
+ |
232
+ +-- server builds env with CTM_SESSION_ID and CTM_PORT
233
+ +-- for OTLP-capable agents, server injects OTLP endpoint env
234
+ +-- agent runs normally in its terminal
235
+
236
+ Agent lifecycle event happens
237
+ |
238
+ +-- provider hook invokes CTM script
239
+ +-- script posts JSON to localhost CTM hook endpoint
240
+ +-- telemetry-receiver maps event to CTM session status
241
+ +-- websocket broadcasts session.status
242
+ +-- desktop/mobile UI updates lanes, badges, and attention state
243
+ ```
244
+
245
+ ## Architectural Benefits
246
+
247
+ ### 1. Reliable Status Without Scraping Terminal Text
248
+
249
+ Terminal text is a weak status source. It changes with provider UI versions,
250
+ color themes, redraw timing, and terminal width. Hooks give CTM structured
251
+ signals at the lifecycle boundary: start, stop, idle, tool/menu, and agent
252
+ turn-complete.
253
+
254
+ CTM should still keep PTY and transcript fallbacks, but hooks reduce the amount
255
+ of brittle regex parsing needed for high-level state.
256
+
257
+ ### 2. Provider-Neutral Session State
258
+
259
+ Claude, Codex, and Gemini expose different mechanics. CTM normalizes them into
260
+ one internal contract: `session.status`. This lets the web UI, mobile UI,
261
+ queue, notifications, and future Wall-E memory capture depend on one local CTM
262
+ event stream instead of three provider-specific contracts.
263
+
264
+ ### 3. Low-Latency Mobile and Remote UX
265
+
266
+ The phone status page and desktop session list need to know when an agent is
267
+ actually running, waiting, or done. Hooks provide low-latency transitions that
268
+ do not require polling large transcripts or waiting for terminal text to settle.
269
+
270
+ This matters especially on mobile, where noisy lane movement and stale
271
+ `Running` badges are high-friction.
272
+
273
+ ### 4. Correct Ownership Boundary
274
+
275
+ The provider still owns execution, tool calls, permissions, and terminal UI.
276
+ CTM only receives lifecycle facts and local telemetry. That keeps CTM from
277
+ pretending it is the agent runtime, while still giving CTM enough signals to be
278
+ a good control plane.
279
+
280
+ ### 5. Future Memory Capture Boundary
281
+
282
+ Hooks are the natural point to trigger durable capture:
283
+
284
+ - `SessionStart`: link provider session ID to CTM session ID.
285
+ - `UserPromptSubmit` / `BeforeAgent`: mark a new work unit.
286
+ - `Stop` / `AfterAgent`: flush final transcript tail and summarize.
287
+ - `PreToolUse` / `BeforeTool`: detect approval/tool attention.
288
+ - Future compaction hooks: preserve memory before context disappears.
289
+
290
+ The existing `session-capture-foundation-design.md` already says hooks are
291
+ strong status signals but should not be the only source of truth. The better
292
+ architecture is "hooks as timing/evidence, transcripts as content, PTY as
293
+ fallback."
294
+
295
+ ## Hooks-Optional Runtime Contract
296
+
297
+ Coding-agent hooks are not required for a CTM session to work. They improve the
298
+ status signal, but the baseline runtime path is still the PTY/session stream:
299
+
300
+ - CTM creates the PTY and renders terminal output regardless of hook status.
301
+ - `statusHooks` tracks meaningful PTY activity through the internal
302
+ `SessionStateBus`, even when no project or global `.ctm-hooks.json` command is
303
+ configured.
304
+ - `waiting-for-input` and `session-resumed` websocket messages continue to
305
+ project running/waiting state through `SessionCapture` without a prior
306
+ `session.status` hook frame.
307
+ - The missing-hook watchdog only emits `session.needsSetup` onboarding. It does
308
+ not fabricate runtime status and does not block the session.
309
+
310
+ The intended degradation is therefore:
311
+
312
+ ```text
313
+ With hooks: provider hook/OTLP -> authoritative session.status -> UI
314
+ Without hooks: PTY/session stream -> state bus + terminal fallback -> UI
315
+ ```
316
+
317
+ If either path disappears, that is a regression. Keep regression coverage for
318
+ both so hook improvements never turn into a hard runtime dependency.
319
+
320
+ ## Consent and Safety Model
321
+
322
+ Installing hooks mutates persistent user-level files under the user's home
323
+ directory. That means the integration can affect future CLI sessions outside
324
+ the current CTM tab. It is useful, but it is also a trust boundary.
325
+
326
+ Therefore CTM should keep hook install user-approved. CTM can proactively
327
+ detect a missing integration and open the setup modal, but the persistent
328
+ config write still needs an explicit user action.
329
+
330
+ Required safety properties:
331
+
332
+ 1. Preview before write for advanced users.
333
+ 2. Idempotent install; no duplicate entries.
334
+ 3. CTM-owned marker for uninstall/repair.
335
+ 4. Preserve user-owned config and hooks.
336
+ 5. Localhost-only ingress.
337
+ 6. Clear "installed for this CTM port" semantics.
338
+ 7. Visible uninstall/disable path.
339
+ 8. No hook install during passive page load.
340
+ 9. Do not expose raw config contents through preview APIs.
341
+
342
+ ## Why CTM Should Not Auto-Install Hooks
343
+
344
+ There are three separate reasons.
345
+
346
+ First, it is a side effect outside the app workspace. The files are user-level
347
+ agent configs, not CTM-owned project files. Silent edits would violate the same
348
+ trust model that Claude/Codex/Gemini use for project trust and hook execution.
349
+
350
+ Second, hooks are executable persistence. A hook entry runs a command in future
351
+ agent sessions. CTM's entries are benign and local, but the class of action is
352
+ still security-sensitive. The UI should make the write explicit.
353
+
354
+ Third, the correct hook endpoint includes the CTM port. If a user runs multiple
355
+ CTM instances, auto-install on page load could race ports and rewrite a working
356
+ config for the wrong instance. User-initiated install gives the user control
357
+ over which CTM instance owns the integration.
358
+
359
+ ## UX Recommendations
360
+
361
+ 1. Use **Enable live status** for missing integrations and
362
+ **Refresh live status** for installed integrations.
363
+ - "Repair" implies breakage.
364
+ - Both actions use an idempotent reinstall for the current CTM port.
365
+
366
+ 2. Keep the setup preview in a consent modal.
367
+ - Use existing `/api/otel/plan-install`.
368
+ - Show target file path and a sanitized CTM-owned change summary.
369
+ - Do not send or render raw current/next config text in the browser.
370
+
371
+ 3. Add **Remove integration** when hooks are installed.
372
+ - Use existing `/api/otel/uninstall`.
373
+ - This makes the trust boundary reversible.
374
+
375
+ 4. Explain the status in product terms:
376
+ - CLI: "Can CTM launch this runtime?"
377
+ - Hooks: "Can this runtime report live state back to CTM?"
378
+ - Provider link: "Which model provider powers this runtime?"
379
+
380
+ 5. Keep provider config separate.
381
+ - Hooks do not configure API keys or default models.
382
+ - Provider cards configure model access.
383
+ - Coding Agent cards configure session runtime observability.
384
+
385
+ 6. Prefer user-level config by default, but expose the target.
386
+ - The current code writes user-level config.
387
+ - If project-scoped hooks are added later, the UI must make scope explicit.
388
+
389
+ ## Open Questions
390
+
391
+ 1. Should CTM support project-scoped hook installs for teams that do not want
392
+ user-level global hooks?
393
+ 2. Should "Ready" require both hooks and a successful live test event, or is
394
+ config presence enough?
395
+ 3. Should Codex move from `notify`-only completion hooks to newer managed
396
+ lifecycle hook config if/when the CLI exposes a stable user-level contract?
397
+ 4. Should Wall-E memory capture become a first-class hook subscriber, or should
398
+ it continue consuming normalized CTM session events?
399
+
400
+ ## Proposed North Star
401
+
402
+ Hooks should be treated as a local, consented observability layer for coding
403
+ agents. The architecture should stay provider-neutral:
404
+
405
+ ```text
406
+ Provider-specific hook/telemetry inputs
407
+ -> CTM local ingress
408
+ -> telemetry-receiver normalization
409
+ -> session.status + capture events
410
+ -> desktop/mobile UI, notifications, Wall-E memory, queues
411
+ ```
412
+
413
+ This keeps the model clean:
414
+
415
+ - Coding agents own execution.
416
+ - AI Providers own model access.
417
+ - CTM owns orchestration, status, mobile/desktop control surfaces, and durable
418
+ session evidence.
@@ -52,6 +52,26 @@ This filter belongs at the parser and `/api/session/messages` boundaries. UI
52
52
  surfaces can keep a defensive check for already-cached old rows, but desktop and
53
53
  phone should both converge on the normalized API result.
54
54
 
55
+ ## Codex User Echo Dedupe
56
+
57
+ Codex can record the same human prompt twice for one turn: once as a
58
+ `response_item` user message and again as an `event_msg.user_message`. CTM must
59
+ collapse that provider echo so Conversation, Review, search, and phone timelines
60
+ do not show duplicate user turns.
61
+
62
+ The dedupe key is **not** globally unique text. Long-lived Codex sessions often
63
+ repeat the same prompt days later, for example rerunning the same research skill
64
+ after follow-up design work. Those later prompts are distinct human turns and
65
+ must remain visible. The importer therefore dedupes only same-text user events
66
+ inside a short timestamp window. If the timestamp is missing, CTM falls back to
67
+ conservative same-text dedupe because it cannot prove the events are separate.
68
+
69
+ The Codex conversation importer records a parser version on
70
+ `session_conversations`. When this semantic contract changes, same-size Codex
71
+ caches with an older parser version must be eligible for full re-import; file
72
+ size alone is not enough to prove a cache is fresh. This avoids one-off DB edits
73
+ for historical sessions whose raw rollout still contains the correct prompt.
74
+
55
75
  ## Non-Starving Scheduling
56
76
 
57
77
  Background DB work can defer briefly while the user is actively interacting
@@ -0,0 +1,77 @@
1
+ # Google Workspace Auth Health
2
+
3
+ ## Problem
4
+
5
+ Google sign-in happens outside the CTM browser tab. After OAuth completes, the
6
+ setup page can still show an old "Google account needs reconnection" banner if
7
+ the page does not refresh its Wall-E credential state. The browser's Google
8
+ login state is not a valid source of truth for CTM; Wall-E must verify the
9
+ stored `gws` credentials and then update both setup UI and service alerts from
10
+ that verified state.
11
+
12
+ ## Source Of Truth
13
+
14
+ `/api/wall-e/gws/accounts` is the authoritative health endpoint for connected
15
+ Google accounts. It derives each account state by asking the bundled
16
+ `gws-workspace` setup module for usable credentials:
17
+
18
+ - `tokenValid: true` means Wall-E has a usable access token for that account.
19
+ - `reauthRequired: true` means the saved refresh credential is missing, expired,
20
+ or revoked.
21
+ - `authIssue` is a user-facing explanation of the credential problem.
22
+
23
+ The setup page must render the reconnection banner only from this endpoint. It
24
+ must not infer success from a browser Google cookie or from returning to the CTM
25
+ tab after OAuth.
26
+
27
+ ## Alert Reconciliation
28
+
29
+ Service alerts are persisted in Wall-E's `service_alerts` KV entry and surfaced
30
+ on the Wall-E panel and session pages. Google Workspace account alerts use this
31
+ stable service key:
32
+
33
+ ```text
34
+ google_workspace:<profile-id-or-default>:<lowercase-email>
35
+ ```
36
+
37
+ Whenever Wall-E proves an account is usable, it should clear only resolved
38
+ Google Workspace auth alerts for that same account. This mirrors the existing
39
+ Slack health model while keeping unrelated alerts, disabled-skill alerts, and
40
+ other providers intact.
41
+
42
+ Reconciliation happens at two boundaries:
43
+
44
+ 1. OAuth completion: `completeGoogleAuthFlow()` only completes after
45
+ `gwsSetup.getCredentials()` returns a usable access token, then clears the
46
+ account's stale `gws_reauth` alert.
47
+ 2. Health reads: `/api/wall-e/gws/accounts` opportunistically clears stale
48
+ auth alerts for every account it reports as usable, so any setup page refresh
49
+ self-heals old alert state.
50
+
51
+ ## Browser Refresh Contract
52
+
53
+ Setup should refresh connected services when the user returns from an external
54
+ OAuth window:
55
+
56
+ - `pageshow`
57
+ - `focus`
58
+ - visible `visibilitychange`
59
+ - `online`
60
+
61
+ These events only trigger a small debounced `/api/wall-e/gws/accounts` refresh.
62
+ The page still uses explicit OAuth flow polling while CTM owns the flow, but it
63
+ does not rely on blind background polling to repair stale UI.
64
+
65
+ The endpoint and browser fetch should use no-store/no-cache semantics because
66
+ credential health is live operational state, not a static catalog.
67
+
68
+ ## Tests
69
+
70
+ Coverage should prove:
71
+
72
+ - Google auth completion clears stale account-specific `gws_reauth` alerts only
73
+ after credentials are usable.
74
+ - Google alert clearing does not remove unrelated Google, Slack, or disabled
75
+ skill alerts.
76
+ - The setup page removes the reconnection banner when a foreground lifecycle
77
+ refresh sees the account become healthy.
@@ -12,6 +12,7 @@ CTM treats pasted screenshots as first-class attachments and shows compact promp
12
12
 
13
13
  - Terminal sessions: paste events and the macOS `Ctrl+V` compatibility path upload images and insert the compact token, for example `[Image #1]`. The token is what the user sees and edits in both Claude and Codex sessions. `Cmd+Shift+V` on macOS and `Ctrl+Shift+V` elsewhere intentionally paste the raw local path reference. The terminal context menu can copy all pasted image paths or URLs for the active session.
14
14
  - Terminal sessions backed by Claude Code or Codex use provider-native image handoff. CTM uploads and normalizes the browser clipboard image, then sends the normalized local image path as a bracketed paste to the PTY. The provider creates the real image attachment and renders its own compact `[Image #n]` chip, so the model receives image context while the terminal does not show raw paths.
15
+ - Terminal sessions backed by Claude Code or Codex also append durable image metadata when the prompt is submitted. CTM does not change the paste behavior: paste still inserts the compact token and keeps provider-native path handoff intact. At Enter/submit time, any unsent image attachments from the active input are appended once as `[Attached image: "..."]` or `[Attached images: "...", "..."]` before the newline reaches the PTY. This makes future Conversation/Review import able to resolve the image path even if the provider transcript only preserves terminal text.
15
16
  - Terminal text paste also normalizes CTM image references. If the clipboard contains `[Image #1: "/path/to/file.png"]`, a raw local image path, or an `/api/images/file/...` URL, default paste deduplicates repeated references and hands each local image path to provider-native attachment paste when possible.
16
17
  - Terminal image paste accepts browser clipboard files by `image/*` MIME type or by common image filename extension when the OS leaves the MIME type empty.
17
18
  - Wall-E sessions: pasted images become structured message attachments. The composer inserts `[Image #n]`; sending preserves the compact token in the message text and sends image data separately.
@@ -20,3 +21,15 @@ CTM treats pasted screenshots as first-class attachments and shows compact promp
20
21
  ## Provider Contract
21
22
 
22
23
  Compact tokens are UI references, not raw file paths. CTM keeps attachment metadata, normalized uploads, and copyable path/URL references beside the visible token. Provider adapters must not send only `[Image #n]` to a raw PTY. They should either send structured attachments, or, for Claude Code and Codex terminal sessions, trigger native image attachment by bracket-pasting the normalized local image path. Explicit path paste remains available for CLIs that require a visible local filesystem reference in the prompt text.
24
+
25
+ Submit-time metadata is a transcript durability layer, not a replacement for native provider image attachment. It must not run during paste, path-copy, or path-paste handling, and it must mark attachments as submitted or discarded so later prompts do not inherit stale image references.
26
+
27
+ ## Performance Contract
28
+
29
+ Image storage must not do large synchronous work on CTM's primary Node.js event loop.
30
+
31
+ - Browser uploads may arrive as buffers, but hashing must process large buffers in bounded chunks and yield between chunks.
32
+ - Screenshot capture must store the captured file through a streaming file path, then rename or copy it into the content-addressed image store. Do not synchronously read the screenshot back into a full buffer after `screencapture` exits.
33
+ - The shared image-store helpers are the boundary for this behavior: `saveImage()` handles in-memory uploads, while `saveImageFromFile()` handles captured or already-on-disk images.
34
+
35
+ This keeps terminal typing, WebSocket output flushes, and screenshot preview rendering responsive while large Retina screenshots are being stored.
@@ -0,0 +1,88 @@
1
+ # CTM iPad Web Preview
2
+
3
+ Status: implemented for local and staging checks
4
+ Date: 2026-05-19
5
+
6
+ ## Goal
7
+
8
+ Use `/ipad.html` to run the CTM mobile app inside an iPad-sized frame from any CTM server. This is a fast desktop-browser check for the iPad layout before testing on a physical iPad.
9
+
10
+ The preview is intentionally same-origin by default:
11
+
12
+ ```text
13
+ http://localhost:3456/ipad.html
14
+ frames
15
+ http://localhost:3456/m/
16
+ ```
17
+
18
+ When testing a staging/tunnel server, open that server's own preview page:
19
+
20
+ ```text
21
+ https://<staging-host>/ipad.html
22
+ ```
23
+
24
+ That keeps CTM cookies, device tokens, service worker scope, and API calls on the same origin as the mobile app.
25
+
26
+ ## Run A Safe Local Staging Instance
27
+
28
+ Use `bin/dev.sh --refresh` with a separate port and data directory so iPad testing has copied CTM/Wall-E data without mutating the primary CTM state:
29
+
30
+ ```bash
31
+ WALLE_DEV_DIR=/tmp/walle-dev-4456 \
32
+ DEV_CTM_PORT=4456 \
33
+ DEV_WALLE_PORT=4457 \
34
+ bash bin/dev.sh --refresh
35
+ ```
36
+
37
+ Open:
38
+
39
+ ```text
40
+ http://localhost:4456/ipad.html
41
+ ```
42
+
43
+ The source field defaults to `/m/`. Keep it there for normal testing. If the preview loads but has no sessions, restart with `--refresh`; that copies the current CTM and Wall-E databases into the staging data directory.
44
+
45
+ ## Preview Modes
46
+
47
+ `/ipad.html` includes four device presets:
48
+
49
+ - `Test Portrait`: `768 x 1024`, matching the automated tablet regression test.
50
+ - `Test Landscape`: `1024 x 768`, matching the automated split-workspace regression test.
51
+ - `11 Portrait`: `834 x 1194`, close to an 11-inch iPad CSS viewport.
52
+ - `11 Landscape`: `1194 x 834`, close to an 11-inch iPad landscape viewport.
53
+
54
+ Use `Reload` to reload only the framed mobile app. Use `Open` to launch the framed URL directly.
55
+
56
+ ## What This Catches
57
+
58
+ - Tablet breakpoint regressions.
59
+ - Horizontal overflow.
60
+ - Portrait single-column sizing.
61
+ - Landscape list/detail split layout.
62
+ - Detail pane modal-vs-region behavior.
63
+ - Composer and bottom navigation placement.
64
+ - Search and session-card density at iPad widths.
65
+
66
+ ## What Still Requires A Real iPad
67
+
68
+ The preview does not replace Safari-on-iPad validation. Always do one physical-device pass before shipping high-risk mobile changes because desktop browser framing does not fully emulate:
69
+
70
+ - iPad Safari viewport height changes when the software keyboard opens.
71
+ - PWA standalone mode.
72
+ - touch momentum scrolling and rubber-band edges.
73
+ - safe-area inset differences.
74
+ - iOS third-party cookie and passkey behavior.
75
+ - real camera/file-picker attachment flows.
76
+
77
+ ## Automated Companion Test
78
+
79
+ The existing mobile render suite covers the same core tablet breakpoints:
80
+
81
+ ```bash
82
+ npm --prefix claude-task-manager exec playwright test -- \
83
+ --config tests/rendering/playwright.config.js \
84
+ scenarios/mobile-pwa.spec.js \
85
+ -g "iPad|tablet|iPad preview"
86
+ ```
87
+
88
+ Use the automated test for regression gates and `/ipad.html` for quick visual inspection.