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,137 @@
1
+ 'use strict';
2
+
3
+ // Shared "user-prompt index" compute for the Queue Builder prompt-preview. Extracted from
4
+ // server.js so the SAME logic runs on the main thread (live connection, fallback) AND on
5
+ // the read-pool worker (read-only connection) — keeping the SELECT-all-user-rows + sort +
6
+ // exclusions + sha1-per-prompt fingerprint OFF the main event loop (Phase 1). It is a pure
7
+ // read: takes a db handle + already-resolved inputs (sourceIds, exclusion rows, a flag for
8
+ // whether the session has a Codex source) so the worker needs no owner/source resolution.
9
+ //
10
+ // Output is identical by construction to the previous inline path, so moving it off-thread
11
+ // (or falling back to it on main) can never change the prompt list.
12
+
13
+ const crypto = require('crypto');
14
+ const { sortTimelineMessagesInPlace } = require('./timeline-order');
15
+ const { isProviderGeneratedUserContextText } = require('./provider-user-context');
16
+
17
+ // Lazy so a require cycle in session-history (large) can't break worker boot.
18
+ let _isCodexSyntheticUserText = null;
19
+ function _codexSynthetic(text) {
20
+ if (!_isCodexSyntheticUserText) {
21
+ try { _isCodexSyntheticUserText = require('./session-history').isCodexSyntheticUserText; }
22
+ catch { _isCodexSyntheticUserText = () => false; }
23
+ }
24
+ return _isCodexSyntheticUserText(text);
25
+ }
26
+
27
+ function _normalizePromptVersionText(text) {
28
+ return String(text || '').replace(/\s+/g, ' ').trim().slice(0, 500);
29
+ }
30
+ function _promptVersionHash(input) {
31
+ return crypto.createHash('sha1').update(String(input || '')).digest('hex').slice(0, 16);
32
+ }
33
+ function _sessionMessageTextHash(text) {
34
+ return crypto.createHash('sha256').update(String(text || '').replace(/\s+/g, ' ').trim()).digest('hex');
35
+ }
36
+ function _msgText(m) { return (m && (m.text || m.content || m.message)) || ''; }
37
+ function _msgTs(m) { return (m && (m.timestamp || m.created_at || m.createdAt)) || ''; }
38
+
39
+ // Mirrors server.js _applySessionMessageExclusions, but takes already-loaded exclusion rows
40
+ // and the codex-synthetic decision as inputs (no DB / owner resolution needed here).
41
+ function applyExclusions(messages, { exclusionRows = [], filterCodexSynthetic = false } = {}) {
42
+ if (!Array.isArray(messages) || messages.length === 0) return messages || [];
43
+ const visible = messages.filter((msg) => {
44
+ const role = String(msg && msg.role || '').trim();
45
+ if (role !== 'user') return true;
46
+ const text = _msgText(msg);
47
+ if (isProviderGeneratedUserContextText(text)) return false;
48
+ if (filterCodexSynthetic && _codexSynthetic(text)) return false;
49
+ return true;
50
+ });
51
+ if (!Array.isArray(exclusionRows) || exclusionRows.length === 0) return visible;
52
+ const exact = new Set();
53
+ const textOnly = new Set();
54
+ for (const row of exclusionRows) {
55
+ const role = String(row && row.role || '').trim();
56
+ const hash = String(row && row.text_hash || '').trim();
57
+ const ts = String(row && row.timestamp || '').trim();
58
+ if (!hash) continue;
59
+ if (ts) exact.add(`${role}\0${ts}\0${hash}`);
60
+ else textOnly.add(`${role}\0${hash}`);
61
+ }
62
+ if (exact.size === 0 && textOnly.size === 0) return visible;
63
+ return visible.filter((msg) => {
64
+ const role = String(msg && msg.role || '').trim();
65
+ const ts = String(_msgTs(msg)).trim();
66
+ const hash = _sessionMessageTextHash(_msgText(msg));
67
+ return !exact.has(`${role}\0${ts}\0${hash}`) && !textOnly.has(`${role}\0${hash}`);
68
+ });
69
+ }
70
+
71
+ // Mirrors server.js _promptSummaryFromMessages.
72
+ function summarize(messages, sourceIds = []) {
73
+ const prompts = (Array.isArray(messages) ? messages : [])
74
+ .map((message, index) => ({
75
+ text: _normalizePromptVersionText(_msgText(message)),
76
+ timestamp: String(_msgTs(message) || ''),
77
+ index,
78
+ }))
79
+ .filter((p) => p.text);
80
+ const last = prompts.length ? prompts[prompts.length - 1] : null;
81
+ const promptFingerprint = prompts.length > 0
82
+ ? _promptVersionHash(prompts.map((p) => [p.index, _promptVersionHash(p.text), p.timestamp].join(':')).join('|'))
83
+ : '';
84
+ return {
85
+ sourceIds,
86
+ cacheAvailable: prompts.length > 0,
87
+ userPromptCount: prompts.length,
88
+ lastPromptPreview: last ? last.text.slice(0, 240) : '',
89
+ lastPromptTimestamp: last ? last.timestamp : '',
90
+ promptFingerprint,
91
+ };
92
+ }
93
+
94
+ // Which table holds the per-message render rows. The row store (session_message_rows) is the
95
+ // default on current installs; the legacy session_messages index has been RETIRED (dropped by
96
+ // the de-dup migration). Mirrors db.js `_messageFreshnessTable()` so the prompt compute reads the
97
+ // SAME table the freshness key is computed from — otherwise this SELECT throws "no such table:
98
+ // session_messages", the off-thread index returns empty, and every prompt poll falls back to the
99
+ // heavy main-thread timeline projection (the multi-second apiSessionPrompts input-box freeze).
100
+ // Column names differ: the row store uses text/timestamp; the legacy table used content/created_at.
101
+ function _promptRowsSource(d) {
102
+ let hasRows = false;
103
+ try { hasRows = !!d.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_message_rows'").get(); }
104
+ catch { hasRows = false; }
105
+ return hasRows
106
+ ? { table: 'session_message_rows', cols: 'role, text AS text, timestamp AS timestamp' }
107
+ : { table: 'session_messages', cols: 'role, content AS text, created_at AS timestamp' };
108
+ }
109
+
110
+ // Load the raw user-prompt rows for the given source ids from the message index, ordered.
111
+ function loadUserPromptRows(d, sourceIds = []) {
112
+ const src = _promptRowsSource(d);
113
+ const stmt = d.prepare(
114
+ `SELECT ${src.cols}
115
+ FROM ${src.table}
116
+ WHERE ctm_session_id = ? AND role = 'user'
117
+ ORDER BY message_index ASC`
118
+ );
119
+ const prompts = [];
120
+ for (const id of (Array.isArray(sourceIds) ? sourceIds : [])) {
121
+ for (const row of stmt.all(String(id))) {
122
+ prompts.push({ role: row.role, text: row.text || '', timestamp: row.timestamp || '' });
123
+ }
124
+ }
125
+ sortTimelineMessagesInPlace(prompts);
126
+ return prompts;
127
+ }
128
+
129
+ // The whole index-source compute: load rows → exclusions → summary. Returns the filtered
130
+ // user-prompt messages + the summary. Runs on the read-pool worker (off main) or on main.
131
+ function computeUserPromptIndex(d, { sourceIds = [], exclusionRows = [], filterCodexSynthetic = false } = {}) {
132
+ const raw = loadUserPromptRows(d, sourceIds);
133
+ const messages = applyExclusions(raw, { exclusionRows, filterCodexSynthetic });
134
+ return { messages, summary: summarize(messages, sourceIds) };
135
+ }
136
+
137
+ module.exports = { computeUserPromptIndex, loadUserPromptRows, applyExclusions, summarize };
@@ -1,11 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const fs = require('fs');
4
+ const path = require('path');
4
5
  const {
5
6
  canResumeAgent,
6
7
  getResumeSpec: defaultGetResumeSpec,
7
8
  normalizeAgentType,
8
9
  } = require('./agent-capabilities');
10
+ const { resolveClaudeResumeCwd } = require('./resume-preflight');
11
+ const { normalizeCwd, samePath } = require('./resume-cwd');
9
12
 
10
13
  function normalizeArgs(args) {
11
14
  if (Array.isArray(args)) return args;
@@ -185,6 +188,55 @@ function resolveRestoreArgsFromAgentSessions({
185
188
  };
186
189
  }
187
190
 
191
+ function resolveRestoreCwdFromAgentSession({
192
+ task,
193
+ row,
194
+ agentType,
195
+ fsExists = fs.existsSync,
196
+ fsStat = fs.statSync,
197
+ homeDir,
198
+ claudeConfigDir,
199
+ } = {}) {
200
+ const normalizedAgentType = normalizeAgentType(agentType || task?.type || task?.cmd);
201
+ const fallbackCwd = normalizeCwd(task?.cwd || '');
202
+ if (normalizedAgentType !== 'claude' || !row) {
203
+ return {
204
+ cwd: fallbackCwd,
205
+ changed: false,
206
+ reason: '',
207
+ };
208
+ }
209
+
210
+ const jsonlPath = String(row.jsonl_path || '').trim();
211
+ const transcriptPath = jsonlPath || (
212
+ row.agent_project_dir && row.agent_session_id
213
+ ? path.join(row.agent_project_dir, `${row.agent_session_id}.jsonl`)
214
+ : ''
215
+ );
216
+ if (!transcriptPath) {
217
+ return { cwd: fallbackCwd, changed: false, reason: '' };
218
+ }
219
+
220
+ const result = resolveClaudeResumeCwd({
221
+ cwd: fallbackCwd,
222
+ projectPath: row.project_path || task?.project_path || '',
223
+ agentRow: row,
224
+ transcriptPath,
225
+ fsExists,
226
+ fsStat,
227
+ homeDir,
228
+ claudeConfigDir,
229
+ });
230
+ return {
231
+ cwd: result.cwd || fallbackCwd,
232
+ changed: !!(result.changed && result.cwd && !samePath(result.cwd, fallbackCwd)),
233
+ reason: result.reason || '',
234
+ blocked: !!result.blocked,
235
+ transcriptProjectDir: result.transcriptProjectDir || '',
236
+ cwdProjectDir: result.cwdProjectDir || '',
237
+ };
238
+ }
239
+
188
240
  function resolveCodexLinkRestoreArgs(codexLink, getResumeSpec = defaultGetResumeSpec) {
189
241
  const agentSessionId = String(codexLink?.agentSessionId || '').trim();
190
242
  if (!agentSessionId) return null;
@@ -201,6 +253,7 @@ function resolveCodexLinkRestoreArgs(codexLink, getResumeSpec = defaultGetResume
201
253
  module.exports = {
202
254
  orderedAgentRows,
203
255
  resolveCodexLinkRestoreArgs,
256
+ resolveRestoreCwdFromAgentSession,
204
257
  resumeSessionIdForRow,
205
258
  selectRestoreAgentSession,
206
259
  resolveRestoreArgsFromAgentSessions,
@@ -20,13 +20,13 @@ const LANE_DEFS = [
20
20
  },
21
21
  {
22
22
  id: 'needs_user',
23
- title: 'Needs User',
23
+ title: 'Needs You',
24
24
  description: 'Approvals, questions, blockers, or failed work that need operator attention.',
25
25
  },
26
26
  {
27
27
  id: 'continue_later',
28
- title: 'Continue Later',
29
- description: 'Idle sessions worth preserving for context reuse.',
28
+ title: 'Ready',
29
+ description: 'Idle sessions ready to resume when this preserved context is useful.',
30
30
  },
31
31
  ];
32
32
 
@@ -208,12 +208,13 @@ function ageLabel(now, value) {
208
208
  }
209
209
 
210
210
  function normalizeStatus(status) {
211
- const text = String(status || '').toLowerCase();
211
+ const text = String(status || '').toLowerCase().replace(/[-\s]+/g, '_');
212
212
  if (!text) return 'unknown';
213
- if (text === 'busy') return 'running';
213
+ if (text === 'busy' || text === 'active' || text === 'working' || text === 'thinking') return 'running';
214
+ if (text === 'restoring' || text === 'resuming' || text === 'restore_starting' || text === 'restarting') return 'resuming';
214
215
  if (text === 'waiting_input') return 'waiting_input';
215
- if (text === 'waiting-for-input') return 'waiting_input';
216
- if (['running', 'waiting', 'idle', 'exited', 'unknown'].includes(text)) return text;
216
+ if (text === 'waiting_for_input') return 'waiting_input';
217
+ if (['running', 'resuming', 'waiting', 'idle', 'exited', 'unknown'].includes(text)) return text;
217
218
  return text;
218
219
  }
219
220
 
@@ -263,21 +264,16 @@ function inferProviderFromAgent(agent) {
263
264
 
264
265
  function isWalleOwnedSession(session) {
265
266
  if (!session || typeof session !== 'object') return false;
267
+ if (session.walle_owned === true || session.walleOwned === true) return true;
268
+ if (session.native_walle_session === true || session.nativeWalleSession === true) return true;
266
269
  const explicitProvider = normalizeProvider(session.provider || session.providerId || session._providerId);
267
270
  if (explicitProvider === 'walle') return true;
268
271
  const explicitAgent = inferProviderFromAgent(session.agentType || session.agent || session.type);
269
272
  if (explicitAgent === 'walle') return true;
270
273
 
271
- const label = String(session.label || session.title || '').trim().toLowerCase();
274
+ // Labels, branches, and worktree names describe the task, not the runtime owner.
272
275
  const cmd = String(session.cmd || '').trim().toLowerCase();
273
- const branch = String(session.branch || session.gitBranch || session.worktreeStatus?.branch || '').trim().toLowerCase();
274
- const worktreePath = String(session.worktree_path || session.worktreePath || session.worktreeStatus?.worktreePath || session.cwd || '').trim().toLowerCase();
275
- const worktreeName = String(session.worktreeStatus?.worktreeName || worktreePath.split('/').filter(Boolean).pop() || '').trim().toLowerCase();
276
-
277
- if (cmd === 'walle coding' || cmd.startsWith('walle coding ')) return true;
278
- if (/^(wall-?e|walle)\s+coding\b/.test(label)) return true;
279
- if (worktreeName === 'walle-coding' || worktreeName.startsWith('walle-coding-')) return true;
280
- if (branch.includes('walle-coding')) return true;
276
+ if (cmd === 'walle' || cmd === 'walle coding' || cmd.startsWith('walle coding ')) return true;
281
277
  return false;
282
278
  }
283
279
 
@@ -344,7 +340,10 @@ function lookupForSession(index, session) {
344
340
 
345
341
  function isBlockingWaitingReason(reason) {
346
342
  const text = String(reason || '').toLowerCase();
347
- return text === 'approval' || text === 'choice';
343
+ return text === 'approval' ||
344
+ text === 'choice' ||
345
+ /\bapproval\b/.test(text) ||
346
+ /\bpermission\b/.test(text);
348
347
  }
349
348
 
350
349
  function hasUnsubmittedWaitingInput(session) {
@@ -364,6 +363,23 @@ function isStaleNonBlockingWaiting(session, status, summary, now = Date.now()) {
364
363
  return !!(waitingAt && (now - waitingAt) > WAITING_INPUT_STALE_MS);
365
364
  }
366
365
 
366
+ function attentionDismissalForSession(session, now = Date.now()) {
367
+ const dismissedAt = normalizeObservedTimeMs(
368
+ session?.attentionDismissedAt ?? session?.attention_dismissed_at,
369
+ now
370
+ );
371
+ const dismissedInputAt = normalizeObservedTimeMs(
372
+ session?.attentionDismissedInputAt ?? session?.attention_dismissed_input_at,
373
+ now
374
+ );
375
+ const lastUserPromptInputAt = normalizeObservedTimeMs(
376
+ session?.lastUserPromptInputAt ?? session?.last_user_prompt_input_at,
377
+ now
378
+ );
379
+ const active = dismissedAt > 0 && (!lastUserPromptInputAt || lastUserPromptInputAt <= dismissedInputAt);
380
+ return { dismissedAt, dismissedInputAt, lastUserPromptInputAt, active };
381
+ }
382
+
367
383
  function statusForSession(session, status, summary, now = Date.now()) {
368
384
  if (session?.waitingForInput && !isStaleNonBlockingWaiting(session, status, summary, now)) return 'waiting_input';
369
385
  const candidates = [
@@ -406,10 +422,17 @@ function standupStatusForSession(session, status, summary, now = Date.now()) {
406
422
  function worktreeEvidence(worktree) {
407
423
  if (!worktree) return '';
408
424
  const dirtyFiles = Number(worktree.dirtyFiles || 0);
409
- const unmergedCommits = Number(worktree.unmergedCommits || 0);
425
+ const trackedDirtyFiles = worktree.trackedDirtyFiles != null
426
+ ? Number(worktree.trackedDirtyFiles || 0)
427
+ : Math.max(0, dirtyFiles - Number(worktree.untrackedFiles || 0));
428
+ const untrackedFiles = Number(worktree.untrackedFiles || 0);
429
+ const localCommits = worktree.isMain
430
+ ? Number(worktree.unpushedCommits || worktree.ahead || worktree.unmergedCommits || 0)
431
+ : Number(worktree.unmergedCommits || 0);
410
432
  const parts = [];
411
- if (dirtyFiles) parts.push(`${dirtyFiles} dirty`);
412
- if (unmergedCommits) parts.push(`${unmergedCommits} unmerged`);
433
+ if (trackedDirtyFiles) parts.push(`${trackedDirtyFiles} dirty`);
434
+ if (untrackedFiles) parts.push(`${untrackedFiles} untracked`);
435
+ if (localCommits) parts.push(worktree.isMain ? `${localCommits} local` : `${localCommits} unmerged`);
413
436
  if (!parts.length && worktree.summary) parts.push(worktree.summary);
414
437
  return parts.length ? `worktree ${parts.join(', ')}` : '';
415
438
  }
@@ -418,8 +441,12 @@ function hasReviewableWork(session, summaryText, progress) {
418
441
  const worktree = session?.worktreeStatus || session?.worktree || null;
419
442
  if (worktree) {
420
443
  if (worktree.needsAttention) return true;
421
- if (Number(worktree.dirtyFiles || 0) > 0) return true;
444
+ const trackedDirtyFiles = worktree.trackedDirtyFiles != null
445
+ ? Number(worktree.trackedDirtyFiles || 0)
446
+ : Math.max(0, Number(worktree.dirtyFiles || 0) - Number(worktree.untrackedFiles || 0));
447
+ if (trackedDirtyFiles > 0) return true;
422
448
  if (Number(worktree.unmergedCommits || 0) > 0) return true;
449
+ if (Number(worktree.unpushedCommits || 0) > 0) return true;
423
450
  }
424
451
  const text = `${summaryText || ''} ${progressText(progress)}`.toLowerCase();
425
452
  return /\b(done|completed|complete|verified|passed|ready for review|all work done)\b/.test(text);
@@ -539,6 +566,7 @@ function baseEvidence({ session, status, summary, now, intentText, progress, goa
539
566
  const evidence = [];
540
567
  if (status === 'waiting_input') evidence.push('waiting input');
541
568
  else if (status === 'waiting') evidence.push('waiting');
569
+ else if (status === 'resuming') evidence.push('resuming');
542
570
  else if (status === 'running') evidence.push('running');
543
571
  const branch = session?.branch || session?.gitBranch || session?.worktreeStatus?.branch || '';
544
572
  if (branch) evidence.push(`branch ${branch}`);
@@ -576,10 +604,29 @@ function latestActivity(session, summary, now = Date.now()) {
576
604
  return latestObservedTimeMs(values, now);
577
605
  }
578
606
 
607
+ function latestAgentOutput(session, summary, status, now = Date.now()) {
608
+ const recentAssistantTurns = Array.isArray(summary?.recentTurns)
609
+ ? summary.recentTurns
610
+ .filter(turn => turn?.role === 'assistant')
611
+ .map(turn => turn.timestamp || turn.updatedAt || turn.createdAt)
612
+ : [];
613
+ const values = [
614
+ summary?.progress?.updatedAt,
615
+ summary?.progress?.timestamp,
616
+ session?.lastAgentOutputAt,
617
+ session?.lastPtyActivity,
618
+ status?.lastAgentOutputAt,
619
+ status?.lastPtyActivity,
620
+ ...(String(status?.status || '').toLowerCase() === 'running' ? [status?.lastActivity] : []),
621
+ ...recentAssistantTurns,
622
+ ];
623
+ return latestObservedTimeMs(values, now);
624
+ }
625
+
579
626
  function classifySessionStandup(session, signals = {}, now = Date.now()) {
580
627
  const summary = signals.summary || {};
581
628
  const streamStatus = signals.status || {};
582
- const status = standupStatusForSession(session, streamStatus, summary, now);
629
+ let status = standupStatusForSession(session, streamStatus, summary, now);
583
630
  const goal = goalForSummary(session, summary);
584
631
  const intentString = goal.text;
585
632
  const progress = summary.progress || '';
@@ -587,6 +634,7 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
587
634
  const progressString = progressInfo.text;
588
635
  const summaryText = valueText(summary.summary) || intentString;
589
636
  const lastActivityMs = latestActivity(session, summary, now);
637
+ const lastAgentOutputMs = latestAgentOutput(session, summary, streamStatus, now);
590
638
  const ageMs = lastActivityMs ? Math.max(0, now - lastActivityMs) : null;
591
639
  const waitingReason = session?.waitingReason || streamStatus?.reason || summary?.statusEvidence?.[0] || '';
592
640
  const reviewable = hasReviewableWork(session, summaryText, progress);
@@ -598,6 +646,7 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
598
646
  const warning = attentionSeverity === 'warning';
599
647
  const isWaiting = status === 'waiting_input' || status === 'waiting';
600
648
  const isRunning = status === 'running' || status === 'busy';
649
+ const isResuming = status === 'resuming';
601
650
 
602
651
  let lane = 'continue_later';
603
652
  let actionKind = 'resume';
@@ -620,7 +669,13 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
620
669
  actionKind = 'watch';
621
670
  actionLabel = 'Open';
622
671
  recommendation = 'Work is still running; no operator action is needed yet.';
623
- confidence = status === 'running' ? 'high' : 'medium';
672
+ confidence = 'high';
673
+ } else if (isResuming) {
674
+ lane = 'continue_later';
675
+ actionKind = 'watch';
676
+ actionLabel = 'Open';
677
+ recommendation = 'CTM is restoring this session after restart; it will return to idle unless new provider output arrives.';
678
+ confidence = 'medium';
624
679
  } else if (failed) {
625
680
  lane = 'needs_user';
626
681
  actionKind = 'investigate';
@@ -658,12 +713,34 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
658
713
  evidence.unshift('warning');
659
714
  }
660
715
 
716
+ const dismissal = attentionDismissalForSession(session, now);
717
+ let dismissedToIdle = false;
718
+ if (dismissal.active && lane === 'needs_user') {
719
+ dismissedToIdle = true;
720
+ lane = 'continue_later';
721
+ status = 'idle';
722
+ actionKind = 'resume';
723
+ actionLabel = 'Open';
724
+ recommendation = 'Dismissed from Needs You; open when ready or send a new prompt to continue.';
725
+ confidence = confidence === 'high' ? 'medium' : confidence;
726
+ if (!evidence.some(item => String(item || '').toLowerCase() === 'dismissed')) {
727
+ evidence.unshift('dismissed');
728
+ }
729
+ }
730
+
661
731
  const title = truncateText(
662
732
  session?.label || summary?.displayPrompt || summary?.lastPrompt || intentString || session?.id || 'Session',
663
733
  90
664
734
  );
665
735
  const provider = inferSessionProvider(session);
666
736
  const modelProvider = inferSessionModelProvider(session);
737
+ const nativeWalleSession = session?.native_walle_session === true
738
+ || session?.nativeWalleSession === true
739
+ || session?.type === 'walle';
740
+ const walleOwned = session?.walle_owned === true
741
+ || session?.walleOwned === true
742
+ || isWalleOwnedSession(session);
743
+ const sessionType = session?.session_type || session?.sessionType || session?.runtime_type || session?.runtimeType || session?.type || '';
667
744
 
668
745
  const card = {
669
746
  id: session?.id || session?.sessionId || '',
@@ -671,6 +748,16 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
671
748
  title,
672
749
  agent: session?.agentType || session?.agent || session?.type || 'session',
673
750
  provider,
751
+ type: session?.type || sessionType || '',
752
+ session_type: sessionType || '',
753
+ runtime_type: session?.runtime_type || session?.runtimeType || session?.type || '',
754
+ walle_owned: !!walleOwned,
755
+ walleOwned: !!walleOwned,
756
+ native_walle_session: !!nativeWalleSession,
757
+ nativeWalleSession: !!nativeWalleSession,
758
+ agentMode: session?.agentMode || session?.agent_mode || null,
759
+ agentKind: session?.agentKind || session?.agent_kind || (walleOwned && !nativeWalleSession ? 'walle-coding' : null),
760
+ taskType: session?.taskType || session?.task_type || (walleOwned && !nativeWalleSession ? 'coding' : null),
674
761
  modelProvider,
675
762
  model: inferSessionModel(session),
676
763
  cwd: session?.cwd || '',
@@ -696,8 +783,16 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
696
783
  progress: progressString,
697
784
  createdAt: toIso(session?.createdAt, now),
698
785
  lastActivity: toIso(lastActivityMs, now),
786
+ lastAgentOutputAt: toIso(lastAgentOutputMs, now),
787
+ attentionDismissedAt: toIso(dismissal.dismissedAt, now),
788
+ attentionDismissedInputAt: toIso(dismissal.dismissedInputAt, now),
789
+ lastUserPromptInputAt: toIso(dismissal.lastUserPromptInputAt, now),
790
+ attentionDismissedActive: dismissal.active,
791
+ dismissedToIdle,
792
+ dismissedToReady: dismissedToIdle,
699
793
  ageMs,
700
794
  worktree: session?.worktreeStatus || session?.worktree || null,
795
+ worktreeStatus: session?.worktreeStatus || session?.worktree || null,
701
796
  capabilities: session?.agentCapabilities || session?.capabilities || {},
702
797
  priority: LANE_ORDER.get(lane) ?? 99,
703
798
  };
@@ -709,6 +804,9 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
709
804
 
710
805
  function sortCards(a, b) {
711
806
  if (a.priority !== b.priority) return a.priority - b.priority;
807
+ const agentA = toMs(a.lastAgentOutputAt);
808
+ const agentB = toMs(b.lastAgentOutputAt);
809
+ if (agentA !== agentB) return (agentB || 0) - (agentA || 0);
712
810
  const actionOrder = {
713
811
  approval_needed: 0,
714
812
  needs_input: 1,
@@ -776,7 +874,9 @@ module.exports = {
776
874
  isWalleOwnedSession,
777
875
  standupStatusForSession,
778
876
  latestActivity,
877
+ latestAgentOutput,
779
878
  truncateText,
780
879
  hasFailureSignal,
880
+ attentionDismissalForSession,
781
881
  },
782
882
  };
@@ -6,6 +6,7 @@
6
6
  // - onOutput(sessionId) — PTY produced output → mark busy; schedule idle debounce
7
7
  // - onApprovalDetected(sessionId) — approval prompt detected → waiting_input
8
8
  // - onApprovalResolved(sessionId) — prompt handled → busy (until idle debounce fires)
9
+ // - clearWaitingInput(sessionId) — stale/non-current wait evidence cleared → idle
9
10
  // - reset(sessionId) — forget this session (on close)
10
11
  //
11
12
  // Output: fires `statechange` events via the EventEmitter interface. Consumers
@@ -51,6 +52,12 @@ class SessionStateBus extends EventEmitter {
51
52
  return this._states.get(sessionId)?.state || null;
52
53
  }
53
54
 
55
+ getSnapshot(sessionId) {
56
+ this._reconcileExpiredBusy(sessionId);
57
+ const cur = this._states.get(sessionId);
58
+ return cur ? { ...cur } : null;
59
+ }
60
+
54
61
  register(sessionId, providerId) {
55
62
  if (this._states.has(sessionId)) return;
56
63
  this._states.set(sessionId, {
@@ -166,6 +173,13 @@ class SessionStateBus extends EventEmitter {
166
173
  this._scheduleIdle(sessionId);
167
174
  }
168
175
 
176
+ clearWaitingInput(sessionId) {
177
+ const cur = this._states.get(sessionId);
178
+ if (!cur || cur.state !== 'waiting_input') return;
179
+ this._cancelIdleTimer(sessionId);
180
+ this._transition(sessionId, 'idle', { providerId: cur.providerId || '' });
181
+ }
182
+
169
183
  reset(sessionId) {
170
184
  this._cancelIdleTimer(sessionId);
171
185
  this._states.delete(sessionId);