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,356 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { parseAgentWorktreePath } = require('./resume-cwd');
6
+
7
+ function normalizePath(value) {
8
+ const raw = String(value || '').trim();
9
+ if (!raw) return '';
10
+ const expanded = raw.replace(/^~(?=\/|$)/, process.env.HOME || '~');
11
+ return path.normalize(path.isAbsolute(expanded) ? expanded : path.resolve(expanded));
12
+ }
13
+
14
+ // realpathSync(dir) does an lstat() per path component, and on a deep iCloud/Dropbox
15
+ // CloudStorage path each lstat can be a slow userspace round-trip. resolveSessionWorkspaceBinding
16
+ // calls safeRealpath multiplicatively — findWorktreeByPath realpaths EVERY worktree and
17
+ // re-realpaths the same candidatePath once per worktree, per candidate, per session — so a
18
+ // single session-list broadcast (≈17 sessions × ≈36 worktrees) fired tens of thousands of
19
+ // lstat syscalls on the main thread (the dominant non-idle frame in the CPU profile: `lstat`
20
+ // 95%-attributed to safeRealpath). Worktree/cwd canonical paths are stable for a process, so
21
+ // memoize with a short TTL: a cache hit collapses the storm to ~one realpathSync per distinct
22
+ // path per TTL window, while the TTL still lets a path that is created/moved re-resolve.
23
+ const _REALPATH_TTL_MS = Number(process.env.CTM_REALPATH_CACHE_TTL_MS) || 60000;
24
+ const _REALPATH_CACHE_MAX = 4000;
25
+ const _realpathCache = new Map(); // normalized input -> { real, at }
26
+
27
+ function safeRealpath(value) {
28
+ const normalized = normalizePath(value);
29
+ if (!normalized) return '';
30
+ const now = Date.now();
31
+ const hit = _realpathCache.get(normalized);
32
+ if (hit && (now - hit.at) < _REALPATH_TTL_MS) return hit.real;
33
+ let real;
34
+ try { real = fs.realpathSync(normalized); }
35
+ catch { real = normalized; }
36
+ // Bound the cache (FIFO eviction) so a long-lived process with churning paths can't grow it.
37
+ if (_realpathCache.size >= _REALPATH_CACHE_MAX) {
38
+ const oldest = _realpathCache.keys().next().value;
39
+ if (oldest !== undefined) _realpathCache.delete(oldest);
40
+ }
41
+ _realpathCache.set(normalized, { real, at: now });
42
+ return real;
43
+ }
44
+
45
+ // Test/maintenance hook: drop all memoized realpaths (e.g. after a worktree move in a test).
46
+ function _clearRealpathCache() { _realpathCache.clear(); }
47
+
48
+ function normalizeBranch(value) {
49
+ return String(value || '').trim().replace(/^refs\/heads\//, '');
50
+ }
51
+
52
+ function isMainBranch(value) {
53
+ const branch = normalizeBranch(value);
54
+ return branch === 'main' || branch === 'master';
55
+ }
56
+
57
+ function normalizeWorktree(worktree) {
58
+ if (!worktree) return null;
59
+ const wtPath = normalizePath(worktree.path || worktree.worktreePath || '');
60
+ const branch = normalizeBranch(worktree.branch || '');
61
+ if (!wtPath && !branch) return null;
62
+ return {
63
+ ...worktree,
64
+ path: wtPath,
65
+ realPath: safeRealpath(wtPath),
66
+ branch,
67
+ worktreeName: worktree.worktreeName || path.basename(wtPath || branch),
68
+ isMain: worktree.isMain === true || isMainBranch(branch) || worktree.state === 'primary',
69
+ };
70
+ }
71
+
72
+ function worktreePathMatches(wt, candidatePath) {
73
+ if (!wt || !candidatePath) return false;
74
+ const candidate = safeRealpath(candidatePath);
75
+ const wtPath = wt.realPath || safeRealpath(wt.path);
76
+ return !!(candidate && wtPath && (candidate === wtPath || candidate.startsWith(wtPath + path.sep)));
77
+ }
78
+
79
+ function findWorktreeByPath(worktrees, candidatePath) {
80
+ const matches = (worktrees || [])
81
+ .map(normalizeWorktree)
82
+ .filter(Boolean)
83
+ .filter(wt => worktreePathMatches(wt, candidatePath))
84
+ .sort((a, b) => String(b.path || '').length - String(a.path || '').length);
85
+ return matches[0] || null;
86
+ }
87
+
88
+ function findWorktreesByBranch(worktrees, branch) {
89
+ const clean = normalizeBranch(branch);
90
+ if (!clean) return [];
91
+ return (worktrees || [])
92
+ .map(normalizeWorktree)
93
+ .filter(Boolean)
94
+ .filter(wt => wt.branch === clean);
95
+ }
96
+
97
+ function pushCandidate(candidates, source, candidatePath, branch, priority, extra = {}) {
98
+ const normalized = normalizePath(candidatePath);
99
+ if (!normalized) return;
100
+ candidates.push({
101
+ source,
102
+ path: normalized,
103
+ branch: normalizeBranch(branch),
104
+ priority,
105
+ ...extra,
106
+ });
107
+ }
108
+
109
+ function runtimeContextFromSession(session) {
110
+ const raw = session?._runtimeWorkContext || session?.runtimeWorkContext || session?.runtime_work_context || null;
111
+ if (!raw || typeof raw !== 'object') return null;
112
+ const cwd = normalizePath(raw.cwd || raw.currentDir || raw.current_dir || raw.path || '');
113
+ const worktreePath = normalizePath(raw.worktreePath || raw.worktree_path || raw.gitWorktree || raw.git_worktree || '');
114
+ if (!cwd && !worktreePath) return null;
115
+ return {
116
+ cwd,
117
+ worktreePath,
118
+ branch: normalizeBranch(raw.branch || raw.gitBranch || raw.git_branch || ''),
119
+ source: String(raw.source || 'runtime.current').trim() || 'runtime.current',
120
+ confidence: String(raw.confidence || 'current').trim() || 'current',
121
+ observedAt: Number(raw.observedAt || raw.observed_at || raw.timestamp || 0) || 0,
122
+ };
123
+ }
124
+
125
+ function identityCandidates(identity) {
126
+ const out = [];
127
+ if (!identity || typeof identity !== 'object') return out;
128
+ const ctm = identity.ctm || null;
129
+ if (ctm) {
130
+ pushCandidate(out, 'ctm.project_path', ctm.project_path, ctm.git_branch || '', 30);
131
+ pushCandidate(out, 'ctm.cwd', ctm.cwd, ctm.git_branch || '', 35);
132
+ }
133
+ const agents = Array.isArray(identity.agents) ? identity.agents : [];
134
+ agents.forEach((agent, idx) => {
135
+ pushCandidate(out, `agent_sessions[${idx}].project_path`, agent?.project_path, agent?.git_branch, 40 + idx);
136
+ });
137
+ return out;
138
+ }
139
+
140
+ function makeBinding(fields) {
141
+ const branch = normalizeBranch(fields.branch || '');
142
+ const worktreePath = normalizePath(fields.worktreePath || '');
143
+ const runtimeBranch = normalizeBranch(fields.runtimeBranch || '');
144
+ const isMain = fields.isMain != null ? !!fields.isMain : isMainBranch(branch);
145
+ const binding = {
146
+ status: fields.status || 'unknown',
147
+ branch,
148
+ displayBranch: branch && !isMain ? branch : '',
149
+ worktreePath,
150
+ worktreeName: fields.worktreeName || path.basename(worktreePath || branch || ''),
151
+ isMain,
152
+ source: fields.source || '',
153
+ confidence: fields.confidence || 'none',
154
+ runtimeBranch,
155
+ runtimeCwd: normalizePath(fields.runtimeCwd || ''),
156
+ runtimeWorktreePath: normalizePath(fields.runtimeWorktreePath || ''),
157
+ currentRuntime: !!fields.currentRuntime,
158
+ runtimeContextSource: fields.runtimeContextSource || '',
159
+ runtimeContextObservedAt: Number(fields.runtimeContextObservedAt || 0) || 0,
160
+ hidesRuntimeBranch: !!fields.hidesRuntimeBranch,
161
+ mismatchReason: fields.mismatchReason || '',
162
+ candidates: Array.isArray(fields.candidates) ? fields.candidates : [],
163
+ };
164
+ return binding;
165
+ }
166
+
167
+ function candidateKey(candidate) {
168
+ const parsed = parseAgentWorktreePath(candidate.path);
169
+ return parsed ? parsed.cwd : safeRealpath(candidate.path);
170
+ }
171
+
172
+ function resolveSessionWorkspaceBinding(session, options = {}) {
173
+ const worktrees = Array.isArray(options.worktrees) ? options.worktrees : [];
174
+ const runtimeCwd = normalizePath(session?.cwd || '');
175
+ const runtimeWorktreePath = normalizePath(session?.worktree_path || '');
176
+ const runtimeBranch = normalizeBranch(session?.branch || '');
177
+ const currentRuntime = runtimeContextFromSession(session);
178
+ const candidates = [];
179
+
180
+ if (currentRuntime) {
181
+ pushCandidate(candidates, 'runtime.current_worktree_path', currentRuntime.worktreePath, currentRuntime.branch || runtimeBranch, -20, {
182
+ currentRuntime: true,
183
+ runtimeContextSource: currentRuntime.source,
184
+ runtimeContextConfidence: currentRuntime.confidence,
185
+ runtimeContextObservedAt: currentRuntime.observedAt,
186
+ });
187
+ pushCandidate(candidates, 'runtime.current_cwd', currentRuntime.cwd, currentRuntime.branch || runtimeBranch, -10, {
188
+ currentRuntime: true,
189
+ runtimeContextSource: currentRuntime.source,
190
+ runtimeContextConfidence: currentRuntime.confidence,
191
+ runtimeContextObservedAt: currentRuntime.observedAt,
192
+ });
193
+ }
194
+ pushCandidate(candidates, 'runtime.worktree_path', runtimeWorktreePath, runtimeBranch, 0);
195
+ pushCandidate(candidates, 'runtime.cwd', runtimeCwd, runtimeBranch, 10);
196
+ for (const candidate of identityCandidates(options.identity)) candidates.push(candidate);
197
+
198
+ const verified = [];
199
+ for (const candidate of candidates) {
200
+ const wt = findWorktreeByPath(worktrees, candidate.path);
201
+ const parsed = parseAgentWorktreePath(candidate.path);
202
+ if (!wt && !parsed) continue;
203
+ verified.push({
204
+ ...candidate,
205
+ key: wt ? (wt.realPath || safeRealpath(wt.path)) : candidateKey(candidate),
206
+ worktree: wt,
207
+ parsed,
208
+ branch: normalizeBranch((wt && wt.branch) || (candidate.currentRuntime && parsed && parsed.worktreeName) || candidate.branch || (parsed && parsed.worktreeName) || ''),
209
+ priority: candidate.priority,
210
+ });
211
+ }
212
+
213
+ verified.sort((a, b) => a.priority - b.priority);
214
+ const currentVerified = verified.find(item => item.currentRuntime);
215
+ if (currentVerified) {
216
+ const wt = currentVerified.worktree;
217
+ const worktreePath = normalizePath((wt && wt.path) || currentVerified.path);
218
+ const branch = normalizeBranch(currentVerified.branch || (wt && wt.branch) || '');
219
+ const isMain = wt ? wt.isMain : isMainBranch(branch);
220
+ return makeBinding({
221
+ status: 'bound',
222
+ branch,
223
+ worktreePath,
224
+ worktreeName: (wt && wt.worktreeName) || (currentVerified.parsed && currentVerified.parsed.worktreeName) || path.basename(worktreePath),
225
+ isMain,
226
+ source: currentVerified.source,
227
+ confidence: wt ? 'verified-current' : 'path-pattern-current',
228
+ runtimeBranch,
229
+ runtimeCwd,
230
+ runtimeWorktreePath,
231
+ currentRuntime: true,
232
+ runtimeContextSource: currentVerified.runtimeContextSource || '',
233
+ runtimeContextObservedAt: currentVerified.runtimeContextObservedAt || 0,
234
+ hidesRuntimeBranch: !!(runtimeBranch && branch && runtimeBranch !== branch),
235
+ mismatchReason: runtimeBranch && branch && runtimeBranch !== branch ? 'runtime_branch_replaced_by_current_context' : '',
236
+ candidates: verified.map(item => ({ source: item.source, branch: item.branch, path: item.path, currentRuntime: !!item.currentRuntime })),
237
+ });
238
+ }
239
+
240
+ const nonMainVerified = verified.filter(item => item.branch && !isMainBranch(item.branch));
241
+ if (nonMainVerified.length > 0) {
242
+ const keys = new Set(nonMainVerified.map(item => item.key).filter(Boolean));
243
+ const runtimeVerified = nonMainVerified.find(item => item.source === 'runtime.worktree_path' || item.source === 'runtime.cwd');
244
+ const selected = runtimeVerified || (keys.size === 1 ? nonMainVerified[0] : null);
245
+ if (selected) {
246
+ const wt = selected.worktree;
247
+ const worktreePath = normalizePath((wt && wt.path) || selected.path);
248
+ return makeBinding({
249
+ status: 'bound',
250
+ branch: selected.branch,
251
+ worktreePath,
252
+ worktreeName: (wt && wt.worktreeName) || (selected.parsed && selected.parsed.worktreeName) || path.basename(worktreePath),
253
+ isMain: false,
254
+ source: selected.source,
255
+ confidence: wt ? 'verified' : 'path-pattern',
256
+ runtimeBranch,
257
+ runtimeCwd,
258
+ runtimeWorktreePath,
259
+ candidates: nonMainVerified.map(item => ({ source: item.source, branch: item.branch, path: item.path })),
260
+ });
261
+ }
262
+ return makeBinding({
263
+ status: 'ambiguous',
264
+ branch: '',
265
+ source: 'conflict',
266
+ confidence: 'none',
267
+ runtimeBranch,
268
+ runtimeCwd,
269
+ runtimeWorktreePath,
270
+ hidesRuntimeBranch: !!runtimeBranch && !isMainBranch(runtimeBranch),
271
+ mismatchReason: 'multiple_verified_worktree_candidates',
272
+ candidates: nonMainVerified.map(item => ({ source: item.source, branch: item.branch, path: item.path })),
273
+ });
274
+ }
275
+
276
+ const mainPath = runtimeWorktreePath || runtimeCwd;
277
+ const mainWt = findWorktreeByPath(worktrees, mainPath);
278
+ if (mainWt) {
279
+ return makeBinding({
280
+ status: 'bound',
281
+ branch: mainWt.branch || runtimeBranch,
282
+ worktreePath: mainWt.path,
283
+ worktreeName: mainWt.worktreeName || path.basename(mainWt.path || ''),
284
+ isMain: mainWt.isMain,
285
+ source: mainWt.isMain ? 'runtime.main_worktree' : 'runtime.worktree',
286
+ confidence: 'verified',
287
+ runtimeBranch,
288
+ runtimeCwd,
289
+ runtimeWorktreePath,
290
+ hidesRuntimeBranch: runtimeBranch && !isMainBranch(runtimeBranch) && mainWt.isMain,
291
+ mismatchReason: runtimeBranch && !isMainBranch(runtimeBranch) && mainWt.isMain ? 'runtime_branch_not_verified_for_cwd' : '',
292
+ });
293
+ }
294
+
295
+ if (runtimeBranch && !isMainBranch(runtimeBranch)) {
296
+ const branchMatches = findWorktreesByBranch(worktrees, runtimeBranch);
297
+ if (branchMatches.length === 1 && runtimeWorktreePath) {
298
+ const wt = branchMatches[0];
299
+ return makeBinding({
300
+ status: 'bound',
301
+ branch: wt.branch,
302
+ worktreePath: wt.path,
303
+ worktreeName: wt.worktreeName || path.basename(wt.path || ''),
304
+ isMain: wt.isMain,
305
+ source: 'runtime.branch_verified_by_worktree_path',
306
+ confidence: 'verified',
307
+ runtimeBranch,
308
+ runtimeCwd,
309
+ runtimeWorktreePath,
310
+ });
311
+ }
312
+ return makeBinding({
313
+ status: 'unverified',
314
+ branch: '',
315
+ source: 'runtime.branch',
316
+ confidence: 'none',
317
+ runtimeBranch,
318
+ runtimeCwd,
319
+ runtimeWorktreePath,
320
+ hidesRuntimeBranch: true,
321
+ mismatchReason: 'runtime_branch_without_verified_worktree',
322
+ });
323
+ }
324
+
325
+ return makeBinding({
326
+ status: runtimeBranch ? 'main' : 'unknown',
327
+ branch: runtimeBranch,
328
+ isMain: isMainBranch(runtimeBranch),
329
+ source: runtimeBranch ? 'runtime.branch' : '',
330
+ confidence: runtimeBranch ? 'runtime' : 'none',
331
+ runtimeBranch,
332
+ runtimeCwd,
333
+ runtimeWorktreePath,
334
+ });
335
+ }
336
+
337
+ function sessionForWorkspaceBinding(session, binding) {
338
+ if (!session || !binding || !binding.worktreePath) return session;
339
+ return {
340
+ ...session,
341
+ branch: binding.branch || session.branch,
342
+ worktree_path: binding.worktreePath || session.worktree_path,
343
+ cwd: binding.worktreePath || session.cwd,
344
+ };
345
+ }
346
+
347
+ module.exports = {
348
+ findWorktreeByPath,
349
+ findWorktreesByBranch,
350
+ isMainBranch,
351
+ normalizeBranch,
352
+ normalizePath,
353
+ resolveSessionWorkspaceBinding,
354
+ sessionForWorkspaceBinding,
355
+ _clearRealpathCache,
356
+ };
@@ -149,11 +149,20 @@ function mergeCloudflareTransportEnv(cfEnv, origin, env = process.env) {
149
149
  };
150
150
  }
