create-walle 0.10.2 → 0.10.3

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 (488) hide show
  1. package/README.md +3 -1
  2. package/lib/release-schema.json +2 -2
  3. package/lib/runtime-closure-policy.json +8 -7
  4. package/package.json +1 -1
  5. package/template/coding-task-manager/api-prompts.js +45 -7
  6. package/template/coding-task-manager/bin/claude-hook.js +55 -1
  7. package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
  8. package/template/coding-task-manager/bin/land.js +2069 -0
  9. package/template/coding-task-manager/bin/memory-census.js +4 -2
  10. package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
  11. package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
  12. package/template/coding-task-manager/db.js +156 -32
  13. package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
  14. package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
  15. package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
  16. package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
  17. package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
  18. package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
  19. package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
  20. package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
  21. package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
  22. package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
  23. package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
  24. package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
  25. package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
  26. package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
  27. package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
  28. package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
  29. package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
  30. package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
  31. package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
  32. package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
  33. package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
  34. package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
  35. package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
  36. package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
  37. package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
  38. package/template/coding-task-manager/lib/agent-definitions.js +19 -0
  39. package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
  40. package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
  41. package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
  42. package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
  43. package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
  44. package/template/coding-task-manager/lib/agent-presets.js +84 -1
  45. package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
  46. package/template/coding-task-manager/lib/agent-version-service.js +74 -11
  47. package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
  48. package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
  49. package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
  50. package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
  51. package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
  52. package/template/coding-task-manager/lib/api/fleet.js +118 -0
  53. package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
  54. package/template/coding-task-manager/lib/api/ingress.js +9 -1
  55. package/template/coding-task-manager/lib/api/landing.js +403 -0
  56. package/template/coding-task-manager/lib/api/machines.js +691 -2
  57. package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
  58. package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
  59. package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
  60. package/template/coding-task-manager/lib/api/session-attach.js +623 -0
  61. package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
  62. package/template/coding-task-manager/lib/api/sessions.js +77 -51
  63. package/template/coding-task-manager/lib/api/setup-network.js +544 -16
  64. package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
  65. package/template/coding-task-manager/lib/api/setup.js +829 -10
  66. package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
  67. package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
  68. package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
  69. package/template/coding-task-manager/lib/auth-rules.js +292 -21
  70. package/template/coding-task-manager/lib/background-stop.js +369 -0
  71. package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
  72. package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
  73. package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
  74. package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
  75. package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
  76. package/template/coding-task-manager/lib/build-info.js +4 -2
  77. package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
  78. package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
  79. package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
  80. package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
  81. package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
  82. package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
  83. package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
  84. package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
  85. package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
  86. package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
  87. package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
  88. package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
  89. package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
  90. package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
  91. package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
  92. package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
  93. package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
  94. package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
  95. package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
  96. package/template/coding-task-manager/lib/conversation-sync.js +355 -0
  97. package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
  98. package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
  99. package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
  100. package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
  101. package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
  102. package/template/coding-task-manager/lib/db-domains.js +1 -0
  103. package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
  104. package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
  105. package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
  106. package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
  107. package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
  108. package/template/coding-task-manager/lib/feature-manifest.js +4 -0
  109. package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
  110. package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
  111. package/template/coding-task-manager/lib/fleet-hub.js +762 -0
  112. package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
  113. package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
  114. package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
  115. package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
  116. package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
  117. package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
  118. package/template/coding-task-manager/lib/fleet-update.js +798 -0
  119. package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
  120. package/template/coding-task-manager/lib/fs-watcher.js +58 -42
  121. package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
  122. package/template/coding-task-manager/lib/headless-term-service.js +84 -8
  123. package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
  124. package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
  125. package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
  126. package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
  127. package/template/coding-task-manager/lib/host-handoff.js +16 -19
  128. package/template/coding-task-manager/lib/host-stats.js +150 -3
  129. package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
  130. package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
  131. package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
  132. package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
  133. package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
  134. package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
  135. package/template/coding-task-manager/lib/hub-bridge.js +398 -0
  136. package/template/coding-task-manager/lib/idle-notify.js +491 -0
  137. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
  138. package/template/coding-task-manager/lib/instance-manifest.js +5 -1
  139. package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
  140. package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
  141. package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
  142. package/template/coding-task-manager/lib/landing/config.js +536 -0
  143. package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
  144. package/template/coding-task-manager/lib/landing/gate.js +360 -0
  145. package/template/coding-task-manager/lib/landing/git.js +344 -0
  146. package/template/coding-task-manager/lib/landing/lease.js +247 -0
  147. package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
  148. package/template/coding-task-manager/lib/landing/proof.js +223 -0
  149. package/template/coding-task-manager/lib/landing/queue.js +998 -0
  150. package/template/coding-task-manager/lib/landing/radar.js +489 -0
  151. package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
  152. package/template/coding-task-manager/lib/landing/state.js +263 -0
  153. package/template/coding-task-manager/lib/landing/stop.js +49 -0
  154. package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
  155. package/template/coding-task-manager/lib/landing/sync.js +456 -0
  156. package/template/coding-task-manager/lib/landing/train.js +885 -0
  157. package/template/coding-task-manager/lib/landing/window.js +57 -0
  158. package/template/coding-task-manager/lib/launch-environment.js +121 -0
  159. package/template/coding-task-manager/lib/launch-model-override.js +36 -10
  160. package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
  161. package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
  162. package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
  163. package/template/coding-task-manager/lib/lead-model-options.js +160 -3
  164. package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
  165. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
  166. package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
  167. package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
  168. package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
  169. package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
  170. package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
  171. package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
  172. package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
  173. package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
  174. package/template/coding-task-manager/lib/machine-registry.js +750 -5
  175. package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
  176. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
  177. package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
  178. package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
  179. package/template/coding-task-manager/lib/memory-join.js +337 -0
  180. package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
  181. package/template/coding-task-manager/lib/memory-sync.js +565 -0
  182. package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
  183. package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
  184. package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
  185. package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
  186. package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
  187. package/template/coding-task-manager/lib/model-availability.js +727 -0
  188. package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
  189. package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
  190. package/template/coding-task-manager/lib/model-id-rule.js +19 -0
  191. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
  192. package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
  193. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
  194. package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
  195. package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
  196. package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
  197. package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
  198. package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
  199. package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
  200. package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
  201. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
  202. package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
  203. package/template/coding-task-manager/lib/native-history-control.js +6 -4
  204. package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
  205. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
  206. package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
  207. package/template/coding-task-manager/lib/opencode-cli.js +480 -0
  208. package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
  209. package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
  210. package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
  211. package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
  212. package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
  213. package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
  214. package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
  215. package/template/coding-task-manager/lib/perf-summary.js +7 -0
  216. package/template/coding-task-manager/lib/perf-tracker.js +63 -2
  217. package/template/coding-task-manager/lib/project-config.js +7 -0
  218. package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
  219. package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
  220. package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
  221. package/template/coding-task-manager/lib/read-pool-client.js +89 -2
  222. package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
  223. package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
  224. package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
  225. package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
  226. package/template/coding-task-manager/lib/relay-client.js +57 -3
  227. package/template/coding-task-manager/lib/relink-audit.js +34 -5
  228. package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
  229. package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
  230. package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
  231. package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
  232. package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
  233. package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
  234. package/template/coding-task-manager/lib/restart-guard.js +18 -6
  235. package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
  236. package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
  237. package/template/coding-task-manager/lib/resume-admission.js +17 -3
  238. package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
  239. package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
  240. package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
  241. package/template/coding-task-manager/lib/runtime-contract.js +3 -1
  242. package/template/coding-task-manager/lib/schema-indexes.js +1 -0
  243. package/template/coding-task-manager/lib/session-context-locator.js +742 -0
  244. package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
  245. package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
  246. package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
  247. package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
  248. package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
  249. package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
  250. package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
  251. package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
  252. package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
  253. package/template/coding-task-manager/lib/session-create/response.js +7 -7
  254. package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
  255. package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
  256. package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
  257. package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
  258. package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
  259. package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
  260. package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
  261. package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
  262. package/template/coding-task-manager/lib/session-empty.js +13 -10
  263. package/template/coding-task-manager/lib/session-host-manager.js +60 -0
  264. package/template/coding-task-manager/lib/session-jobs.js +3 -1
  265. package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
  266. package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
  267. package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
  268. package/template/coding-task-manager/lib/session-park.js +738 -0
  269. package/template/coding-task-manager/lib/session-path-grant.js +13 -4
  270. package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
  271. package/template/coding-task-manager/lib/session-transport.js +17 -0
  272. package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
  273. package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
  274. package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
  275. package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
  276. package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
  277. package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
  278. package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
  279. package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
  280. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
  281. package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
  282. package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
  283. package/template/coding-task-manager/lib/submission-ack.js +90 -2
  284. package/template/coding-task-manager/lib/systemd-scope.js +115 -0
  285. package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
  286. package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
  287. package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
  288. package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
  289. package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
  290. package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
  291. package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
  292. package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
  293. package/template/coding-task-manager/lib/transcript-source.js +36 -4
  294. package/template/coding-task-manager/lib/transcript-store.js +9 -0
  295. package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
  296. package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
  297. package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
  298. package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
  299. package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
  300. package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
  301. package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
  302. package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
  303. package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
  304. package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
  305. package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
  306. package/template/coding-task-manager/lib/walle/turn.js +1 -1
  307. package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
  308. package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
  309. package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
  310. package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
  311. package/template/coding-task-manager/lib/walle-row-history.js +495 -0
  312. package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
  313. package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
  314. package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
  315. package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
  316. package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
  317. package/template/coding-task-manager/lib/ws/misc.js +1 -1
  318. package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
  319. package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
  320. package/template/coding-task-manager/oauth-proxy.js +112 -115
  321. package/template/coding-task-manager/package-lock.json +10 -94
  322. package/template/coding-task-manager/package.json +4 -3
  323. package/template/coding-task-manager/protocol/message-table.json +10 -0
  324. package/template/coding-task-manager/protocol/messages.js +10 -0
  325. package/template/coding-task-manager/protocol/ws-schema.json +20 -0
  326. package/template/coding-task-manager/protocol/ws-schema.md +2 -0
  327. package/template/coding-task-manager/public/css/app.css +170 -0
  328. package/template/coding-task-manager/public/css/walle-session.css +4 -0
  329. package/template/coding-task-manager/public/index.html +473 -243
  330. package/template/coding-task-manager/public/js/agent-command.js +86 -0
  331. package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
  332. package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
  333. package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
  334. package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
  335. package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
  336. package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
  337. package/template/coding-task-manager/public/js/background-work.js +196 -27
  338. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
  339. package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
  340. package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
  341. package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
  342. package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
  343. package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
  344. package/template/coding-task-manager/public/js/document-review-links.js +9 -1
  345. package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
  346. package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
  347. package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
  348. package/template/coding-task-manager/public/js/message-renderer.js +4 -3
  349. package/template/coding-task-manager/public/js/model-picker.js +3 -1
  350. package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
  351. package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
  352. package/template/coding-task-manager/public/js/pasted-content.js +236 -0
  353. package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
  354. package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
  355. package/template/coding-task-manager/public/js/prompts.js +11 -10
  356. package/template/coding-task-manager/public/js/protocol.js +10 -0
  357. package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
  358. package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
  359. package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
  360. package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
  361. package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
  362. package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
  363. package/template/coding-task-manager/public/js/stream-view.js +6 -5
  364. package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
  365. package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
  366. package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
  367. package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
  368. package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
  369. package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
  370. package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
  371. package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
  372. package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
  373. package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
  374. package/template/coding-task-manager/public/js/walle.js +6 -0
  375. package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
  376. package/template/coding-task-manager/public/m/app.css +140 -0
  377. package/template/coding-task-manager/public/m/app.js +507 -68
  378. package/template/coding-task-manager/public/m/index.html +17 -0
  379. package/template/coding-task-manager/public/m/machines.js +838 -4
  380. package/template/coding-task-manager/public/m/private-api.js +31 -1
  381. package/template/coding-task-manager/public/usage.html +1 -0
  382. package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
  383. package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
  384. package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
  385. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
  386. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
  387. package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
  388. package/template/coding-task-manager/server.js +1950 -11679
  389. package/template/coding-task-manager/session-integrity.js +64 -4
  390. package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
  391. package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
  392. package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
  393. package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
  394. package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
  395. package/template/coding-task-manager/workers/session-host-process.js +5 -5
  396. package/template/coding-task-manager/workers/watch-worker.js +105 -0
  397. package/template/coding-task-manager/workers/worktree-worker.js +168 -33
  398. package/template/ctm-relay/lib/protocol.js +14 -1
  399. package/template/package-lock.json +2 -2
  400. package/template/package.json +1 -1
  401. package/template/shared/backup-retention.js +82 -0
  402. package/template/shared/conversation-admission.js +2 -0
  403. package/template/shared/conversation-provenance.js +3 -7
  404. package/template/shared/conversation-storage-v2-contract.js +5 -0
  405. package/template/shared/linked-worktree.js +51 -0
  406. package/template/shared/macos-fda-target.js +57 -0
  407. package/template/shared/orphan-parents.js +55 -0
  408. package/template/shared/release-schema.json +2 -2
  409. package/template/shared/storage/contract.js +3 -0
  410. package/template/wall-e/adapters/imessage.js +12 -0
  411. package/template/wall-e/agent.js +71 -4
  412. package/template/wall-e/api-walle.js +21 -1
  413. package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
  414. package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
  415. package/template/wall-e/brain/brain-join.js +859 -0
  416. package/template/wall-e/brain/brain-sync-membership.js +20 -0
  417. package/template/wall-e/brain/brain-sync-store.js +131 -77
  418. package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
  419. package/template/wall-e/brain/brain-sync-v2.js +578 -0
  420. package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
  421. package/template/wall-e/brain/deterministic-id.js +51 -0
  422. package/template/wall-e/brain/memories.js +2 -2
  423. package/template/wall-e/brain/migrations.js +40 -6
  424. package/template/wall-e/brain/model-identity-migration.js +1 -1
  425. package/template/wall-e/brain/owner-call-whitelist.js +23 -7
  426. package/template/wall-e/brain/schema.js +45 -85
  427. package/template/wall-e/brain.js +171 -35
  428. package/template/wall-e/chat.js +3 -3
  429. package/template/wall-e/coding/agent-shell-env.js +7 -2
  430. package/template/wall-e/coding/prompt-bundle.js +66 -21
  431. package/template/wall-e/config/main-loop-exemptions.json +2 -2
  432. package/template/wall-e/http/admin-api.js +37 -0
  433. package/template/wall-e/http/gws-api.js +4 -0
  434. package/template/wall-e/http/helper-rules-api.js +7 -1
  435. package/template/wall-e/http/model-admin.js +8 -1
  436. package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
  437. package/template/wall-e/http/model-proxy-providers.js +174 -1
  438. package/template/wall-e/http/model-route-health.js +157 -0
  439. package/template/wall-e/http/sync-api.js +278 -464
  440. package/template/wall-e/jobs/job-runner.js +28 -1
  441. package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
  442. package/template/wall-e/lib/ctm-data-dir.js +26 -0
  443. package/template/wall-e/lib/derivation-home.js +147 -0
  444. package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
  445. package/template/wall-e/lib/helper-rules/grade.js +51 -8
  446. package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
  447. package/template/wall-e/lib/helper-rules/store.js +4 -2
  448. package/template/wall-e/lib/landing-mcp-tools.js +170 -0
  449. package/template/wall-e/lib/mcp-client-config.js +133 -14
  450. package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
  451. package/template/wall-e/lib/mcp-integration.js +58 -13
  452. package/template/wall-e/lib/parent-death.js +7 -1
  453. package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
  454. package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
  455. package/template/wall-e/llm/delegate-vendor-default.js +12 -5
  456. package/template/wall-e/llm/model-roles.js +1 -1
  457. package/template/wall-e/llm/native-delegate-selection.js +56 -8
  458. package/template/wall-e/llm/worker-delegate-args.js +72 -7
  459. package/template/wall-e/llm/worker-mcp-routing.js +66 -17
  460. package/template/wall-e/loops/brain-custom-writes.js +19 -0
  461. package/template/wall-e/loops/ingest.js +17 -1
  462. package/template/wall-e/loops/think.js +19 -4
  463. package/template/wall-e/mcp-contract.js +222 -6
  464. package/template/wall-e/mcp-protocol-contract.js +40 -5
  465. package/template/wall-e/mcp-server.js +128 -29
  466. package/template/wall-e/mcp-worker-schemas.js +5 -5
  467. package/template/wall-e/memory/ctm-context-client.js +85 -0
  468. package/template/wall-e/memory/ctm-session-context.js +9 -3
  469. package/template/wall-e/memory/hub-bridge-client.js +388 -0
  470. package/template/wall-e/memory/replica-origin.js +56 -0
  471. package/template/wall-e/memory/session-pool.js +135 -0
  472. package/template/wall-e/runtime/live-capabilities.js +8 -3
  473. package/template/wall-e/server.js +4 -2
  474. package/template/wall-e/shared/release-schema.json +2 -2
  475. package/template/wall-e/shared/sqlite-file-set.js +39 -0
  476. package/template/wall-e/shared/storage/contract.js +3 -0
  477. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  478. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
  479. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
  480. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
  481. package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
  482. package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
  483. package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
  484. package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
  485. package/template/wall-e/tools/chrome-automation.js +6 -0
  486. package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
  487. package/template/wall-e/workers/brain-owner-worker.js +18 -4
  488. package/template/wall-e/workers/mcp-gateway-process.js +5 -5
