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
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
6
6
  <title>Pair Phone - CTM</title>
7
7
  <link rel="manifest" href="/manifest.json">
8
- <link rel="stylesheet" href="/m/app.css?v=20260519-walle-phone-model-picker">
8
+ <link rel="stylesheet" href="/m/app.css?v=20260529-phone-submission-ledger">
9
9
  </head>
10
10
  <body>
11
11
  <main class="claim-shell">
@@ -25,10 +25,17 @@
25
25
  var params = new URLSearchParams(location.search);
26
26
  var claim = params.get('claim') || '';
27
27
  var secret = params.get('secret') || '';
28
+ var reason = params.get('reason') || '';
28
29
  var statusEl = document.getElementById('claim-status');
29
30
  var summaryEl = document.getElementById('claim-summary');
30
31
  var actionEl = document.getElementById('claim-action');
31
32
  var publicKeyOptions = null;
33
+ var passkeyMode = 'register';
34
+ var actionHandler = null;
35
+ var pairingPollTimer = null;
36
+ var pairingStorageKey = 'ctm.mobile.pendingPairingRequest';
37
+ var sessionSnapshotKey = 'ctm.mobile.sessionSnapshot.v1';
38
+ var forceFullRefreshKey = 'ctm.mobile.forceFullRefresh.v1';
32
39
 
33
40
  function setStatus(text, isError) {
34
41
  statusEl.textContent = text;
@@ -40,9 +47,151 @@
40
47
  if (/rpid|rp id|origin|related origins/i.test(message)) {
41
48
  return 'Pairing origin did not match this tunnel URL. Refresh the setup page on the Mac, create a new QR from the active tunnel URL, and try again.';
42
49
  }
50
+ if (message === 'phone_origin_rotation_required') {
51
+ return 'This phone is already paired on another CTM URL. Open that saved stable URL, or add a passkey for this new URL from the mobile More page if you intentionally changed URLs.';
52
+ }
43
53
  return message;
44
54
  }
45
55
 
