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
@@ -29,6 +29,7 @@ const SERVER_INSTRUCTIONS = [
29
29
  "Keep the lead's own model and account.",
30
30
  'Read-only census and review work can be delegated the same way with `worker_profile: "review"`: the worker cannot edit files, and you keep the verdict.',
31
31
  'Wait on workers with walle_worker_wait and omit wait_ms; it wakes on a finished, failed, resumed or stuck worker, on a question, and when your user types -- never sleep-and-check or wrap it in a short-yield script.',
32
+ 'To integrate finished work on a repo CTM manages, call walle_landing_submit; never merge or fast-forward the target yourself. The same action from a shell is `land submit`; `walle_landing_status` / `walle_landing_wait` report the queue.',
32
33
  '',
33
34
  'This guidance is advice, not enforcement: it never authorizes spawning extra agents on your own initiative, and Wall-E cannot intercept or reroute native `spawn_agent` calls you make without it.',
34
35
  '',
@@ -60,13 +61,36 @@ const EXPLORE_GUIDANCE = [
60
61
  "- Trust the report's file:line facts; re-read only the lines you will change.",
61
62
  ].join('\n');
62
63
 
64
+ // WP-2 (design-hub-bridge-box-session-awareness-2026-10-31.html §5 R-4, §6.3, §8 WP-2): "where you
65
+ // run". When the stdio proxy's initialize finds this session is a BOX session (R-1), the received
66
+ // instructions start with this one block, before SERVER_INSTRUCTIONS. Codex reads only the first 512
67
+ // characters as server-wide guidance, so the block is capped there (BOX_CONTEXT_MAX_CHARS) and the
68
+ // two names are truncated to 48 characters each; the routing facts come first, the shared guidance
69
+ // follows unchanged.
70
+ const BOX_CONTEXT_MAX_CHARS = 512;
71
+ const BOX_CONTEXT_NAME_MAX_CHARS = 48;
72
+
73
+ function buildBoxContextBlock({ boxName = '', hubName = '', hubConnected } = {}) {
74
+ const box = String(boxName == null ? '' : boxName).slice(0, BOX_CONTEXT_NAME_MAX_CHARS);
75
+ const hub = String(hubName == null ? '' : hubName).slice(0, BOX_CONTEXT_NAME_MAX_CHARS);
76
+ const text = `Machine context: this session runs on the box '${box}'; the user works from the hub '${hub}'. `
77
+ + 'Your Bash/Read/Edit run on the box. walle_get_session takes a session link or id from any machine (hub or '
78
+ + 'box); hub_session_read reads the hub, hub_list/hub_read_file/hub_exec reach it (the user grants access), and '
79
+ + "hub_mcp_list_tools/hub_mcp_call drive the hub's browser. Try them before saying the hub is unreachable."
80
+ // R-4: the link state is a fact, not a guess -- said plainly, and only when it is known to be down.
81
+ + (hubConnected === false ? ' The hub link is down right now; calls answer hub_unreachable.' : '');
82
+ return text.slice(0, BOX_CONTEXT_MAX_CHARS);
83
+ }
84
+
63
85
  // The one builder both transports call with the state their reader resolved; 'off' (and anything
64
86
  // unrecognized) serves SERVER_INSTRUCTIONS byte-for-byte, so the guidance is switchable per lead
65
- // harness without a restart and without a second copy of the text.
66
- function buildServerInstructions({ explore = 'on' } = {}) {
67
- return (explore === 'on' || explore === 'probe')
87
+ // harness without a restart and without a second copy of the text. WP-2: `hubContext` is PREPENDED
88
+ // (the routing facts come first); with no hubContext the output is byte-identical to before.
89
+ function buildServerInstructions({ explore = 'on', hubContext = null } = {}) {
90
+ const guidance = (explore === 'on' || explore === 'probe')
68
91
  ? `${SERVER_INSTRUCTIONS}\n\n${EXPLORE_GUIDANCE}`
69
92
  : SERVER_INSTRUCTIONS;
93
+ return hubContext ? `${buildBoxContextBlock(hubContext)}\n\n${guidance}` : guidance;
70
94
  }
71
95
 
72
96
  // WP-2 correction (lead review): the managed agent-instruction block is the SECOND surface of the
@@ -147,6 +171,11 @@ function handleProtocolMessage(message, options = {}) {
147
171
  if (message.method === 'initialize') {
148
172
  const protocolVersion = selectProtocolVersion(message.params?.protocolVersion);
149
173
  const sessionIdFactory = typeof options.sessionIdFactory === 'function' ? options.sessionIdFactory : null;
174
+ // R-6 (WP-3): only the transport that really emits it advertises capabilities.tools.listChanged
175
+ // -- the stdio proxy passes options.listChanged === true; the daemon (HTTP /mcp, no stream) keeps
176
+ // today's empty `tools` capability. R-4 (WP-2): `hubContext` prepends the "where you run" block,
177
+ // with or without the lead-guidance option (the two are independent transport facts).
178
+ const hasHubContext = options.hubContext !== undefined && options.hubContext !== null;
150
179
  return {
151
180
  handled: true,
152
181
  result: {
@@ -154,14 +183,18 @@ function handleProtocolMessage(message, options = {}) {
154
183
  protocolVersion,
155
184
  response: mcpResponse(message.id, {
156
185
  protocolVersion,
157
- capabilities: CAPABILITIES,
186
+ capabilities: options.listChanged === true
187
+ ? { ...CAPABILITIES, tools: { listChanged: true } }
188
+ : CAPABILITIES,
158
189
  serverInfo: SERVER_INFO,
159
190
  // WP-2: shared guidance every transport serves verbatim (MCP initialize result
160
191
  // instructions) -- never a per-transport variant, so stdio and HTTP cannot drift.
161
192
  // WP-4: the lead harness's exploration hand-off block rides on top ONLY when the
162
193
  // transport resolved its `explore` cell (options.leadGuidance); with no option the
163
194
  // reply is SERVER_INSTRUCTIONS, exactly as before this rule existed.
164
- instructions: options.leadGuidance ? buildServerInstructions(options.leadGuidance) : SERVER_INSTRUCTIONS,
195
+ instructions: (options.leadGuidance || hasHubContext)
196
+ ? buildServerInstructions({ ...(options.leadGuidance || {}), hubContext: options.hubContext || null })
197
+ : SERVER_INSTRUCTIONS,
165
198
  }),
166
199
  },
167
200
  };
@@ -179,12 +212,14 @@ function handleProtocolMessage(message, options = {}) {
179
212
  }
180
213
 
181
214
  module.exports = {
215
+ BOX_CONTEXT_MAX_CHARS,
182
216
  CAPABILITIES,
183
217
  EXPLORE_GUIDANCE,
184
218
  PROTOCOL_VERSION,
185
219
  SERVER_INFO,
186
220
  SERVER_INSTRUCTIONS,
187
221
  SUPPORTED_PROTOCOL_VERSIONS,
222
+ buildBoxContextBlock,
188
223
  buildManagedAgentInstructions,
189
224
  buildServerInstructions,
190
225
  handleProtocolMessage,
@@ -34,6 +34,12 @@ const {
34
34
  resolveDelegateParentAgentSessionId, callerDoorResponse, callerDoorBearerOk,
35
35
  applyAdmissionHealth, normalizeWorkerExecutionOptions, resolveWorkerWaitResult, resolveWorkerStopResult,
36
36
  } = require('./llm/worker-mcp-routing');
37
+ const {
38
+ callerLandingSessionId, executeLandingStatus, executeLandingSubmit, executeLandingWait, executeLandingConflicts,
39
+ landingHintForCaller,
40
+ } = require('./lib/landing-mcp-tools'); // WP-4 (§6.4): landing-queue tools + the D-10 hint line
41
+ const hubBridgeClient = require('./memory/hub-bridge-client'); // WP-1: the hub-bridge lane + its R-10 pool probe
42
+ const sessionPool = require('./memory/session-pool'); // WP-4: the pool legs (hub context + pool search)
37
43
  const { queryEmbedCacheEnabled, getCachedQueryEmbedding, setCachedQueryEmbedding } = require('./lib/query-embed-cache');
38
44
  const { recordToolCall } = require('./lib/mcp-usage'); // WP-0: per-call usage counters, flushed by agent.js
39
45
  const DIRECT_SESSION_SOURCE_SCAN_BYTES = 4 * 1024 * 1024;
@@ -386,7 +392,12 @@ async function _maybeVerifyChosenIdentity(brainApi, resolved, identityCtx, args,
386
392
  return { resolved, identityVerified: false };
387
393
  }
388
394
  const identityVerified = Boolean(verifyResult && verifyResult.proposed > 0);
389
- const freshCtx = await buildIdentityResolutionCtx(brainApi, { admissionTimeoutMs: args.timeout_ms || 5000 });
395
+ // WP-2 (§6): this second resolution must read the SAME origin verdicts as the first (the
396
+ // ctx the handler already carries) -- never a second fetch, and never a silent regress to
397
+ // the pre-WP-2 path if re-resolution happens after an identity verify correction.
398
+ const availability = identityCtx && identityCtx.availability;
399
+ const builtFreshCtx = await buildIdentityResolutionCtx(brainApi, { admissionTimeoutMs: args.timeout_ms || 5000 });
400
+ const freshCtx = builtFreshCtx ? { ...builtFreshCtx, availability } : (availability ? { availability } : null);
390
401
  const reresolved = resolveDelegateArgs(args, listing, registryModels, freshCtx, prefs);
391
402
  return { resolved: reresolved.ok ? reresolved : resolved, identityVerified };
392
403
  }
@@ -438,7 +449,7 @@ async function executeTool(name, args = {}, context = {}) {
438
449
  return buildDegradedContextHint(args, err, { route });
439
450
  }
440
451
  }
441
- return buildContextHint(args);
452
+ return buildContextHint(args, context);
442
453
  }
443
454
  case 'walle_user_profile': {
444
455
  const workerResult = await maybeRunMcpToolInWorker('walle_user_profile', args, {
@@ -452,6 +463,34 @@ async function executeTool(name, args = {}, context = {}) {
452
463
  case 'walle_postflight_check': {
453
464
  return buildPostflightCheck(args);
454
465
  }
466
+ // WP-4 (§6.3/§6.4): the landing-queue tools. Thin shapers over ctm-context-client; the caller
467
+ // identity (`session`) defaults to the stdio proxy's injected parent_agent_session_id.
468
+ case 'walle_landing_status': {
469
+ return executeLandingStatus(ctmContextClient, args, context);
470
+ }
471
+ case 'walle_landing_submit': {
472
+ return executeLandingSubmit(ctmContextClient, args, context);
473
+ }
474
+ case 'walle_landing_wait': {
475
+ return executeLandingWait(ctmContextClient, args, context);
476
+ }
477
+ case 'walle_landing_conflicts': {
478
+ return executeLandingConflicts(ctmContextClient, args, context);
479
+ }
480
+ // WP-1/WP-2 (docs/remote-session-hub-bridge-2026-10-30.html §5 R-4/R-10, §6.4): the `hub_*` tools
481
+ // run an op on ANOTHER machine in this pool (normally the hub Mac driving this session) over the
482
+ // local CTM hub-bridge lane. The caller identity is the landing tools' one (D-13); CTM owns every
483
+ // refusal code, and memory/hub-bridge-client.js owns the tool -> op mapping.
484
+ case 'hub_session_read':
485
+ case 'hub_read_file':
486
+ case 'hub_list':
487
+ case 'hub_exec':
488
+ // WP-3 (docs/remote-session-hub-bridge-2026-10-30.html §3 P-2, D-4, §6.4, §8 WP-3): the two
489
+ // browser MCP tools ride the SAME lane and the SAME mapping table (HUB_TOOL_OPS) — no new
490
+ // switch body, so mcp-server.js's file-size ceiling is untouched.
491
+ case 'hub_mcp_list_tools':
492
+ case 'hub_mcp_call':
493
+ return hubBridgeClient.runHubTool(name, args, callerLandingSessionId(args, context));
455
494
  case 'search_memories': {
456
495
  const workerResult = await maybeRunMcpToolInWorker('search_memories', args, {
457
496
  timeoutMs: Number(args?.timeout_ms) || DEFAULT_MCP_SEARCH_TIMEOUT_MS,
@@ -762,7 +801,9 @@ async function executeTool(name, args = {}, context = {}) {
762
801
  needSession: !(args.route || args.model),
763
802
  });
764
803
  // Only a routed answer needs the route listing and identity tier; a native answer never reaches CTM.
765
- const routed = Boolean(args.route || args.model) || foldDelegateLadder(prefs, execution.agent).effective.lane === 'routed';
804
+ // §9 S-16 (WP-5): the stored LADDER is keyed by the LEAD's agent (prefs.agent -- an OpenCode
805
+ // lead reads default:opencode), while the worker HARNESS stays execution.agent (claude|codex).
806
+ const routed = Boolean(args.route || args.model) || foldDelegateLadder(prefs, prefs.agent).effective.lane === 'routed';
766
807
  const { providers, registryModels } = routed
767
808
  ? await ctmContextClient.listWorkerRoutes({ timeoutMs: args.timeout_ms || 5000 })
768
809
  : { providers: [], registryModels: [] };
@@ -770,7 +811,24 @@ async function executeTool(name, args = {}, context = {}) {
770
811
  // Identity WP-3 (S-6): a phrase in `model` now resolves through the
771
812
  // identity tier (D-9) when the legacy tiers miss -- best-effort ctx,
772
813
  // never blocks delegation when the brain/identity read fails.
773
- const identityCtx = routed ? await buildIdentityResolutionCtx(require('./brain'), { admissionTimeoutMs: args.timeout_ms || 5000 }) : null;
814
+ // WP-2 (§5 D-6/D-7, §6): a call that names no route/model resolves the lead's STORED
815
+ // pick -- so this machine's OWN origin-reachability verdicts ride the ctx, letting the
816
+ // resolver refuse a stored pick whose gateway this box cannot reach BEFORE any launch
817
+ // work (instead of CTM dying later as a raw 503 upstream_unready). Fetched in parallel
818
+ // with the identity ctx, over loopback, best-effort (null on any failure = no gate).
819
+ // Explicit route/model calls take the pre-WP-2 path and never fetch availability.
820
+ const storedPick = !(args.route || args.model);
821
+ let identityCtx = null;
822
+ if (routed) {
823
+ const [builtCtx, availability] = await Promise.all([
824
+ buildIdentityResolutionCtx(require('./brain'), { admissionTimeoutMs: args.timeout_ms || 5000 }),
825
+ storedPick ? ctmContextClient.modelAvailability({ timeoutMs: args.timeout_ms || 5000 }) : Promise.resolve(null),
826
+ ]);
827
+ // routeHealthRefusal guards circuitFor/admissionFor with typeof === 'function', so a
828
+ // `{ availability }` ctx (brain unavailable) is safe -- a missing identityCtx must
829
+ // never silently drop the origin gate.
830
+ identityCtx = builtCtx ? { ...builtCtx, availability } : (availability ? { availability } : null);
831
+ }
774
832
  const normalizedArgs = { ...args, agent: execution.agent };
775
833
  let resolved = resolveDelegateArgs(normalizedArgs, listing, registryModels, identityCtx, prefs);
776
834
  if (!resolved.ok) throw delegateArgsError(resolved.code, resolved);
@@ -890,8 +948,8 @@ async function executeTool(name, args = {}, context = {}) {
890
948
  case 'walle_search_sessions': {
891
949
  const limit = clampLimit(args.limit, 10, 50);
892
950
  const ctmResults = args.prefer_db === false
893
- ? { ok: false, results: [], skipped: true, reason: 'prefer_db_false' }
894
- : await safeCtmSearchSessions({ query: args.query, limit });
951
+ ? { ok: false, results: [], skipped: true, reason: 'prefer_db_false', machines: [] }
952
+ : await sessionPool.searchSessionsAcrossPool({ query: args.query, limit, args, context });
895
953
  const memorySearch = args.include_memory === false
896
954
  ? {
897
955
  results: [],
@@ -924,6 +982,9 @@ async function executeTool(name, args = {}, context = {}) {
924
982
  scheduleMemoryRecall(memoryResults, { toolName: 'walle_search_sessions', logger: console });
925
983
  return {
926
984
  results,
985
+ // WP-4 (R-7): which machines this answer heard from (self first when CTM labelled the search,
986
+ // plus the hub when the caller is a box session and the pool fan-out ran).
987
+ machines: Array.isArray(ctmResults.machines) ? ctmResults.machines : [],
927
988
  sources: {
928
989
  ctm_db: {
929
990
  ok: Boolean(ctmResults.ok),
@@ -973,12 +1034,12 @@ async function executeTool(name, args = {}, context = {}) {
973
1034
  });
974
1035
  }
975
1036
  const wantsDb = args.prefer_db !== false;
976
- const dbSessionIds = args.session_ids || args.session_id || args.source_id;
977
- if (wantsDb && dbSessionIds) {
1037
+ if (wantsDb && (args.session_ids || args.session_id || args.source_id || args.ref)) {
978
1038
  const dbContext = await safeCtmSessionContext({
979
1039
  session_ids: args.session_ids,
980
1040
  session_id: args.session_id,
981
1041
  source_id: args.source_id,
1042
+ ref: args.ref, // WP-3 (§6.4, R-1): an identity string, not a session id — enough on its own
982
1043
  limit: args.limit ?? 20,
983
1044
  turn_limit: args.turn_limit,
984
1045
  byte_limit: args.byte_limit ?? DEFAULT_SESSION_PAGE_BYTES,
@@ -991,10 +1052,8 @@ async function executeTool(name, args = {}, context = {}) {
991
1052
  dedupe: args.dedupe !== false,
992
1053
  format: args.format || 'messages',
993
1054
  });
994
- if (dbContext.ok && (dbContext.sessions.length > 0 || dbContext.messages.length > 0)) {
995
- return dbContext;
996
- }
997
- if (args.session_id || args.session_ids) return dbContext;
1055
+ if (dbContext.ok && (dbContext.sessions.length > 0 || dbContext.messages.length > 0)) return dbContext;
1056
+ if (args.session_id || args.session_ids || args.ref) return sessionPool.sessionContextViaHub(dbContext, args, context);
998
1057
  }
999
1058
  if (!args.source_id) throw new Error('source_id is required when adapter_id and uri are not provided');
1000
1059
  return memorySessionPage(args.source_id, {
@@ -1094,6 +1153,26 @@ function routeWallEQuery(query, opts = {}) {
1094
1153
  };
1095
1154
  }
1096
1155
 
1156
+ // WP-4 (§6.4): the landing queue is CTM's, not Wall-E memory -- matched before session_context so
1157
+ // "land my branch" (which also matches `\bbranch\b`) recommends the landing tools, not context packs.
1158
+ const landingQueue = add('landing_queue', [
1159
+ /\blanding queue\b/,
1160
+ /\bmerge queue\b/,
1161
+ /\bland (my|this|the) (branch|work|tip|commit)\b/,
1162
+ /\bwho is blocking (the|my) (merge|landing|queue)\b/,
1163
+ ]);
1164
+ if (landingQueue) {
1165
+ return {
1166
+ route: 'landing_queue',
1167
+ should_use_walle: true,
1168
+ primary_tools: ['walle_landing_status', 'walle_landing_submit'],
1169
+ secondary_tools: ['walle_landing_conflicts', 'walle_landing_wait'],
1170
+ avoid_until_memory_miss: ['web_search', 'web_fetch'],
1171
+ reason: 'The request is about integrating finished work into the repo CTM manages, which is the landing queue\'s job -- submit through it rather than merging by hand.',
1172
+ matched,
1173
+ };
1174
+ }
1175
+
1097
1176
  if (selfProfile) {
1098
1177
  return {
1099
1178
  route: 'walle_private_memory',
@@ -1241,7 +1320,7 @@ async function lookupWallEContext(args = {}) {
1241
1320
  if (includeSessions) {
1242
1321
  const sessionQuery = isProfileLookup ? 'thorough review fix issues commit high-agency' : query;
1243
1322
  const sessionSearchPromise = withMcpDeadline(
1244
- () => safeCtmSearchSessions({
1323
+ () => sessionPool.safeSearchLocal({
1245
1324
  query: sessionQuery,
1246
1325
  limit,
1247
1326
  prefer_db: args.prefer_db !== false,
@@ -1695,7 +1774,7 @@ function renderPromptContext({ route, profile, lookup, budget }) {
1695
1774
  return rendered.length > budget ? rendered.slice(0, Math.max(0, budget - 18)).trimEnd() + '\n</wall-e-context>' : rendered;
1696
1775
  }
1697
1776
 
1698
- async function buildContextHint(args = {}) {
1777
+ async function buildContextHint(args = {}, context = {}) {
1699
1778
  const query = String(args.query || '').trim();
1700
1779
  if (!query) throw new Error('query is required');
1701
1780
  const route = routeWallEQuery(query, { context: args.context });
@@ -1730,24 +1809,43 @@ async function buildContextHint(args = {}) {
1730
1809
  });
1731
1810
  }
1732
1811
 
1733
- const promptContext = mustUseWallE
1812
+ let promptContext = mustUseWallE
1734
1813
  ? renderPromptContext({ route, profile: compactProfile, lookup, budget })
1735
1814
  : '';
1736
1815
 
1816
+ // WP-4 (§6.4/D-10): when the caller has a CTM session id, one landing line is appended if that
1817
+ // session has a NON-terminal job. The probe has a hard 300 ms budget (inside landingHintForCaller);
1818
+ // on timeout/refusal/unreachable CTM the line is omitted and `sources.landing.ok === false`. With
1819
+ // no caller session, or no job, nothing is added -- no `sources.landing` key (byte-identical to
1820
+ // the pre-WP-4 hint).
1821
+ const callerSessionId = callerLandingSessionId(args, context);
1822
+ const landingHint = await landingHintForCaller(ctmContextClient, callerSessionId);
1823
+ const sources = {
1824
+ profile: { included: Boolean(compactProfile), evidence_count: compactProfile?.evidence?.length || 0 },
1825
+ lookup: lookup?.sources || null,
1826
+ };
1827
+ let landingLine = '';
1828
+ if (landingHint) {
1829
+ if (landingHint.ok === false) {
1830
+ sources.landing = { ok: false, error: landingHint.error };
1831
+ } else if (landingHint.line) {
1832
+ landingLine = landingHint.line;
1833
+ promptContext = promptContext ? `${promptContext}\n${landingLine}` : landingLine;
1834
+ sources.landing = { ok: true };
1835
+ }
1836
+ }
1837
+
1737
1838
  return {
1738
1839
  route,
1739
1840
  confidence: routeConfidence(route),
1740
1841
  must_use_walle_before_answer: mustUseWallE,
1741
- should_inject_context: Boolean(mustUseWallE && promptContext),
1842
+ should_inject_context: Boolean((mustUseWallE && promptContext) || landingLine),
1742
1843
  recommended_tools: recommendedTools,
1743
1844
  skipped_reason: mustUseWallE ? '' : route.reason,
1744
1845
  compact_profile: compactProfile,
1745
1846
  lookup,
1746
1847
  prompt_context: promptContext,
1747
- sources: {
1748
- profile: { included: Boolean(compactProfile), evidence_count: compactProfile?.evidence?.length || 0 },
1749
- lookup: lookup?.sources || null,
1750
- },
1848
+ sources,
1751
1849
  };
1752
1850
  }
1753
1851
 
@@ -1945,14 +2043,6 @@ function stripRank(item) {
1945
2043
  return rest;
1946
2044
  }
1947
2045
 
1948
- async function safeCtmSearchSessions(args) {
1949
- try {
1950
- return await ctmContextClient.searchSessions(args);
1951
- } catch (err) {
1952
- return { ok: false, source: 'ctm-db', results: [], reason: err.message };
1953
- }
1954
- }
1955
-
1956
2046
  async function safeCtmSessionContext(args) {
1957
2047
  try {
1958
2048
  return await ctmContextClient.getSessionContext(args);
@@ -2745,6 +2835,10 @@ async function handleMcpMessage(msg, context = {}) {
2745
2835
  // notification methods here instead of silently swallowing them.
2746
2836
  acceptAnyNotification: true,
2747
2837
  leadGuidance: leadGuidanceForMessage(msg, brain), // WP-4 §6.4: gates the exploration hand-off block
2838
+ // R-1/R-2 (WP-0): the daemon answers tools/list too, but over HTTP it has no per-session caller
2839
+ // id and no stream to push on, so it gates on role alone (sessionId ''). No listChanged, no
2840
+ // hubContext here -- both are stdio-proxy behaviours (WP-2/WP-3).
2841
+ hideTools: await hubBridgeClient.hideTools({ tools: MCP_TOOLS, sessionId: '' }),
2748
2842
  });
2749
2843
  if (control.handled) return control.result;
2750
2844
 
@@ -2788,7 +2882,12 @@ async function handleMcpMessage(msg, context = {}) {
2788
2882
  if (mcpPerfLogsEnabled()) {
2789
2883
  console.warn(`[mcp] tool ${toolName || 'unknown'} failed in ${Date.now() - startedAt}ms: ${err.message}`);
2790
2884
  }
2791
- return { response: mcpResponse(id, { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true }) };
2885
+ // D-9: a CTM refusal wrapped by ctm-context-client's _wrapCtmDelegateError keeps the
2886
+ // parsed CTM body on err.body; surface its next_step instead of dropping it with err.message
2887
+ // (unless the message already carries it, e.g. a refusal whose message IS the JSON body).
2888
+ const nextStep = err && err.body && typeof err.body === 'object' && typeof err.body.next_step === 'string'
2889
+ && !String(err.message).includes(err.body.next_step) ? err.body.next_step : '';
2890
+ return { response: mcpResponse(id, { content: [{ type: 'text', text: nextStep ? `Error: ${err.message}\nnext_step: ${nextStep}` : `Error: ${err.message}` }], isError: true }) };
2792
2891
  }
2793
2892
  }
2794
2893
 
@@ -20,7 +20,7 @@ const WORKER_ROUTE_ENTRY_SCHEMA = {
20
20
  models: { type: 'array', items: { type: 'string' }, description: 'Every enabled model_registry model id for this provider (GET /api/models/registry); empty when the provider has none' },
21
21
  kind: { type: 'string' },
22
22
  upstream_apis: { type: 'array', items: { type: 'string', enum: ['anthropic-messages', 'openai-responses', 'openai-chat'] } },
23
- agents: { type: 'array', items: { type: 'string', enum: ['claude', 'codex'] } },
23
+ agents: { type: 'array', items: { type: 'string', enum: ['claude', 'codex', 'dsh'] } },
24
24
  // Admission WP-4 (worker-admission-no-cap-throttle-truth-2026-10-10.html D-3): 'throttled'
25
25
  // means GET /api/sessions/delegate/admission names this route with a live hold
26
26
  // (throttled_until or quota_held), with its reason and refusal count.
@@ -124,7 +124,7 @@ const LIST_WORKER_ROUTES_OUTPUT_SCHEMA = {
124
124
  properties: {
125
125
  route: { type: 'string' },
126
126
  model: { type: 'string' },
127
- agents: { type: 'array', items: { type: 'string', enum: ['claude', 'codex'] } }, // WP-4 D-18
127
+ agents: { type: 'array', items: { type: 'string', enum: ['claude', 'codex', 'dsh'] } }, // WP-4 D-18
128
128
  },
129
129
  required: ['route', 'model'],
130
130
  additionalProperties: true,
@@ -146,7 +146,7 @@ const LIST_WORKER_ROUTES_OUTPUT_SCHEMA = {
146
146
  // pin field at all. One definition per enum, so the shape rules can never drift from the whitelist.
147
147
  const NATIVE_LAUNCH_FIELD_SCHEMAS = {
148
148
  state: { type: 'string', enum: ['known', 'unknown'] },
149
- agent: { type: 'string', enum: ['codex', 'claude'], description: 'The lead\'s own harness -- a native helper always runs on it; present whenever the resolved live lead reported one, even with an unknown pin' },
149
+ agent: { type: 'string', enum: ['codex', 'claude', 'opencode'], description: 'The lead\'s own harness (opencode = an OpenCode lead, whose native helper runs inside OpenCode) -- a native helper always runs on it; present whenever the resolved live lead reported one, even with an unknown pin' },
150
150
  kind: { type: 'string', enum: ['native', 'routed', 'inherit'], description: 'The launch class this lead was launched with: native = a model override, routed = the reserved worker alias, inherit = the lead\'s own model' },
151
151
  model: { type: 'string', description: 'The model the launch was configured with (empty = no model override was configured, which is not proof the lead will run the requested model; a routed class records the launch-time target snapshot, not the alias its role actually forces)' },
152
152
  effort: { type: ['string', 'null'], description: 'The configured Codex role effort: a bounded token, \'\' for a known "no role override", null when unknown or not applicable (Claude applies none)' },
@@ -166,7 +166,7 @@ const DELEGATE_IMPLEMENTATION_OUTPUT_SCHEMA = {
166
166
  ok: { type: 'boolean', description: 'true on a native answer (nothing was launched)' },
167
167
  lane: { type: 'string', enum: ['routed', 'native'], description: 'routed = a worker session was launched; native = the lead spawns the helper itself with `model`' },
168
168
  source: { type: 'string', enum: ['explicit', 'session', 'default', 'vendor'], description: 'The rung that decided the model: named in the call, the lead\'s session pick, the agent default, or the vendor default' },
169
- harness: { type: ['string', 'null'], enum: ['claude-code', 'codex-cli', null] },
169
+ harness: { type: ['string', 'null'], enum: ['claude-code', 'codex-cli', 'dsh-acp', null] },
170
170
  worker_profile: { type: ['string', 'null'], enum: ['legacy', 'implementation', 'review', null] },
171
171
  original_brief_sha256: { type: ['string', 'null'] },
172
172
  rendered_brief_sha256: { type: ['string', 'null'] },
@@ -319,7 +319,7 @@ const WORKER_STATUS_OUTPUT_SCHEMA = {
319
319
  properties: {
320
320
  status: { type: 'string', enum: ['starting', 'working', 'throttled', 'report_ready', 'failed', 'exited'] },
321
321
  generation: { type: 'integer' },
322
- harness: { type: ['string', 'null'], enum: ['claude-code', 'codex-cli', null] },
322
+ harness: { type: ['string', 'null'], enum: ['claude-code', 'codex-cli', 'dsh-acp', null] },
323
323
  worker_profile: { type: ['string', 'null'], enum: ['legacy', 'implementation', 'review', null] },
324
324
  parent_ctm_session_id: { type: 'string' },
325
325
  report_path: { type: 'string' },
@@ -38,6 +38,9 @@ async function searchSessions(args = {}, options = {}) {
38
38
  const params = new URLSearchParams();
39
39
  if (args.query !== undefined) params.set('q', String(args.query || ''));
40
40
  if (args.limit !== undefined) params.set('limit', String(args.limit));
41
+ // WP-4 (docs/cross-machine-session-context-2026-10-31.html §6.2/§6.4, R-7): `scope=pool` lets CTM
42
+ // fan the search out to every dialable member and merge by RRF; omitted, CTM's own default applies.
43
+ if (args.scope !== undefined) params.set('scope', String(args.scope));
41
44
  return apiFirst({
42
45
  path: `/api/ctm/session-memory/search?${params.toString()}`,
43
46
  fallback: () => ctmSessionContext.searchCtmSessions({ ...args, ...directOptions(options) }),
@@ -49,6 +52,10 @@ async function getSessionContext(args = {}, options = {}) {
49
52
  const params = new URLSearchParams();
50
53
  for (const id of normalizeIds(args.session_ids || args.ids)) params.append('session_id', id);
51
54
  if (args.session_id || args.source_id) params.append('session_id', args.session_id || args.source_id);
55
+ // WP-3 (docs/cross-machine-session-context-2026-10-31.html §6.2/§6.4, R-1): `ref` is any identity
56
+ // string the search box's parser understands (`…#session=<id>`, `review=<id>`, or a bare id) and
57
+ // CTM merges it into the read's session ids. It rides ALONGSIDE session_id, never as one.
58
+ if (args.ref) params.set('ref', String(args.ref));
52
59
  for (const [key, value] of Object.entries({
53
60
  limit: args.limit,
54
61
  cursor: args.cursor,
@@ -483,6 +490,22 @@ async function listWorkerRoutes(options = {}) {
483
490
  };
484
491
  }
485
492
 
493
+ // WP-2 (docs/remote-session-child-transcript-model-truth-and-restart-2026-10-27.html §5 D-6): this
494
+ // machine's own origin-reachability verdicts, read over loopback with the same bearer as the route
495
+ // listing. Best-effort: any failure (refused, 403, timeout, non-JSON) answers null, never throws --
496
+ // an unknown verdict is "no gate", exactly like a missing identityCtx. `_ctmDelegateCall` throws on
497
+ // every non-2xx/transport failure and returns whatever the endpoint body parsed to, so ONLY a
498
+ // well-formed `{ ok: true, routes: [...] }` is returned; anything else (an error body, a partial
499
+ // shape) answers null.
500
+ async function modelAvailability(options = {}) {
501
+ const env = options.env || process.env;
502
+ const timeoutMs = options.timeoutMs ?? 5000;
503
+ try {
504
+ const body = await _ctmDelegateCall('/api/models/availability', { timeoutMs, env });
505
+ return body && body.ok === true && Array.isArray(body.routes) ? body : null;
506
+ } catch { return null; } // expected: availability is advisory; the health gate degrades to "unknown"
507
+ }
508
+
486
509
  // POST /api/sessions/delegate (§6.2). `body` is the exact request body shape sessions.js's
487
510
  // handleDelegateSession reads (brief_path, cwd, route, model, agent,
488
511
  // parent_agent_session_id, allowed_tools, max_turns, title) -- the caller (mcp-server.js)
@@ -694,6 +717,65 @@ async function stopWorker(ctmSessionId, { mode = 'after_turn', reason = '', grac
694
717
  }
695
718
  }
696
719
 
720
+ // WP-4 (local-landing-queue-multi-session-integration-2026-10-26.html §6.3, §6.4): the landing
721
+ // queue's two CTM calls. Same authenticated helper as every other worker/delegate call
722
+ // (`_ctmDelegateCall`) -- never a second hand-rolled client, and (like the delegated-worker calls)
723
+ // no apiFirst() direct-DB fallback: there is no local equivalent of "what is in this repo's queue"
724
+ // to fall back to.
725
+ //
726
+ // The status route answers 200 with the read model, or a non-2xx `{ ok:false, error }` body (404
727
+ // repo_unknown, 502 landing_probe_failed). A structured non-2xx body is a FIRST-CLASS result,
728
+ // relayed verbatim (the D-8 pattern resumeWorker/stopWorker already use); only a transport failure
729
+ // (unreachable CTM, abort, timeout) throws.
730
+ function _landingQuery({ repo, session, cached }) {
731
+ const params = new URLSearchParams();
732
+ if (typeof repo === 'string' && repo) params.set('repo', repo);
733
+ if (typeof session === 'string' && session) params.set('session', session);
734
+ if (cached === true) params.set('cached', '1');
735
+ const query = params.toString();
736
+ return query ? `?${query}` : '';
737
+ }
738
+
739
+ // `cached: true` asks CTM for the session's view as its last sweep left it (no CLI child); it needs
740
+ // `session` and answers `{ ok, cached:true, repo, forSession }`.
741
+ async function landingStatus({ repo, session, cached, timeoutMs } = {}, options = {}) {
742
+ const env = options.env || process.env;
743
+ try {
744
+ return await _ctmDelegateCall(`/api/landing/status${_landingQuery({ repo, session, cached })}`, {
745
+ timeoutMs: timeoutMs ?? 6000,
746
+ env,
747
+ });
748
+ } catch (err) {
749
+ if (err && err.body && typeof err.body === 'object') return err.body; // structured refusal is a result
750
+ throw err; // RETHROW: a transport failure is not a status answer.
751
+ }
752
+ }
753
+
754
+ // POST /api/landing/submit { session, priority?, reason? }: the CLI's own `land submit --json`
755
+ // payload on 200, or a typed refusal body on 409 (the caller's branch is not landable) / 400
756
+ // (usage). Both are relayed verbatim; only a transport failure throws.
757
+ // WP-4 (§6.4): `priority` and `reason` are optional passthroughs -- CTM hands them to the CLI's
758
+ // `--priority` / `--reason`, which is the one validator. Only a non-empty string is sent, so a call
759
+ // without them still posts exactly `{session}` (byte-for-byte the pre-WP-4 body).
760
+ async function landingSubmit({ session, priority, reason, timeoutMs } = {}, options = {}) {
761
+ const env = options.env || process.env;
762
+ const body = {};
763
+ if (typeof session === 'string' && session) body.session = session;
764
+ if (typeof priority === 'string' && priority) body.priority = priority;
765
+ if (typeof reason === 'string' && reason) body.reason = reason;
766
+ try {
767
+ return await _ctmDelegateCall('/api/landing/submit', {
768
+ method: 'POST',
769
+ body,
770
+ timeoutMs: timeoutMs ?? 30000,
771
+ env,
772
+ });
773
+ } catch (err) {
774
+ if (err && err.body && typeof err.body === 'object') return err.body; // structured refusal is a result
775
+ throw err; // RETHROW: a transport failure is not a submit answer.
776
+ }
777
+ }
778
+
697
779
  function annotateFallback(result, apiTransport) {
698
780
  return {
699
781
  ...(result || {}),
@@ -734,6 +816,7 @@ module.exports = {
734
816
  getConversationItems,
735
817
  ackConversationChanges,
736
818
  listWorkerRoutes,
819
+ modelAvailability,
737
820
  expandWorkerRegistry,
738
821
  fetchWorkerRegistry,
739
822
  delegateWorker,
@@ -741,6 +824,8 @@ module.exports = {
741
824
  delegateParent,
742
825
  workerStatus,
743
826
  waitForWorkers,
827
+ landingStatus,
828
+ landingSubmit,
744
829
  resumeWorker,
745
830
  stopWorker,
746
831
  resetApiState,
@@ -23,6 +23,7 @@ const CTM_SESSION_TABLES = [
23
23
  'conversation_item_placement_v2',
24
24
  'conversation_text_fts_v2',
25
25
  ];
26
+ const { createReplicaOriginLookup: replicaLookup } = require('./replica-origin'); // WP-5/R-6 replica_origin
26
27
  let Database = null;
27
28
 
28
29
  function requireBetterSqlite3() {
@@ -345,6 +346,7 @@ function getCtmSessionContext({
345
346
  }
346
347
 
347
348
  const bundles = identifiers.map((id) => resolveSessionBundle(conn, id)).filter(Boolean);
349
+ const replicaOriginOf = replicaLookup(conn, hasTable); // WP-5: one cursor read per call
348
350
  const seenBundles = new Set();
349
351
  const uniqueBundles = bundles.filter((bundle) => {
350
352
  const key = bundle.ctm_session_id || bundle.requested_id;
@@ -371,7 +373,7 @@ function getCtmSessionContext({
371
373
  const conversationId = selectBoundedConversationId(conn, bundle);
372
374
  const conversations = getConversationRows(conn, bundle);
373
375
  if (!conversationId) {
374
- sessions.push(formatSessionSummary(bundle, conversations, []));
376
+ sessions.push(formatSessionSummary(bundle, conversations, [], replicaOriginOf));
375
377
  continue;
376
378
  }
377
379
  const pageCursor = cursorForConversation(cursor, conversationId, bundle, uniqueBundles.length);
@@ -402,7 +404,7 @@ function getCtmSessionContext({
402
404
  row, bundle, conversationId, index,
403
405
  }));
404
406
  const selectedMessages = dedupe ? dedupeMessages(sessionMessages) : sessionMessages;
405
- sessions.push(formatSessionSummary(bundle, conversations, selectedMessages));
407
+ sessions.push(formatSessionSummary(bundle, conversations, selectedMessages, replicaOriginOf));
406
408
  allMessages.push(...selectedMessages);
407
409
  ranges[bundle.ctm_session_id] = page.range;
408
410
  generations[bundle.ctm_session_id] = page.generation;
@@ -885,6 +887,7 @@ function quoteIdent(value) {
885
887
  function searchSessionMessagesFts(db, query, limit) {
886
888
  const ftsQueries = buildFtsQueries(query);
887
889
  if (!ftsQueries.length) return [];
890
+ const replicaOriginOf = replicaLookup(db, hasTable); // WP-5: one cursor read per call
888
891
  if (hasTable(db, 'conversation_text_items_v2')
889
892
  && hasTable(db, 'conversation_item_placement_v2')
890
893
  && hasTable(db, 'conversation_text_fts_v2')) {
@@ -907,6 +910,7 @@ function searchSessionMessagesFts(db, query, limit) {
907
910
  source_table: 'conversation_text_fts_v2',
908
911
  rank: index,
909
912
  score: row.rank,
913
+ replicaOriginOf,
910
914
  }));
911
915
  }
912
916
  }
@@ -935,6 +939,7 @@ function enrichSearchRow(db, row, extra = {}) {
935
939
  snippet: snippetAround(row.content || '', 800),
936
940
  content_hash: contentFingerprint(row.content || ''),
937
941
  rank: extra.rank || 0,
942
+ replica_origin: extra.replicaOriginOf ? extra.replicaOriginOf([row.conversation_id, resolved.ctm_session_id]) : '',
938
943
  };
939
944
  }
940
945
 
@@ -1130,7 +1135,7 @@ function messageText(raw) {
1130
1135
  return '';
1131
1136
  }
1132
1137
 
1133
- function formatSessionSummary(bundle, conversations, messages) {
1138
+ function formatSessionSummary(bundle, conversations, messages, replicaOriginOf) {
1134
1139
  const firstConversation = conversations[0] || {};
1135
1140
  return {
1136
1141
  session_id: bundle.ctm_session_id,
@@ -1146,6 +1151,7 @@ function formatSessionSummary(bundle, conversations, messages) {
1146
1151
  message_count: messages.length,
1147
1152
  user_msg_count: firstConversation.user_msg_count || messages.filter((msg) => msg.role === 'user').length,
1148
1153
  assistant_msg_count: firstConversation.assistant_msg_count || messages.filter((msg) => msg.role === 'assistant').length,
1154
+ replica_origin: replicaOriginOf ? replicaOriginOf([bundle.ctm_session_id, ...(bundle.agent_session_ids || [])]) : '',
1149
1155
  };
1150
1156
  }
1151
1157