@@ -17,7 +17,17 @@
17
17
  // settings object plus counts. A matcher group can be mixed (a CTM hook
18
18
  // alongside a user's own hook in the same `hooks: [...]` array) — only the
19
19
  // CTM sub-entries inside it are ever touched; the group itself is dropped
20
- // only once every hook it held is gone. pruneClaudeHooks() is the fully
20
+ // only once every hook it held is gone.
21
+ //
22
+ // OWN-PORT ENTRIES ARE NEVER STALE (D-5): an entry on THIS CTM's own port is
23
+ // its own install, possibly recorded at a path that no longer exists (a repo
24
+ // rename/move). It is kept so the post-prune refresh step
25
+ // (agent-hooks-boot-prune.js refreshOutdatedHooks — which rewrites `outdated`
26
+ // entries only) repairs it to the current path, instead of the prune deleting it
27
+ // and leaving the host with no status hooks at all. Design:
28
+ // docs/remote-session-history-reads-and-box-status-hooks-2026-10-26.html WP-3/D-5.
29
+ //
30
+ // pruneClaudeHooks() is the fully
21
31
  // async I/O wrapper that reads the real file, probes real ports over
22
32
  // loopback, and writes back atomically only when something actually
23
33
  // changed — no sync fs calls anywhere on this path, since it runs on the