56
+ function setAction(text, handler, disabled) {
57
+ actionEl.textContent = text;
58
+ actionEl.disabled = !!disabled;
59
+ actionHandler = typeof handler === 'function' ? handler : null;
60
+ }
61
+
62
+ function setSummary(text) {
63
+ summaryEl.hidden = !text;
64
+ summaryEl.textContent = text || '';
65
+ }
66
+
67
+ function dashboardUrl() {
68
+ return '/m/#status';
69
+ }
70
+
71
+ function openDashboard() {
72
+ location.href = dashboardUrl();
73
+ }
74
+
75
+ function enterDashboard() {
76
+ location.replace(dashboardUrl());
77
+ }
78
+
79
+ function markPairingCompleted() {
80
+ try {
81
+ localStorage.removeItem(sessionSnapshotKey);
82
+ localStorage.setItem(forceFullRefreshKey, JSON.stringify({
83
+ reason: 'phone-pairing-completed',
84
+ at: Date.now(),
85
+ }));
86
+ } catch (_) {}
87
+ }
88
+
89
+ function storedPairingRequest() {
90
+ try {
91
+ var raw = localStorage.getItem(pairingStorageKey);
92
+ if (!raw) return null;
93
+ var parsed = JSON.parse(raw);
94
+ if (!parsed || parsed.origin !== location.origin || !parsed.id || !parsed.secret) return null;
95
+ if (parsed.expires_at && Number(parsed.expires_at) <= Date.now()) {
96
+ localStorage.removeItem(pairingStorageKey);
97
+ return null;
98
+ }
99
+ return parsed;
100
+ } catch (_) {
101
+ return null;
102
+ }
103
+ }
104
+
105
+ function rememberPairingRequest(request, secret) {
106
+ try {
107
+ localStorage.setItem(pairingStorageKey, JSON.stringify({
108
+ id: request.id,
109
+ secret: secret,
110
+ code: request.code || '',
111
+ origin: location.origin,
112
+ expires_at: request.expires_at || (Date.now() + 10 * 60 * 1000),
113
+ }));
114
+ } catch (_) {}
115
+ }
116
+
117
+ function clearPairingRequest() {
118
+ try { localStorage.removeItem(pairingStorageKey); } catch (_) {}
119
+ if (pairingPollTimer) clearTimeout(pairingPollTimer);
120
+ pairingPollTimer = null;
121
+ }
122
+
123
+ function phonePairingIntro() {
124
+ setSummary('Tap Request Pairing, then approve the matching code on the Mac in CTM Settings > Pair Phone. This page continues automatically after approval.');
125
+ setStatus('This phone is not paired with this CTM URL.', true);
126
+ setAction('Request Pairing', requestPairing, false);
127
+ }
128
+
129
+ function showPendingPairing(request) {
130
+ var code = request && request.code ? String(request.code) : 'pending';
131
+ setSummary('Approval code: ' + code + '. Leave this page open, then approve this request on the Mac. If the code is not visible there, refresh Settings > Pair Phone.');
132
+ setStatus('Waiting for Mac approval...');
133
+ setAction('Waiting for approval', null, true);
134
+ }
135
+
136
+ async function requestPairing() {
137
+ setAction('Requesting...', null, true);
138
+ setStatus('Creating a pairing request...');
139
+ try {
140
+ var res = await fetch('/api/auth/pairing-requests', {
141
+ method: 'POST',
142
+ headers: { 'Content-Type': 'application/json' },
143
+ body: JSON.stringify({ label: '', scopes: ['read', 'respond'] }),
144
+ });
145
+ var data = await res.json();
146
+ if (!res.ok || !data.ok || !data.request || !data.secret) {
147
+ throw new Error(data.message || data.error || 'Pairing request failed');
148
+ }
149
+ rememberPairingRequest(data.request, data.secret);
150
+ showPendingPairing(data.request);
151
+ pollPairing(data.request.id, data.secret);
152
+ } catch (err) {
153
+ setStatus(friendlyError(err), true);
154
+ setAction('Request Pairing', requestPairing, false);
155
+ }
156
+ }
157
+
158
+ async function pollPairing(id, requestSecret) {
159
+ if (pairingPollTimer) clearTimeout(pairingPollTimer);
160
+ try {
161
+ var res = await fetch('/api/auth/pairing-requests/' + encodeURIComponent(id) + '/poll', {
162
+ method: 'POST',
163
+ headers: { 'Content-Type': 'application/json' },
164
+ body: JSON.stringify({ secret: requestSecret }),
165
+ });
166
+ var data = await res.json();
167
+ if (!res.ok || !data.ok) throw new Error(data.message || data.error || 'Pairing request failed');
168
+ if (data.status === 'approved' && data.claim && data.claim.claimUrl) {
169
+ clearPairingRequest();
170
+ setSummary('Approved. Opening one-time phone pairing...');
171
+ setStatus('Mac approved this phone. Finish pairing with Face ID.');
172
+ location.replace(data.claim.claimUrl);
173
+ return;
174
+ }
175
+ if (data.status === 'rejected') {
176
+ clearPairingRequest();
177
+ setStatus('The Mac rejected this pairing request.', true);
178
+ setAction('Request Again', requestPairing, false);
179
+ return;
180
+ }
181
+ if (data.status === 'expired') {
182
+ clearPairingRequest();
183
+ setStatus('This pairing request expired.', true);
184
+ setAction('Request Again', requestPairing, false);
185
+ return;
186
+ }
187
+ showPendingPairing(data.request || { id: id });
188
+ pairingPollTimer = setTimeout(function() { pollPairing(id, requestSecret); }, 2000);
189
+ } catch (err) {
190
+ setStatus(friendlyError(err), true);
191
+ setAction('Retry Polling', function() { pollPairing(id, requestSecret); }, false);
192
+ }
193
+ }
194
+
46
195
  function b64urlToBuffer(value) {
47
196
  var base64 = String(value || '').replace(/-/g, '+').replace(/_/g, '/');
48
197
  base64 += '='.repeat((4 - base64.length % 4) % 4);
@@ -69,6 +218,15 @@
69
218
  return { publicKey: publicKey };
70
219
  }
71
220
 