151
151
 
152
+ function _isDevTunnelOrigin(origin) {
153
+ try { return new URL(origin).hostname.endsWith('.devtunnels.ms'); } catch { return false; }
154
+ }
155
+
152
156
  function mergeAllowedOriginTransportEnv(origin, env = process.env) {
157
+ // A managed Dev Tunnel origin REPLACES any previous devtunnels.ms origin: CTM
158
+ // runs one managed tunnel, and a rotated tunnel's old hostname is dead — it
159
+ // must not stay allowlisted. Non-devtunnel origins (Tailscale, custom) are kept.
160
+ const replacingDevTunnel = !!origin && _isDevTunnelOrigin(origin);
153
161
  const origins = [];
154
162
  const seen = new Set();
155
163
  for (const item of [...parseAllowedOrigins(env.CTM_ALLOWED_ORIGINS || ''), origin]) {
156
164
  if (!item || seen.has(item)) continue;
165
+ if (replacingDevTunnel && item !== origin && _isDevTunnelOrigin(item)) continue;
157
166
  seen.add(item);
158
167
  origins.push(item);
159
168
  }
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+ // Hard size cap for whole-conversation parse/stringify operations.
3
+ //
4
+ // A multi-GB Codex/Claude transcript stored as one JSON blob exceeds Node/V8's
5
+ // max string length (0x1fffffe8 ≈ 512 MiB UTF-16 code units) and takes 28-33s to
6
+ // JSON.parse / JSON.stringify on the main thread — freezing the event loop and
7
+ // starving ALL session input. This module is the single shared predicate that
8
+ // lets every whole-conversation code path REFUSE to touch an over-cap payload
9
+ // and instead serve a tail/row view.
10
+ //
11
+ // Design rule: FAIL OPEN. The cap is a pure integer comparison with no I/O and
12
+ // never throws. An unknown / non-finite / non-positive size is treated as UNDER
13
+ // the cap — we do not block work we cannot measure — so a bug here can never
14
+ // itself brick CTM. We only ever block on a concrete, finite measurement that
15
+ // exceeds the cap.
16
+
17
+ // Cap well below V8's ~512 MiB string ceiling: a UTF-8 blob near that byte size
18
+ // blows past it once decoded to a JS string, and even comfortably under it the
19
+ // synchronous parse/stringify is multi-second. Override with the env var (bytes).
20
+ const DEFAULT_MAX_PARSE_BYTES = 256 * 1024 * 1024; // 256 MiB
21
+
22
+ // Read the active cap each call so an env override applies at runtime (and so
23
+ // tests can flip it). Cheap: one Number() + comparison.
24
+ function maxParseBytes() {
25
+ const raw = Number(process.env.CTM_MAX_PARSE_BYTES);
26
+ if (Number.isFinite(raw) && raw > 0) return Math.floor(raw);
27
+ return DEFAULT_MAX_PARSE_BYTES;
28
+ }
29
+
30
+ // True ONLY when byteLen is a finite, positive size that exceeds the cap.
31
+ // Unknown / NaN / 0 / negative / Infinity → false (fail open).
32
+ function isOverParseCap(byteLen) {
33
+ const n = Number(byteLen);
34
+ if (!Number.isFinite(n) || n <= 0) return false;
35
+ return n > maxParseBytes();
36
+ }
37
+
38
+ // Describe a size relative to the cap for response/state plumbing.
39
+ function parseCapState(byteLen) {
40
+ const n = Number(byteLen);
41
+ const bytes = Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
42
+ return { overCap: isOverParseCap(byteLen), bytes, cap: maxParseBytes() };
43
+ }
44
+
45
+ module.exports = { isOverParseCap, parseCapState, maxParseBytes, DEFAULT_MAX_PARSE_BYTES };
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+ const test = require('node:test');
3
+ const assert = require('node:assert');
4
+ const { isOverParseCap, parseCapState, maxParseBytes, DEFAULT_MAX_PARSE_BYTES } = require('./size-cap');
5
+
6
+ test('size-cap', async (t) => {
7
+ // Never mutate process.env at module top level — set/restore around the test.
8
+ const ORIG = process.env.CTM_MAX_PARSE_BYTES;
9
+ t.after(() => {
10
+ if (ORIG === undefined) delete process.env.CTM_MAX_PARSE_BYTES;
11
+ else process.env.CTM_MAX_PARSE_BYTES = ORIG;
12
+ });
13
+
14
+ await t.test('default cap is 256 MiB', () => {
15
+ delete process.env.CTM_MAX_PARSE_BYTES;
16
+ assert.equal(maxParseBytes(), 256 * 1024 * 1024);
17
+ assert.equal(DEFAULT_MAX_PARSE_BYTES, 256 * 1024 * 1024);
18
+ });
19
+
20
+ await t.test('over/under boundary', () => {
21
+ delete process.env.CTM_MAX_PARSE_BYTES;
22
+ const cap = 256 * 1024 * 1024;
23
+ assert.equal(isOverParseCap(cap), false, 'exactly at cap is not over');
24
+ assert.equal(isOverParseCap(cap + 1), true, 'one over cap is over');
25
+ assert.equal(isOverParseCap(cap - 1), false);
26
+ assert.equal(isOverParseCap(7.4 * 1024 * 1024 * 1024), true, '7.4GB is over');
27
+ });
28
+
29
+ await t.test('fails OPEN on unmeasurable sizes', () => {
30
+ delete process.env.CTM_MAX_PARSE_BYTES;
31
+ for (const bad of [undefined, null, NaN, 0, -1, -1e9, 'abc', Infinity, -Infinity]) {
32
+ assert.equal(isOverParseCap(bad), false, `${String(bad)} must not be over cap (fail open)`);
33
+ }
34
+ });
35
+
36
+ await t.test('env override applies', () => {
37
+ process.env.CTM_MAX_PARSE_BYTES = String(1000);
38
+ assert.equal(maxParseBytes(), 1000);
39
+ assert.equal(isOverParseCap(1001), true);
40
+ assert.equal(isOverParseCap(1000), false);
41
+ assert.equal(isOverParseCap(999), false);
42
+ });
43
+
44
+ await t.test('invalid env override falls back to default', () => {
45
+ process.env.CTM_MAX_PARSE_BYTES = 'not-a-number';
46
+ assert.equal(maxParseBytes(), DEFAULT_MAX_PARSE_BYTES);
47
+ process.env.CTM_MAX_PARSE_BYTES = '-5';
48
+ assert.equal(maxParseBytes(), DEFAULT_MAX_PARSE_BYTES);
49
+ process.env.CTM_MAX_PARSE_BYTES = '0';
50
+ assert.equal(maxParseBytes(), DEFAULT_MAX_PARSE_BYTES);
51
+ });
52
+
53
+ await t.test('parseCapState shape', () => {
54
+ delete process.env.CTM_MAX_PARSE_BYTES;
55
+ const s = parseCapState(300 * 1024 * 1024);
56
+ assert.equal(s.overCap, true);
57
+ assert.equal(s.bytes, 300 * 1024 * 1024);
58
+ assert.equal(s.cap, 256 * 1024 * 1024);
59
+ const u = parseCapState(undefined);
60
+ assert.deepEqual({ overCap: u.overCap, bytes: u.bytes }, { overCap: false, bytes: 0 });
61
+ });
62
+ });