@@ -80,14 +90,27 @@ function ctmHooksInGroup(group) {
80
90
  /**
81
91
  * Pure prune planner. Never touches the filesystem or network — `scriptExists`
82
92
  * and `portListening` are injected predicates so this stays unit-testable.
83
- * Within one matcher group: a CTM hook is removed when `scriptExists(scriptPath)
84
- * === false`, or when its (non-own) port has `portListening(port) === false`;
85
- * any non-CTM hook in the same group is never touched. A group that becomes
86
- * empty is dropped. A group made up ENTIRELY of CTM hooks (no user hook mixed
87
- * in) is additionally deduped against other such groups with the same
88
- * matcher + same (command, timeout) hook list, keeping the first. Drops an
89
- * event key entirely only if every group it held was pure-CTM and all were
90
- * removed.
93
+ * Within one matcher group: a CTM hook on an OTHER port is removed when
94
+ * `scriptExists(scriptPath) === false` or `portListening(port) === false`; any
95
+ * non-CTM hook in the same group is never touched. A group that becomes empty is
96
+ * dropped. A group made up ENTIRELY of CTM hooks (no user hook mixed in) is
97
+ * additionally deduped against other such groups with the same matcher + same
98
+ * (command, timeout) hook list, keeping the first. Drops an event key entirely
99
+ * only if every group it held was pure-CTM and all were removed.
100
+ *
101
+ * OWN-PORT RULE: a hook whose `port === ownPort` is never stale — not even when
102
+ * its script path is gone. Such an entry is this CTM's OWN install, recorded at
103
+ * some earlier path, and `agent-hooks-installer.js` `isOwnClaudeHook()` treats
104
+ * ANY checkout's claude-hook.js on this port as ours ("one CTM per port, last
105
+ * installer wins"), so `hookStatus` classifies it `outdated`, never foreign.
106
+ * Deleting it here is what incident 3 (2026-10-19) did after the repo rename
107
+ * `claude-task-manager -> coding-task-manager`: the prune removed all ten
108
+ * own-port entries, the state flipped to `missing`, and the post-prune
109
+ * `refreshOutdatedHooks` (which only rewrites `outdated`) then had nothing left
110
+ * to repair — `~/.claude/settings.json` ended at `"hooks": {}`. Keeping the
111
+ * entry lets that existing refresh step rewrite it to the current path, so every
112
+ * future path move self-repairs at the next boot. See design
113
+ * docs/remote-session-history-reads-and-box-status-hooks-2026-10-26.html WP-3 / D-5.
91
114
  */
92
115
  function planPruneClaudeHooks(data, { scriptExists, portListening, ownPort }) {
93
116
  let removedStale = 0;
@@ -119,8 +142,11 @@ function planPruneClaudeHooks(data, { scriptExists, portListening, ownPort }) {
119
142
  const info = classifySingleHook(hk);
120
143
  if (!info) { sawNonCtm = true; survivingHooks.push(hk); continue; }
121
144
  sawCtm = true;
122
- const isStale = scriptExists(info.scriptPath) === false
123
- || (info.port !== ownPort && portListening(info.port) === false);
145
+ // D-5: an OTHER-port entry is stale on a missing script or a dead port; an own-port
146
+ // entry is this CTM's own install at a possibly-old path and is left for the
147
+ // post-prune refresh to rewrite (see the own-port rule above). Never mark it stale.
148
+ const isStale = info.port !== ownPort
149
+ && (scriptExists(info.scriptPath) === false || portListening(info.port) === false);
124
150
  if (isStale) { removedStale++; changed = true; removed.push({ event: eventName, command: hk.command, reason: 'stale' }); continue; }
125
151
  survivingHooks.push(hk);
126
152
  }
@@ -0,0 +1,105 @@
1
+ // Per-port POSIX sh shim that Codex's `~/.codex/config.toml` names as its hook command.
2
+ //
3
+ // Why a shim and not the script path: Codex pins hook trust to a sha256 of the exact `command`
4
+ // text (design docs/codex-hook-stable-shim-trust-safe-self-repair-2026-11-01.html §3). A repo move
5
+ // that rewrites that text flips the hook to "Modified", Codex skips it, and every hosted Codex TUI
6
+ // shows a "Hooks need review" prompt — which the next move repeats. So the config names a path that
7
+ // never moves (`<home>/.walle/bin/ctm-hook-<port>`) and CTM rewrites only the shim BODY at each
8
+ // primary boot. Codex hashes the command text, which stays byte-identical.
9
+ //
10
+ // POSIX sh, not node: the failure this fixes is node printing MODULE_NOT_FOUND before any CTM code
11
+ // runs, so the `[ -f ]` check has to happen before node is involved.
12
+ //
13
+ // Exit 0, never 1, when the target is missing: Codex reports any non-zero exit other than 2 as
14
+ // "Hook failed" on every tool call (post_tool_use.rs:281), and this hook is a passive bridge
15
+ // (bin/codex-workspace-hook.js: "tracking never blocks coding"). Drift is reported by hookStatus and
16
+ // one stderr line, never by breaking the TUI.
17
+
18
+ const fs = require('fs');
19
+ const os = require('os');
20
+ const path = require('path');
21
+
22
+ const HOOK_BIN_DIR = path.join(path.resolve(__dirname, '..'), 'bin');
23
+
24
+ /** The two Codex bins CTM installs (the writers live in lib/agent-hooks-codex-toml.js). */
25
+ const SHIM_TARGETS = Object.freeze(['codex-workspace-hook', 'codex-notify']);
26
+
27
+ /** Absolute shim path for a port. `homeDir` defaults to `os.homedir()`, resolved at CALL time, so a
28
+ * test that swaps `process.env.HOME` in `before()` resolves under the temp home. */
29
+ function hookShimPath(port, { homeDir = os.homedir() } = {}) {
30
+ return path.join(homeDir, '.walle', 'bin', `ctm-hook-${port}`);
31
+ }
32
+
33
+ /** POSIX single-quote quoting: every interpolated value goes through this before it lands in the body. */
34
+ const sq = (value) => `'${String(value).replace(/'/g, "'\\''")}'`;
35
+
36
+ /** Escape for a double-quoted shell string (the two diagnostics lines only). */
37
+ const dq = (value) => String(value).replace(/[\\"$`]/g, (c) => `\\${c}`);
38
+
39
+ /** Exact shim body. `binDir` = absolute CTM bin dir; `nodePath` = `process.execPath`. Pure. */
40
+ function renderHookShim({ port, binDir, nodePath }) {
41
+ const name = `ctm-hook-${dq(port)}`;
42
+ return [
43
+ '#!/bin/sh',
44
+ `# Written by CTM (port ${dq(port)}) at each primary boot. Do not edit; the config.toml hook names`,
45
+ "# this file so a CTM checkout move never changes Codex's trusted hook command.",
46
+ `BIN=${sq(binDir)}`,
47
+ `NODE=${sq(nodePath)}`,
48
+ `case "$1" in ${SHIM_TARGETS.join('|')}) ;; *) echo "${name}: unknown target $1" >&2; exit 0;; esac`,
49
+ 'SCRIPT="$BIN/$1.js"; shift',
50
+ `[ -f "$SCRIPT" ] || { echo "${name}: $SCRIPT missing; CTM refreshes this shim at its next boot" >&2; exit 0; }`,
51
+ '[ -x "$NODE" ] || NODE=node',
52
+ 'exec "$NODE" "$SCRIPT" "$@"',
53
+ '',
54
+ ].join('\n');
55
+ }
56
+
57
+ /** Read the shim body, or null when it does not exist. */
58
+ function readShimBody(target) {
59
+ try { return fs.readFileSync(target, 'utf8'); }
60
+ catch (e) {
61
+ if (e.code === 'ENOENT') return null; // expected: the shim may not have been written yet
62
+ throw e; // RETHROW: an unreadable shim is not "missing" — never treat it as absent
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Write the shim iff its body differs (atomic tmp+rename, mode 0755, `mkdir -p` the dir).
68
+ * Returns `{ path, changed }`. Throws on I/O failure (RETHROW: `install()` must not write a
69
+ * config.toml that names a shim it could not create).
70
+ */
71
+ function ensureHookShim({ port, binDir = HOOK_BIN_DIR, nodePath = process.execPath, homeDir } = {}) {
72
+ const target = hookShimPath(port, { homeDir });
73
+ const body = renderHookShim({ port, binDir, nodePath });
74
+ if (readShimBody(target) === body) return { path: target, changed: false };
75
+ const tmpPath = `${target}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
76
+ try {
77
+ fs.mkdirSync(path.dirname(target), { recursive: true });
78
+ fs.writeFileSync(tmpPath, body, { mode: 0o755 });
79
+ fs.renameSync(tmpPath, target);
80
+ } catch (error) {
81
+ // RETHROW: clean up the orphaned tmp file, then surface the original error.
82
+ try { fs.unlinkSync(tmpPath); } catch { /* expected: tmp file may already be gone */ }
83
+ throw error;
84
+ }
85
+ fs.chmodSync(target, 0o755);
86
+ return { path: target, changed: true };
87
+ }
88
+
89
+ /** `'current' | 'stale' | 'missing'` — compares the on-disk body to `renderHookShim()`. */
90
+ function hookShimState({ port, binDir = HOOK_BIN_DIR, nodePath = process.execPath, homeDir } = {}) {
91
+ const body = readShimBody(hookShimPath(port, { homeDir }));
92
+ if (body === null) return 'missing';
93
+ return body === renderHookShim({ port, binDir, nodePath }) ? 'current' : 'stale';
94
+ }
95
+
96
+ /** Remove the shim (uninstall). Returns true when a file was removed. */
97
+ function removeHookShim({ port, homeDir } = {}) {
98
+ try { fs.unlinkSync(hookShimPath(port, { homeDir })); return true; }
99
+ catch (e) {
100
+ if (e.code === 'ENOENT') return false; // expected: the shim was never written, or is already gone
101
+ throw e; // RETHROW: report a shim we could not remove
102
+ }
103
+ }
104
+
105
+ module.exports = { hookShimPath, renderHookShim, ensureHookShim, hookShimState, removeHookShim, SHIM_TARGETS };
@@ -5,6 +5,11 @@
5
5
  // - agent detection (command matching)
6
6
  // Port of /tmp/clideck/agent-presets.json, adapted for CTM and the CTM_PORT env var.
7
7
 
8
+ const fs = require('fs');
9
+ const os = require('os');
10
+ const path = require('path');
11
+ const { agentTypeFromCommandWord } = require('../public/js/agent-command');
12
+
8
13
  /**
9
14
  * @typedef {Object} AgentPreset
10
15
  * @property {string} presetId - stable identifier ('claude-code', 'codex', 'gemini-cli')
@@ -134,10 +139,15 @@ const PRESETS = {
134
139
  },
135
140
  };
136
141
 
142
+ // S-4 (D-5): the detector's agent type maps to a preset id; the loop below stays the fallback.
143
+ const PRESET_BY_AGENT = { claude: 'claude-code', codex: 'codex', gemini: 'gemini-cli', opencode: 'opencode', cursor: 'cursor' };
144
+
137
145
  /** Detect which preset applies to a given spawn command (same contract as server.js's detectAgentType). */
138
146
  function detectPresetId(cmd) {
139
147
  if (!cmd) return null;
140
148
  const s = String(cmd);
149
+ const byWord = PRESET_BY_AGENT[agentTypeFromCommandWord(s)];
150
+ if (byWord && PRESETS[byWord]) return byWord;
141
151
  for (const [id, p] of Object.entries(PRESETS)) {
142
152
  if (p.commandRegex.test(s) || s.includes(p.presetId === 'claude-code' ? 'claude' : p.presetId === 'gemini-cli' ? 'gemini' : p.presetId)) {
143
153
  return id;
@@ -200,10 +210,19 @@ const WORKER_STRIPPED_TOKEN_KEYS = Object.freeze(['WALLE_CTM_TOKEN', 'WALL_E_API
200
210
  // sessions keep all of it.
201
211
  const WORKER_STRIPPED_CTM_API_KEYS = Object.freeze(['CTM_SESSION_MEMORY_API_BASE_URL', 'CTM_API_BASE_URL', 'CTM_BASE_URL']);
202
212
 
213
+ // WP-14 (docs/deepseek-harness-acp-agent-2026-10-28.html C-8/W-7, T-26): a delegated worker whose
214
+ // CLI is the DeepSeek Harness (`dsh`, an ACP child, not a PTY) is a worker like any other -- it
215
+ // returns a report to its lead and never drives CTM -- so it inherits the same strip. Its launch env
216
+ // carries the mark (`CTM_WORKER_AGENT: 'dsh'`, resolve-launch-params.js), and the dsh create path
217
+ // builds the child env from the create request's own resolved launch env
218
+ // (server.js `buildLaunchEnv` -> lib/session-create/dsh-session.js), which IS this object, so the
219
+ // strip is reached without a server.js change.
220
+ const WORKER_AGENT_TYPES = Object.freeze(['claude', 'codex', 'dsh']);
221
+
203
222
  function sanitizeInheritedAgentEnv(env, explicitWorkerAgent) {
204
223
  if (!env || typeof env !== 'object') return env;
205
224
  for (const key of INHERITED_AGENT_ENV_KEYS) delete env[key];
206
- if (explicitWorkerAgent === 'claude' || explicitWorkerAgent === 'codex') {
225
+ if (WORKER_AGENT_TYPES.includes(explicitWorkerAgent)) {
207
226
  for (const key of WORKER_STRIPPED_TOKEN_KEYS) delete env[key];
208
227
  for (const key of WORKER_STRIPPED_CTM_API_KEYS) delete env[key];
209
228
  env.WALLE_CTM_API = '0';
@@ -245,12 +264,76 @@ function buildTelemetryEnv(ctmSessionId, cmd, port, baseEnv = process.env) {
245
264
  return env;
246
265
  }
247
266
 
267
+ // ── Claude renderer choice (WP-2, restore-seed-alt-screen-trap-2026-10-27.html R-4) ──
268
+ // Claude Code 2.1.312 has a "fullscreen boot canary": several fullscreen starts that die
269
+ // before becoming healthy make it write `fullscreenAutoDisabled` to ~/.claude.json, after
270
+ // which every later Claude renders inline. CTM's crash-restore storms can trip that canary
271
+ // through no fault of the user's — and it silently flips the renderer the user chose. Claude
272
+ // names its own override: with CLAUDE_CODE_NO_FLICKER truthy the canary is bypassed and the
273
+ // fullscreen renderer is used outright. CTM therefore restates the user's own choice through
274
+ // that override, and only when the user's settings already say fullscreen. CTM never writes
275
+ // any Claude config.
276
+
277
+ /**
278
+ * The renderer env for a resolved Claude user setting.
279
+ * @param {{ tui?: unknown }|null|undefined} claudeSettings parsed user Claude settings, or null
280
+ * @returns {{ CLAUDE_CODE_NO_FLICKER?: '1' }} {CLAUDE_CODE_NO_FLICKER:'1'} iff
281
+ * claudeSettings.tui === 'fullscreen' (exact match), else {}
282
+ */
283
+ function claudeRendererEnv(claudeSettings) {
284
+ if (claudeSettings && typeof claudeSettings === 'object'
285
+ && !Array.isArray(claudeSettings) && claudeSettings.tui === 'fullscreen') {
286
+ return { CLAUDE_CODE_NO_FLICKER: '1' };
287
+ }
288
+ return {};
289
+ }
290
+
291
+ /**
292
+ * Parsed Claude user settings for a CHILD env, or null on any error.
293
+ * The path is `<env.CLAUDE_CONFIG_DIR || <env.HOME || os.homedir()>/.claude>/settings.json`
294
+ * — the Claude process reads its config from its own env, so the caller passes the child env.
295
+ * @param {NodeJS.ProcessEnv|Object} env
296
+ * @returns {Object|null}
297
+ */
298
+ function readClaudeUserSettings(env) {
299
+ try {
300
+ const e = env && typeof env === 'object' ? env : {};
301
+ const configDir = e.CLAUDE_CONFIG_DIR || path.join(e.HOME || os.homedir(), '.claude');
302
+ const parsed = JSON.parse(fs.readFileSync(path.join(configDir, 'settings.json'), 'utf8'));
303
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
304
+ return parsed;
305
+ } catch {
306
+ /* expected: a missing/unreadable/corrupt Claude settings file is normal — the renderer is Claude's call */
307
+ return null;
308
+ }
309
+ }
310
+
311
+ /**
312
+ * The env additions for spawning `cmd` with child env `env`.
313
+ * - {} unless the command is Claude Code;
314
+ * - {} when `env` already defines CLAUDE_CODE_NO_FLICKER (any value, even '' or '0' — an
315
+ * explicit user/launch env always wins);
316
+ * - else claudeRendererEnv(readClaudeUserSettings(env)).
317
+ * @param {string} cmd
318
+ * @param {NodeJS.ProcessEnv|Object} env
319
+ * @returns {{ CLAUDE_CODE_NO_FLICKER?: '1' }}
320
+ */
321
+ function buildClaudeRendererLaunchEnv(cmd, env) {
322
+ if (detectPresetId(cmd) !== 'claude-code') return {};
323
+ const e = env && typeof env === 'object' ? env : {};
324
+ if (Object.prototype.hasOwnProperty.call(e, 'CLAUDE_CODE_NO_FLICKER')) return {};
325
+ return claudeRendererEnv(readClaudeUserSettings(e));
326
+ }
327
+
248
328
  module.exports = {
249
329
  PRESETS,
250
330
  detectPresetId,
251
331
  getPreset,
252
332
  buildTelemetryEnv,
253
333
  sanitizeInheritedAgentEnv,
334
+ buildClaudeRendererLaunchEnv,
335
+ readClaudeUserSettings,
336
+ claudeRendererEnv,
254
337
  WORKER_STRIPPED_TOKEN_KEYS,
255
338
  WORKER_STRIPPED_CTM_API_KEYS,
256
339
  };
@@ -178,6 +178,8 @@ function _logJobEnd(opts, job, onJobEnd) {
178
178
  `version=${versions}`,
179
179
  `durationMs=${Math.max(0, (job.finishedAt || Date.now()) - job.startedAt)}`,
180
180
  `outcome=${job.outcome || 'none'}`,
181
+ // AC-4d: 0 unless the plan named live sessions for a live-sensitive install mode.
182
+ `liveSessions=${Number(job.liveSessions) || 0}`,
181
183
  `error=${job.error || 'none'}`,
182
184
  ].join(' '));
183
185
  if (typeof onJobEnd !== 'function') return;
@@ -187,11 +189,18 @@ function _logJobEnd(opts, job, onJobEnd) {
187
189
  }
188
190
 
189
191
  function createJobRunner({ getAgentVersionStatus, buildUpgradePlan, onJobEnd }) {
190
- async function startUpgradeJob(agentId, opts = {}) {
192
+ async function startUpgradeJob(agentId, opts = {}, { confirmLive = false } = {}) {
191
193
  _pruneUpgradeJobs();
192
194
  // Re-check first so "before" is never from a stale cache.
193
195
  const status = opts.statusPayload || await getAgentVersionStatus({ ...opts, force: true });
194
196
  const plan = buildUpgradePlan(agentId, status);
197
+ // WP-4 (D-9): a live-sensitive install replaces files a running session executes from. The
198
+ // automatic tick defers for this reason; a click must say so out loud first. The refusal starts
199
+ // no job, so nothing is written to the job map and no updater is spawned.
200
+ const liveSessions = Array.isArray(plan.liveSessions) ? plan.liveSessions : [];
201
+ if (liveSessions.length && confirmLive !== true) {
202
+ return { ok: false, error: 'upgrade_live_sessions', liveSessions };
203
+ }
195
204
  const existing = _findRunningUpgradeJob(plan.agent);
196
205
  if (existing) {
197
206
  const snapshot = _upgradeJobSnapshot(existing);
@@ -211,6 +220,8 @@ function createJobRunner({ getAgentVersionStatus, buildUpgradePlan, onJobEnd })
211
220
  command: plan.command,
212
221
  args: plan.args.slice(),
213
222
  plan,
223
+ // AC-4d: the count the plan saw at start, so a broken session is attributable after the fact.
224
+ liveSessions: liveSessions.length,
214
225
  pid: 0,
215
226
  startedAt: now,
216
227
  updatedAt: now,
@@ -8,11 +8,16 @@ const { execFile } = require('child_process');
8
8
  const agentCliCache = require('./agent-cli-cache');
9
9
  const { detectInstallSource, classifyInstall, resolveUpgrade } = require('./agent-upgrade-planner');
10
10
  const { AGENT_DEFINITIONS, DEFAULT_AGENT_IDS } = require('./agent-definitions');
11
+ // WP-4 (S-13): the live-sensitive install modes, shared with the automatic-update tick.
12
+ const { LIVE_SENSITIVE_MODES } = require('./agent-auto-update');
11
13
  const jobs = require('./agent-upgrade-jobs');
12
14
  const { redactOutput, getUpgradeJob, listUpgradeJobs, _upgradeJobs, _upgradeEnv } = jobs;
13
15
 
14
- // 4: rows carry qualification / installedQualification (WP-2 of the Codex harness qualification design).
15
- const CACHE_VERSION = 4;
16
+ // History: 4 added per-row qualification fields, 5 added a qualification-table revision stamp so a
17
+ // moved table recomputed a cached row. 6 removes both (docs/codex-upgrades-without-version-approval-2026-10-28.html
18
+ // WP-1/D-3): a row carries no per-version approval state, so a schema-4/5 cache -- including one
19
+ // still holding qualification rows -- is recomputed and can never be served.
20
+ const CACHE_VERSION = 6;
16
21
  const DEFAULT_TTL_MS = 6 * 60 * 60 * 1000;
17
22
  const DEFAULT_REGISTRY_BASE_URL = 'https://registry.npmjs.org';
18
23
  const DEFAULT_VERSION_TIMEOUT_MS = 2500;
@@ -36,10 +41,8 @@ function _writeJson(filePath, payload) {
36
41
  try { fs.chmodSync(filePath, 0o600); } catch {}
37
42
  }
38
43
 
39
- // normalizeSemver/compareSemver live in the leaf module lib/semver-compare.js (shared with the
40
- // Codex qualified-version table, which this service reads back for its status row).
44
+ // normalizeSemver/compareSemver live in the leaf module lib/semver-compare.js.
41
45
  const { normalizeSemver, compareSemver } = require('./semver-compare');
42
- const { codexQualification } = require('./codex-harness-qualification');
43
46
 
44
47
  function parseVersionText(stdout, stderr) {
45
48
  const primary = String(stdout || '');
@@ -210,8 +213,21 @@ function _deriveStatus(installedVersion, latestVersion, available) {
210
213
  return { status: 'current', hasUpdate: false };
211
214
  }
212
215
 
216
+ // WP-12 (AC-12a): a definition may name the install it owns (`def.installIdentity`). Path discovery is
217
+ // name-based, and one of these names is not unique on this host -- homebrew/core's `dsh` is the
218
+ // unrelated "Dancer's shell" -- so an entry whose realpath (or path) is outside the owning package is
219
+ // NOT this CLI. Such an entry reads as not installed, which also keeps its `--version` unprobed: the
220
+ // wrong tool's version must never render as this agent's row. The rule is the one
221
+ // lib/hermetic-agent-launch-guard.js applies to the dsh entrypoint.
222
+ function _installIdentityHolds(def, entry) {
223
+ if (!def.installIdentity || !entry || !entry.available) return true;
224
+ // The realpath decides when discovery resolved one: a symlink's own path proves nothing.
225
+ return def.installIdentity.test(String(entry.realpath || entry.path || ''));
226
+ }
227
+
213
228
  async function _checkAgent(def, availability, opts) {
214
- const entry = availability && availability.agents ? availability.agents[def.cli] : null;
229
+ const discovered = availability && availability.agents ? availability.agents[def.cli] : null;
230
+ const entry = _installIdentityHolds(def, discovered) ? discovered : null;
215
231
  const available = !!(entry && entry.available && !entry.stale);
216
232
  let versionResult = { ok: false, stdout: '', stderr: '', error: '' };
217
233
  let installedVersion = '';
@@ -251,10 +267,6 @@ async function _checkAgent(def, availability, opts) {
251
267
  manual: upgrade.manual,
252
268
  versionError: available && !installedVersion ? (versionResult.error || 'version_parse_failed') : '',
253
269
  latestError: latest.error || '',
254
- // WP-2 (D-6): why a Codex version may not be switchable as a lead (the row says so in the UI);
255
- // every other agent is not gated by the table.
256
- qualification: def.cli === 'codex' ? codexQualification(latest.version) : { state: 'not_applicable' },
257
- installedQualification: def.cli === 'codex' ? codexQualification(installedVersion) : { state: 'not_applicable' },
258
270
  };
259
271
  }
260
272
 
@@ -297,6 +309,8 @@ async function getAgentVersionStatus(opts = {}) {
297
309
  const ttlMs = Number(opts.ttlMs) || DEFAULT_TTL_MS;
298
310
  if (!opts.force && opts.cacheFile) {
299
311
  const cached = _readJson(opts.cacheFile);
312
+ // A hit is schema + TTL + agents only: nothing in this status is pinned to a build-time table,
313
+ // so there is no second stamp to compare (a schema-5 row recomputes below on `version`).
300
314
  if (cached && cached.version === CACHE_VERSION && cached.generatedAt && now - cached.generatedAt < ttlMs && cached.agents) {
301
315
  return { ...cached, cached: true };
302
316
  }
@@ -316,7 +330,39 @@ function _getDefinition(agentId) {
316
330
  return def;
317
331
  }
318
332
 
319
- function buildUpgradePlan(agentId, statusPayload) {
333
+ // WP-4 (D-9): the live-session predicate the auto tick already uses, injected by server.js from the
334
+ // same derivation (lib/agent-auto-update.js liveAgentIds/liveSessionsFor). Uninjected (a dev
335
+ // instance, a unit test) reads as "no live sessions", which is the pre-WP-4 plan exactly.
336
+ let _liveSessions = {
337
+ liveSessionAgents: () => new Set(),
338
+ liveSessionsFor: () => [],
339
+ };
340
+
341
+ /** server.js injects `{ liveSessionAgents, liveSessionsFor }`; no argument restores the no-op default. */
342
+ function configureLiveSessions(deps) {
343
+ _liveSessions = {
344
+ liveSessionAgents: typeof (deps && deps.liveSessionAgents) === 'function' ? deps.liveSessionAgents : () => new Set(),
345
+ liveSessionsFor: typeof (deps && deps.liveSessionsFor) === 'function' ? deps.liveSessionsFor : () => [],
346
+ };
347
+ }
348
+
349
+ /** `[{ id, title, agent }]` for the live sessions of this agent; `[]` when nothing is live. */
350
+ function _liveSessionsFor(def, deps) {
351
+ const live = deps || _liveSessions;
352
+ let agents;
353
+ // HANDLE: naming the sessions is advisory — a broken session reader must never fail the plan.
354
+ try { agents = live.liveSessionAgents(); } catch (e) { return []; }
355
+ if (!agents || typeof agents.has !== 'function' || !agents.has(def.id)) return [];
356
+ try {
357
+ const sessions = live.liveSessionsFor(def.id);
358
+ return Array.isArray(sessions) ? sessions : [];
359
+ } catch (e) {
360
+ // HANDLE: same — an unreadable session list degrades to "nothing to name".
361
+ return [];
362
+ }
363
+ }
364
+
365
+ function buildUpgradePlan(agentId, statusPayload, liveDeps) {
320
366
  const def = _getDefinition(agentId);
321
367
  const row = statusPayload && statusPayload.agents ? statusPayload.agents[def.id] : null;
322
368
  if (!row || !row.available) throw new Error('agent_not_available');
@@ -331,6 +377,9 @@ function buildUpgradePlan(agentId, statusPayload) {
331
377
  const args = exec.args.slice();
332
378
  const commandKind = row.upgradeMode || '';
333
379
  const commandLabel = row.upgradeCommand || '';
380
+ // WP-4 (D-9): an install mode whose upgrade replaces files a running session executes from.
381
+ const liveSensitive = LIVE_SENSITIVE_MODES.has(commandKind);
382
+ const liveSessions = liveSensitive ? _liveSessionsFor(def, liveDeps) : [];
334
383
  return {
335
384
  ok: true,
336
385
  agent: def.id,
@@ -345,6 +394,8 @@ function buildUpgradePlan(agentId, statusPayload) {
345
394
  args,
346
395
  commandKind,
347
396
  commandLabel,
397
+ liveSensitive,
398
+ liveSessions,
348
399
  changes: [
349
400
  { description: row.latestVersion ? `Upgrade ${def.name} from ${row.installedVersion || 'unknown'} to ${row.latestVersion}` : `Run ${def.name}'s updater to check for the latest version` },
350
401
  { description: `Command: ${commandLabel || [path.basename(command)].concat(args).join(' ')}` },
@@ -352,9 +403,20 @@ function buildUpgradePlan(agentId, statusPayload) {
352
403
  };
353
404
  }
354
405
 
406
+ /** WP-4 (D-9): the shared refusal shape for a live-sensitive upgrade the caller has not confirmed. */
407
+ function _liveSessionsRefusal(plan) {
408
+ const liveSessions = Array.isArray(plan.liveSessions) ? plan.liveSessions : [];
409
+ if (!liveSessions.length) return null;
410
+ return { ok: false, error: 'upgrade_live_sessions', liveSessions };
411
+ }
412
+
355
413
  async function upgradeAgentVersion(agentId, opts = {}) {
356
414
  const status = opts.statusPayload || await getAgentVersionStatus({ ...opts, force: false });
357
415
  const plan = buildUpgradePlan(agentId, status);
416
+ if (opts.confirmLive !== true) {
417
+ const refusal = _liveSessionsRefusal(plan);
418
+ if (refusal) return refusal;
419
+ }
358
420
  const result = await runCommand(plan.command, plan.args, {
359
421
  execFileImpl: opts.execFileImpl,
360
422
  timeoutMs: opts.upgradeTimeoutMs || DEFAULT_UPGRADE_TIMEOUT_MS,
@@ -398,6 +460,7 @@ module.exports = {
398
460
  checkAgentVersions,
399
461
  getAgentVersionStatus,
400
462
  buildUpgradePlan,
463
+ configureLiveSessions,
401
464
  upgradeAgentVersion,
402
465
  startUpgradeJob,
403
466
  setUpgradeJobEndHandler,
@@ -50,7 +50,9 @@ function queryAllSessionsData(d) {
50
50
  CASE
51
51
  WHEN LOWER(COALESCE(a.provider, '')) = 'walle'
52
52
  THEN ''
53
- ELSE COALESCE(NULLIF(a.modified_at, ''), a.updated_at, a.created_at, '')
53
+ ELSE COALESCE(NULLIF(a.modified_at, ''),
54
+ strftime('%Y-%m-%dT%H:%M:%SZ', a.updated_at),
55
+ strftime('%Y-%m-%dT%H:%M:%SZ', a.created_at), '')
54
56
  END as last_message_at
55
57
  ${startupSelect}
56
58
  FROM ctm_sessions c
@@ -101,7 +103,9 @@ function queryAllSessionsData(d) {
101
103
  CASE
102
104
  WHEN LOWER(COALESCE(a.provider, '')) = 'walle'
103
105
  THEN ''
104
- ELSE COALESCE(NULLIF(a.modified_at, ''), a.updated_at, a.created_at, '')
106
+ ELSE COALESCE(NULLIF(a.modified_at, ''),
107
+ strftime('%Y-%m-%dT%H:%M:%SZ', a.updated_at),
108
+ strftime('%Y-%m-%dT%H:%M:%SZ', a.created_at), '')
105
109
  END as last_message_at
106
110
  FROM agent_sessions a
107
111
  ORDER BY