221
+ function prepareAuthenticationOptions(options) {
222
+ var publicKey = Object.assign({}, options);
223
+ publicKey.challenge = b64urlToBuffer(publicKey.challenge);
224
+ publicKey.allowCredentials = (publicKey.allowCredentials || []).map(function(c) {
225
+ return Object.assign({}, c, { id: b64urlToBuffer(c.id) });
226
+ });
227
+ return { publicKey: publicKey };
228
+ }
229
+
72
230
  function credentialToJSON(credential) {
73
231
  return {
74
232
  id: credential.id,
@@ -83,9 +241,42 @@
83
241
  };
84
242
  }
85
243
 
244
+ function assertionToJSON(credential) {
245
+ return {
246
+ id: credential.id,
247
+ rawId: bufferToB64url(credential.rawId),
248
+ type: credential.type,
249
+ response: {
250
+ authenticatorData: bufferToB64url(credential.response.authenticatorData),
251
+ clientDataJSON: bufferToB64url(credential.response.clientDataJSON),
252
+ signature: bufferToB64url(credential.response.signature),
253
+ userHandle: credential.response.userHandle ? bufferToB64url(credential.response.userHandle) : null,
254
+ },
255
+ clientExtensionResults: credential.getClientExtensionResults ? credential.getClientExtensionResults() : {},
256
+ };
257
+ }
258
+
86
259
  async function begin() {
87
260
  if (!claim || !secret) {
88
- setStatus('This pairing link is missing its claim secret.', true);
261
+ if (reason) {
262
+ if (reason === 'ip_locked') {
263
+ setSummary('Your existing phone pairing was not removed. If the tunnel asks you to sign in, complete that provider login before CTM opens.');
264
+ setStatus('Access is temporarily locked after repeated failed token checks. Wait briefly, then open the dashboard again.', true);
265
+ setAction('Open Dashboard', openDashboard, false);
266
+ } else {
267
+ var existing = storedPairingRequest();
268
+ if (existing) {
269
+ showPendingPairing(existing);
270
+ pollPairing(existing.id, existing.secret);
271
+ } else {
272
+ phonePairingIntro();
273
+ }
274
+ }
275
+ } else {
276
+ setStatus('This pairing link is missing its claim secret.', true);
277
+ setSummary('Open the complete pairing link from the Mac, or request a new pairing from this phone and approve it on the Mac.');
278
+ setAction('Request Pairing', requestPairing, false);
279
+ }
89
280
  return;
90
281
  }
91
282
  if (!window.isSecureContext) {
@@ -102,38 +293,54 @@
102
293
  body: JSON.stringify({ claim: claim, secret: secret }),
103
294
  });
104
295
  var data = await res.json();
105
- if (!res.ok || !data.ok) throw new Error(data.error || 'Pairing failed');
296
+ if (!res.ok || !data.ok) throw new Error(data.message || data.error || 'Pairing failed');
106
297
  publicKeyOptions = data.options;
107
- summaryEl.hidden = false;
108
- summaryEl.textContent = (data.claim.label || 'Phone') + ' - ' + (data.claim.scopes || []).join(', ');
109
- setStatus('Confirm with Face ID to bind this device.');
110
- actionEl.disabled = false;
111
- actionEl.textContent = 'Face ID & Pair';
298
+ passkeyMode = data.mode === 'recover' ? 'recover' : 'register';
299
+ setSummary((data.claim.label || 'Phone') + ' - ' + (data.claim.scopes || []).join(', '));
300
+ if (passkeyMode === 'recover') {
301
+ setStatus('Use Face ID to reconnect this already-paired phone.');
302
+ setAction('Face ID & Reconnect', finish, false);
303
+ } else {
304
+ setStatus('Use Face ID once to pair this phone to CTM.');
305
+ setAction('Face ID & Pair', finish, false);
306
+ }
112
307
  }
113
308
 
114
309
  async function finish() {
310
+ if (!publicKeyOptions) return;
115
311
  actionEl.disabled = true;
116
- setStatus('Waiting for passkey confirmation...');
312
+ setStatus('Waiting for pairing confirmation...');
117
313
  try {
118
- var credential = await navigator.credentials.create(prepareCreationOptions(publicKeyOptions));
314
+ var isRecover = passkeyMode === 'recover';
315
+ var credential = isRecover
316
+ ? await navigator.credentials.get(prepareAuthenticationOptions(publicKeyOptions))
317
+ : await navigator.credentials.create(prepareCreationOptions(publicKeyOptions));
119
318
  var res = await fetch('/api/auth/claim/finish', {
120
319
  method: 'POST',
121
320
  headers: { 'Content-Type': 'application/json' },
122
- body: JSON.stringify({ claim: claim, secret: secret, response: credentialToJSON(credential) }),
321
+ body: JSON.stringify({
322
+ claim: claim,
323
+ secret: secret,
324
+ mode: passkeyMode,
325
+ response: isRecover ? assertionToJSON(credential) : credentialToJSON(credential),
326
+ }),
123
327
  });
124
328
  var data = await res.json();
125
- if (!res.ok || !data.ok) throw new Error(data.error || 'Pairing failed');
126
- setStatus('This phone is paired.');
127
- actionEl.textContent = 'Open Dashboard';
128
- actionEl.disabled = false;
129
- actionEl.onclick = function() { location.href = '/m/'; };
329
+ if (!res.ok || !data.ok) throw new Error(data.message || data.error || 'Pairing failed');
330
+ markPairingCompleted();
331
+ setStatus('This phone is paired. Opening dashboard...');
332
+ setAction('Open Dashboard', openDashboard, false);
333
+ enterDashboard();
130
334
  } catch (err) {
131
335
  setStatus(friendlyError(err), true);
132
336
  actionEl.disabled = false;
133
337
  }
134
338
  }
135
339
 
136
- actionEl.addEventListener('click', finish);
340
+ actionEl.addEventListener('click', function() {
341
+ if (actionEl.disabled || !actionHandler) return;
342
+ actionHandler();
343
+ });
137
344
  begin().catch(function(err) { setStatus(friendlyError(err), true); });
138
345
  })();
139
346
  </script>
@@ -48,24 +48,31 @@
48
48
  <link rel="icon" type="image/png" sizes="32x32" href="/icon-32.png">
49
49
  <link rel="apple-touch-icon" sizes="180x180" href="/icon-180.png">
50
50
  <link rel="manifest" href="/manifest.json">
51
- <link rel="stylesheet" href="/m/app.css?v=20260519-walle-phone-model-picker">
51
+ <link rel="stylesheet" href="/m/app.css?v=20260607-detail-alert-dismiss">
52
52
  </head>
53
- <body class="mobile-app">
53
+ <body class="mobile-app" data-mobile-tab="status">
54
54
  <header class="app-topbar">
55
55
  <div>
56
56
  <div class="app-kicker">CTM</div>
57
57
  <h1 id="app-title">Status</h1>
58
58
  </div>
59
59
  <div class="topbar-actions">
60
- <span id="connection-chip" class="connection-chip stale">Stale</span>
60
+ <button id="connection-chip" class="connection-chip stale" type="button" aria-label="Connection status: Stale" title="Refresh connection status">Stale</button>
61
61
  <button id="refresh-btn" class="icon-btn" type="button" aria-label="Refresh" title="Refresh">↻</button>
62
62
  </div>
63
63
  </header>
64
+ <section id="app-reload-banner" class="app-reload-banner" role="status" aria-live="polite" aria-atomic="true" hidden>
65
+ <div>
66
+ <strong id="app-reload-title">Update installed</strong>
67
+ <span id="app-reload-msg">Reload to use the latest CTM / Wall-E UI.</span>
68
+ </div>
69
+ <button id="app-reload-now-btn" type="button">Reload</button>
70
+ </section>
64
71
 
65
72
  <main id="app-main" class="app-main" tabindex="-1">
66
73
  <section id="view-status" class="mobile-view active" aria-labelledby="status-heading">
67
74
  <h2 id="status-heading" class="sr-only">Status</h2>
68
- <div id="status-summary" class="status-summary" aria-live="polite"></div>
75
+ <div id="status-summary" class="status-summary" aria-label="Status lanes" aria-live="polite"></div>
69
76
  <div id="home-search" class="home-search" role="search">
70
77
  <div class="home-search-box">
71
78
  <span class="home-search-icon" aria-hidden="true">⌕</span>
@@ -107,14 +114,17 @@
107
114
  </section>
108
115
 
109
116
  <section id="view-more" class="mobile-view" aria-labelledby="more-heading">
110
- <h2 id="more-heading">More</h2>
117
+ <h2 id="more-heading" class="sr-only">More</h2>
111
118
  <div id="more-content" class="view-content"></div>
112
119
  </section>
113
120
  </main>
114
121
 
115
122
  <aside id="detail-view" class="detail-view" role="dialog" aria-modal="true" aria-labelledby="detail-title" aria-hidden="true">
116
123
  <header class="detail-topbar">
117
- <button id="detail-back" class="icon-btn" type="button" aria-label="Back" title="Back">←</button>
124
+ <button id="detail-back" class="icon-btn detail-back-btn" type="button" aria-label="Back" title="Back">
125
+ <span class="detail-back-glyph" aria-hidden="true">←</span>
126
+ <span class="detail-back-label" aria-hidden="true">Back</span>
127
+ </button>
118
128
  <div class="detail-title-block">
119
129
  <h2 id="detail-title">Agent</h2>
120
130
  <p id="detail-meta"></p>
@@ -126,7 +136,7 @@
126
136
  </header>
127
137
  <section id="detail-alert" class="detail-alert" hidden></section>
128
138
  <section id="detail-controls" class="detail-controls" hidden></section>
129
- <section id="detail-messages" class="detail-messages" aria-live="polite"></section>
139
+ <section id="detail-messages" class="detail-messages" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section>
130
140
  <form id="detail-composer" class="composer" autocomplete="off" autocorrect="on" autocapitalize="sentences" spellcheck="true">
131
141
  <div class="composer-field">
132
142
  <span id="detail-input-label" class="sr-only">Reply</span>
@@ -148,16 +158,20 @@
148
158
  <div id="mobile-skill-picker" class="mobile-skill-picker" role="listbox" aria-label="Skill suggestions" hidden></div>
149
159
  <div id="composer-status" class="composer-status" aria-live="polite"></div>
150
160
  </div>
151
- <button id="detail-model" class="model-picker-btn" type="button" aria-label="Choose model for this Wall-E session" aria-haspopup="dialog" aria-expanded="false" hidden>
152
- <span class="model-picker-btn-kicker">Model</span>
153
- <span id="detail-model-label" class="model-picker-btn-label">Auto</span>
154
- </button>
155
161
  <button id="detail-send" class="send-btn" type="submit" aria-label="Send" aria-haspopup="menu" aria-expanded="false"><span aria-hidden="true">➤</span></button>
156
162
  <div id="send-menu" class="send-menu" role="menu" hidden>
157
163
  <div class="send-menu-header" role="presentation">
158
164
  <strong>Session actions</strong>
159
- <span>Recall a prompt, attach context, or control the live terminal.</span>
165
+ <span>Review the queue, recall a prompt, choose a model, attach context, or control the live terminal.</span>
160
166
  </div>
167
+ <button id="send-model-option" class="send-menu-item send-menu-model" type="button" role="menuitem" aria-haspopup="dialog" aria-expanded="false" hidden>
168
+ <span class="send-menu-item-kicker">Model</span>
169
+ <span id="send-model-label" class="send-menu-item-main">Auto model</span>
170
+ </button>
171
+ <button id="send-queue-builder-option" class="send-menu-item send-menu-queue" type="button" role="menuitem" aria-haspopup="dialog" data-send-menu-queue>
172
+ <span class="send-menu-item-kicker">Queue</span>
173
+ <span class="send-menu-item-main">Review, edit, send</span>
174
+ </button>
161
175
  <button id="send-prev-prompt-option" class="send-menu-item" type="button" role="menuitem" data-send-menu-control="previous">Previous prompt</button>
162
176
  <button id="send-next-prompt-option" class="send-menu-item" type="button" role="menuitem" data-send-menu-control="next">Next prompt</button>
163
177
  <button id="send-copy-url-option" class="send-menu-item" type="button" role="menuitem" data-send-menu-copy>Copy session URL</button>
@@ -171,11 +185,11 @@
171
185
  </aside>
172
186
 
173
187
  <nav class="bottom-nav" aria-label="Mobile sections">
174
- <button class="nav-item active" type="button" data-tab="status" aria-current="page"><span>●</span>Status</button>
175
- <button class="nav-item" type="button" data-tab="agents"><span>▤</span>Agents</button>
176
- <button class="nav-item" type="button" data-tab="walle"><span>◆</span>Wall-E</button>
177
- <button class="nav-item" type="button" data-tab="search"><span>⌕</span>Search</button>
178
- <button class="nav-item" type="button" data-tab="more"><span>⋯</span>More</button>
188
+ <a class="nav-item active" href="#status" data-tab="status" aria-current="page"><span>●</span>Status</a>
189
+ <a class="nav-item" href="#agents" data-tab="agents"><span>▤</span>Agents</a>
190
+ <a class="nav-item" href="#walle" data-tab="walle"><span>◆</span>Wall-E</a>
191
+ <a class="nav-item" href="#search" data-tab="search"><span>⌕</span>Search</a>
192
+ <a class="nav-item" href="#more" data-tab="more"><span>⋯</span>More</a>
179
193
  </nav>
180
194
 
181
195
  <div id="stepup-sheet" class="modal-backdrop" hidden>
@@ -202,6 +216,87 @@
202
216
  </section>
203
217
  </div>
204
218
 
219
+ <div id="queue-builder-sheet" class="modal-backdrop queue-builder-backdrop" hidden>
220
+ <section class="mobile-queue-builder-sheet" role="dialog" aria-modal="true" aria-labelledby="queue-builder-title">
221
+ <div class="queue-builder-head">
222
+ <div>
223
+ <p class="sheet-kicker">Session queue</p>
224
+ <h2 id="queue-builder-title">Review queue</h2>
225
+ <p id="queue-builder-subtitle">Load pending prompts for this session.</p>
226
+ </div>
227
+ <button id="queue-builder-close" class="model-picker-close" type="button" aria-label="Close queue builder">&times;</button>
228
+ </div>
229
+ <div class="queue-builder-toolbar" role="group" aria-label="Queue mode and controls">
230
+ <button id="queue-builder-mode" class="queue-builder-chip" type="button" aria-pressed="false">Manual</button>
231
+ <button id="queue-builder-clear" class="queue-builder-chip danger" type="button">Clear sent</button>
232
+ </div>
233
+ <div id="queue-builder-status" class="queue-builder-status" role="status" aria-live="polite"></div>
234
+ <div id="queue-builder-list" class="mobile-queue-list" aria-label="Queued prompts"></div>
235
+ <form id="queue-builder-add-form" class="queue-builder-add-form">
236
+ <label for="queue-builder-input">Add prompt</label>
237
+ <textarea id="queue-builder-input" rows="3" placeholder="Type a queued prompt..." autocomplete="off" spellcheck="true"></textarea>
238
+ <button id="queue-builder-add" class="secondary-btn" type="submit">Add to queue</button>
239
+ </form>
240
+ <div class="queue-builder-actions">
241
+ <button id="queue-builder-send-next" class="secondary-btn" type="button">Send next</button>
242
+ <button id="queue-builder-send-all" class="primary-btn" type="button">Send all</button>
243
+ </div>
244
+ </section>
245
+ </div>
246
+
247
+ <div id="worktree-finish-sheet" class="modal-backdrop" hidden>
248
+ <section class="stepup-sheet worktree-finish-sheet" role="dialog" aria-modal="true" aria-labelledby="worktree-finish-title">
249
+ <h2 id="worktree-finish-title">Finish worktree</h2>
250
+ <p id="worktree-finish-copy">Ask the owning coding session to finish the local work.</p>
251
+ <div class="worktree-finish-card">
252
+ <div>
253
+ <span>Branch</span>
254
+ <strong id="worktree-finish-branch">main</strong>
255
+ </div>
256
+ <div>
257
+ <span>Path</span>
258
+ <strong id="worktree-finish-path"></strong>
259
+ </div>
260
+ <div>
261
+ <span>Session</span>
262
+ <strong id="worktree-finish-session"></strong>
263
+ </div>
264
+ <div>
265
+ <span>Changes</span>
266
+ <strong id="worktree-finish-counts"></strong>
267
+ </div>
268
+ <div>
269
+ <span>Skill</span>
270
+ <strong id="worktree-finish-skill"></strong>
271
+ </div>
272
+ </div>
273
+ <div class="worktree-finish-action-group" aria-label="Worktree action">
274
+ <span>Action</span>
275
+ <div class="worktree-finish-action-options" role="radiogroup" aria-label="Worktree command action">
276
+ <button id="worktree-finish-action-finish" type="button" role="radio" aria-checked="true" data-worktree-finish-action="finish">
277
+ Finish & merge
278
+ </button>
279
+ <button id="worktree-finish-action-pr" type="button" role="radio" aria-checked="false" data-worktree-finish-action="pr">
280
+ Create PR
281
+ </button>
282
+ </div>
283
+ </div>
284
+ <label class="worktree-finish-session-picker" for="worktree-finish-session-select">
285
+ <span>Send command to</span>
286
+ <select id="worktree-finish-session-select"></select>
287
+ </label>
288
+ <div class="worktree-finish-plan">
289
+ <strong>Request flow</strong>
290
+ <ol id="worktree-finish-plan"></ol>
291
+ </div>
292
+ <p id="worktree-finish-error" class="worktree-finish-error" hidden></p>
293
+ <div class="sheet-actions">
294
+ <button id="worktree-finish-cancel" class="secondary-btn" type="button">Cancel</button>
295
+ <button id="worktree-finish-confirm" class="primary-btn" type="button">Ask session to finish</button>
296
+ </div>
297
+ </section>
298
+ </div>
299
+
205
300
  <div id="new-session-sheet" class="modal-backdrop" hidden>
206
301
  <form id="new-session-form" class="stepup-sheet" role="dialog" aria-modal="true" aria-labelledby="new-session-title">
207
302
  <h2 id="new-session-title">New Session</h2>
@@ -239,9 +334,10 @@
239
334
  </script>
240
335
  <script src="https://cdn.jsdelivr.net/npm/marked@15.0.7/marked.min.js"></script>
241
336
  <script src="https://cdn.jsdelivr.net/npm/dompurify@3.2.4/dist/purify.min.js"></script>
242
- <script src="/js/session-search-utils.js?v=20260519-walle-phone-model-picker"></script>
243
- <script src="/js/image-normalize.js?v=20260519-walle-phone-model-picker"></script>
244
- <script src="/js/message-renderer.js?v=20260519-walle-phone-model-picker"></script>
245
- <script src="/m/app.js?v=20260519-walle-phone-model-picker"></script>
337
+ <script src="/js/session-search-utils.js?v=20260519-update-refresh"></script>
338
+ <script src="/js/image-normalize.js?v=20260519-update-refresh"></script>
339
+ <script src="/js/message-renderer.js?v=20260520-image-attachments"></script>
340
+ <script src="/js/document-review-links.js?v=20260520-doc-review-anchors"></script>
341
+ <script src="/m/app.js?v=20260607-detail-alert-dismiss"></script>
246
342
  </body>
247
343
  </html>
@@ -1,13 +1,15 @@
1
1
  'use strict';
2
2
 
3
- const CACHE_NAME = 'ctm-mobile-shell-v32';
3
+ const CACHE_NAME = 'ctm-mobile-shell-v69';
4
4
  const SHELL_ASSETS = [
5
5
  '/m/',
6
6
  '/m/index.html',
7
+ '/m/claim.html',
7
8
  '/m/app.css',
8
9
  '/m/app.js',
9
10
  '/js/session-search-utils.js',
10
11
  '/js/message-renderer.js',
12
+ '/js/document-review-links.js',
11
13
  '/icon-32.png',
12
14
  '/icon-180.png',
13
15
  '/manifest.json',
@@ -1,7 +1,7 @@
1
1
  {
2
- "name": "Claude Task Manager",
2
+ "name": "Coding Task Manager",
3
3
  "short_name": "CTM",
4
- "description": "Manage Claude Code sessions, prompts, and task queues",
4
+ "description": "Manage coding-agent sessions, prompts, and task queues",
5
5
  "start_url": "/",
6
6
  "display": "standalone",
7
7
  "background_color": "#1a1b26",
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Claude Prompt Editor</title>
6
+ <title>Coding Prompt Editor</title>
7
7
  <link rel="icon" type="image/png" sizes="32x32" href="/icon-32.png">
8
8
  <link rel="icon" type="image/png" sizes="16x16" href="/icon-16.png">
9
9
  <link rel="apple-touch-icon" sizes="180x180" href="/icon-180.png">
@@ -933,11 +933,19 @@
933
933
  .toast-title { font-size: 12px; font-weight: 600; color: var(--fg); margin-bottom: 2px; }
934
934
  .toast-msg { font-size: 11px; color: var(--fg-dim); line-height: 1.4; word-break: break-word; }
935
935
  .toast-close {
936
- background: none; border: none; color: var(--fg-dim); cursor: pointer;
937
- font-size: 14px; padding: 0 0 0 8px; line-height: 1; flex-shrink: 0;
938
- opacity: 0; transition: opacity 0.2s;
936
+ width: 24px; height: 24px; border-radius: 8px;
937
+ display: inline-flex; align-items: center; justify-content: center;
938
+ background: transparent; border: 1px solid transparent; color: var(--fg-dim); cursor: pointer;
939
+ font-size: 18px; padding: 0; line-height: 1; flex-shrink: 0;
940
+ transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
941
+ }
942
+ .toast-close:hover,
943
+ .toast-close:focus-visible {
944
+ background: rgba(255,255,255,0.06);
945
+ border-color: var(--border);
946
+ color: var(--fg);
947
+ outline: none;
939
948
  }
940
- .toast:hover .toast-close { opacity: 1; }
941
949
  .toast-progress {
942
950
  position: absolute; bottom: 0; left: 0; height: 2px;
943
951
  border-radius: 0 0 12px 12px; transition: width linear;
@@ -1144,7 +1152,7 @@
1144
1152
  <body>
1145
1153
  <div id="toast-container"></div>
1146
1154
  <div id="topbar">
1147
- <span class="logo" onclick="navigateToMain()">Claude Task Manager</span>
1155
+ <span class="logo" onclick="navigateToMain()">Coding Task Manager</span>
1148
1156
  <span style="color:var(--fg-dim);font-size:12px">/</span>
1149
1157
  <span style="font-size:13px;font-weight:500">Prompt Editor</span>
1150
1158
  <div class="topbar-actions">
@@ -1555,13 +1563,25 @@ function toast(message, opts = {}) {
1555
1563
  el.innerHTML = `
1556
1564
  <div class="toast-icon ${type}">${TOAST_ICONS[type]}</div>
1557
1565
  <div class="toast-body">
1558
- ${title ? `<div class="toast-title">${title}</div>` : ''}
1559
- <div class="toast-msg">${message}</div>
1566
+ ${title ? `<div class="toast-title">${escHtml(title)}</div>` : ''}
1567
+ <div class="toast-msg">${escHtml(message)}</div>
1560
1568
  </div>
1561
- <button class="toast-close" onclick="this.closest('.toast').remove()">&times;</button>
1569
+ <button class="toast-close" type="button" aria-label="Dismiss notification" title="Dismiss notification">&times;</button>
1562
1570
  <div class="toast-progress ${type}" style="width:100%"></div>
1563
1571
  `;
1564
1572
  container.appendChild(el);
1573
+ let removed = false;
1574
+ let dismissTimer = null;
1575
+ const dismiss = () => {
1576
+ if (removed) return;
1577
+ removed = true;
1578
+ if (dismissTimer) clearTimeout(dismissTimer);
1579
+ el.classList.remove('show');
1580
+ el.classList.add('hide');
1581
+ setTimeout(() => el.remove(), 400);
1582
+ };
1583
+ const close = el.querySelector('.toast-close');
1584
+ if (close) close.addEventListener('click', dismiss);
1565
1585
  requestAnimationFrame(() => {
1566
1586
  el.classList.add('show');
1567
1587
  const bar = el.querySelector('.toast-progress');
@@ -1570,11 +1590,7 @@ function toast(message, opts = {}) {
1570
1590
  requestAnimationFrame(() => { bar.style.width = '0%'; });
1571
1591
  }
1572
1592
  });
1573
- setTimeout(() => {
1574
- el.classList.remove('show');
1575
- el.classList.add('hide');
1576
- setTimeout(() => el.remove(), 400);
1577
- }, duration);
1593
+ dismissTimer = setTimeout(dismiss, duration);
1578
1594
  return el;
1579
1595
  }
1580
1596