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
@@ -9,13 +9,13 @@ function _inputError(error, detail) {
9
9
  function normalizeWorkerExecutionOptions(args = {}) {
10
10
  const suppliedAgent = args.agent !== undefined && args.agent !== null;
11
11
  const suppliedHarness = args.harness !== undefined && args.harness !== null;
12
- const harnessAgent = args.harness === 'claude-code' ? 'claude' : args.harness === 'codex-cli' ? 'codex' : null;
13
- if (suppliedHarness && !harnessAgent) throw _inputError('harness_invalid', 'harness must be claude-code or codex-cli');
14
- if (suppliedAgent && !['claude', 'codex'].includes(args.agent)) throw _inputError('agent_invalid', 'agent must be claude or codex');
12
+ const harnessAgent = args.harness === 'claude-code' ? 'claude' : args.harness === 'codex-cli' ? 'codex' : args.harness === 'dsh-acp' ? 'dsh' : null;
13
+ if (suppliedHarness && !harnessAgent) throw _inputError('harness_invalid', 'harness must be claude-code, codex-cli or dsh-acp');
14
+ if (suppliedAgent && !['claude', 'codex', 'dsh'].includes(args.agent)) throw _inputError('agent_invalid', 'agent must be claude, codex or dsh');
15
15
  if (suppliedAgent && harnessAgent && args.agent !== harnessAgent) throw _inputError('harness_conflict', 'agent and harness select different worker CLIs');
16
16
 
17
17
  const agent = harnessAgent || (suppliedAgent ? args.agent : 'claude');
18
- const harness = suppliedHarness ? args.harness : agent === 'codex' ? 'codex-cli' : 'claude-code';
18
+ const harness = suppliedHarness ? args.harness : agent === 'codex' ? 'codex-cli' : agent === 'dsh' ? 'dsh-acp' : 'claude-code';
19
19
  const suppliedProfile = args.worker_profile ?? args.workerProfile;
20
20
  const workerProfile = suppliedProfile === undefined ? 'implementation' : suppliedProfile;
21
21
  if (!['legacy', 'implementation', 'review'].includes(workerProfile)) {
@@ -49,6 +49,31 @@ function resolveDelegateParentAgentSessionId(explicitValue, isExplicit = false)
49
49
  // downstream with caller_unresolved).
50
50
  const CALLER_CONTEXT_TOOLS = new Set(['walle_delegate_implementation', 'walle_worker_wait', 'walle_resume_worker', 'walle_stop_worker']);
51
51
 
52
+ // WP-4 (local-landing-queue-multi-session-integration-2026-10-26.html §6.3, §6.4): the four landing
53
+ // tools take the SAME caller identity the delegate tools do (the stdio proxy's env-resolved
54
+ // CODEX_THREAD_ID || CTM_SESSION_ID, injected as `parent_agent_session_id`), so `session` can
55
+ // default to the caller's CTM session id. They are deliberately NOT in CALLER_CONTEXT_TOOLS: that
56
+ // set is the bearer-gated HTTP door (D-11), and these are read-mostly surface every harness must
57
+ // reach -- landing status/conflicts/wait are read-only, and land submit is already loopback-gated by
58
+ // CTM's own auth rules. `walle_context_hint` rides here too: the D-10 line is appended for the
59
+ // caller's session, so the hint needs the caller identity.
60
+ const LANDING_CALLER_TOOLS = new Set([
61
+ 'walle_landing_status', 'walle_landing_submit', 'walle_landing_wait', 'walle_landing_conflicts',
62
+ 'walle_context_hint',
63
+ ]);
64
+
65
+ // docs/remote-session-hub-bridge-2026-10-30.html §5 R-2, §6.4: the hub-bridge tools ask the hub
66
+ // that drives THIS session to act, and the hub binds every request to the caller's own session
67
+ // (caller_session_not_on_machine otherwise), so they need the same injected caller identity. Not in
68
+ // CALLER_CONTEXT_TOOLS: the box CTM route they reach is loopback-gated, not bearer-gated (D-11).
69
+ const HUB_BRIDGE_CALLER_TOOLS = new Set([
70
+ 'hub_session_read', 'hub_read_file', 'hub_list', 'hub_exec', 'hub_mcp_list_tools', 'hub_mcp_call',
71
+ ]);
72
+
73
+ // The one gate the identity injection consults: the bearer-gated caller-context tools plus the
74
+ // landing and hub-bridge surfaces above.
75
+ const CALLER_IDENTITY_TOOLS = new Set([...CALLER_CONTEXT_TOOLS, ...LANDING_CALLER_TOOLS, ...HUB_BRIDGE_CALLER_TOOLS]);
76
+
52
77
  // WP-2 (usage-attribution-followups R-3/R-4, §6.3): the two LAUNCH tools -- the ones that
53
78
  // start a worker as a side effect. They differ from the other caller-context tools twice:
54
79
  // their proxy deadline must outlast the daemon's own CTM fetch deadline
@@ -94,7 +119,7 @@ function attachDelegateCallerContext(message, callerParentId) {
94
119
  return changed ? items : message;
95
120
  }
96
121
  if (!message || message.method !== 'tools/call'
97
- || !CALLER_CONTEXT_TOOLS.has(message.params?.name)
122
+ || !CALLER_IDENTITY_TOOLS.has(message.params?.name)
98
123
  || typeof callerParentId !== 'string' || !callerParentId.trim()) return message;
99
124
  const args = message.params.arguments;
100
125
  if (args !== undefined && (!args || typeof args !== 'object' || Array.isArray(args))) return message;
@@ -180,8 +205,8 @@ function callerBearerHeader(hostname) {
180
205
  // stays one branch); only data.cause and data.next_step differ. Frozen: the
181
206
  // skill templates and delegate-skill-templates.test.js pin these verbatim.
182
207
  const PROXY_NEXT_STEPS = Object.freeze({
183
- proxy_token_missing: 'The Wall-E MCP server for this session was started without WALL_E_API_TOKEN, so it cannot present the CTM runtime bearer. Wall-E rewrites the managed Codex [mcp_servers."wall-e"] block (env_vars) at boot and before each CTM Codex launch; restart this session so Codex respawns the MCP server with the token. Do not edit config.toml by hand.',
184
- non_loopback_daemon: 'The Wall-E daemon for this session is not on loopback, and the runtime bearer is only sent to a loopback daemon (F1b-1). Routed delegation needs a local Wall-E; use the native lane or a CTM-launched session on this host.',
208
+ proxy_token_missing: 'The Wall-E MCP server for this session was started without WALL_E_API_TOKEN, so it cannot present the CTM runtime bearer. Wall-E rewrites the managed Codex [mcp_servers."wall-e"] block (env_vars) when Wall-E starts; restart this session so Codex respawns the MCP server with the token. Do not edit config.toml by hand.',
209
+ non_loopback_daemon: 'The Wall-E daemon for this session is not on loopback, so routed delegation is unavailable from here. Tell the user and wait for their word; do not substitute a native helper.',
185
210
  });
186
211
 
187
212
  // D-3 (S-8): the stdio proxy refuses a caller-context call it cannot
@@ -268,12 +293,15 @@ function callerDoorBearerOk(req) {
268
293
  return require('../http/auth').requireBearer(req, strFlag('WALL_E_API_TOKEN', ''));
269
294
  }
270
295
 
271
- // WP-5b (lead-cost routing §6.2/§6.7): the rule cell decides whether a wait parks the watcher.
272
- // 'off' is a user veto (D-18: final, and silent ticks cannot move it), 'silent' is an off cell
273
- // still collecting 1-in-10 ticks (D-16), and CTM's default 'on' is returned as null so an
274
- // unchanged request keeps its exact shape (`watch=` is omitted entirely). A route wait starts
275
- // no watcher (WP-1), and a wait whose worker has no recorded route has no cell to read.
276
- const WATCH_ORDER = Object.freeze({ off: 0, silent: 1, on: 2 });
296
+ // WP-5b (lead-cost routing §6.2/§6.7), WP-2: the rule cell decides whether a wait parks the
297
+ // watcher. `off` is a user veto (D-18: final) or the evaluator's demotion — a watcher that has
298
+ // proved useless is parked outright. Silent mode is RETIRED in Wall-E (it collected 1-in-10 ticks
299
+ // inside a watcher that never lived long enough to produce a row), so the only modes are `off` and
300
+ // `on`; a cell in `probe` collects through CTM's own default. CTM still accepts `watch=silent`
301
+ // for mixed-version safety, but Wall-E never sends it. `on` is CTM's default and is returned as
302
+ // null so an unchanged request keeps its exact shape (`watch=` is omitted entirely). A route wait
303
+ // starts no watcher (WP-1), and a wait whose worker has no recorded route has no cell to read.
304
+ const WATCH_ORDER = Object.freeze({ off: 0, on: 1 });
277
305
  const WATCH_OFF_CELL = 'off';
278
306
 
279
307
  function _helperRulesDb() {
@@ -291,7 +319,20 @@ function _watchModeOfRoute(route, db) {
291
319
  const cellKey = `wait-watch|default|${route}`;
292
320
  const row = readCell(db, cellKey);
293
321
  if (row && Number(row.user_veto) === 1) return 'off';
294
- return readCellState(db, cellKey) === WATCH_OFF_CELL ? 'silent' : 'on';
322
+ return readCellState(db, cellKey) === WATCH_OFF_CELL ? 'off' : 'on';
323
+ }
324
+
325
+ // D-8 (round 3): a null below is CTM's default `on` -- a full-rate watcher for a worker whose cell
326
+ // may be off. The reason is counted (and named once) so the dominant fail-open cause can be read
327
+ // off the panel instead of guessed. Counting is advisory: it may never fail a lead's wait.
328
+ function _noteWatchFallback(hook, reason, workerId) {
329
+ if (!hook || typeof hook.noteWatchFallback !== 'function') return;
330
+ try {
331
+ hook.noteWatchFallback(reason, workerId || null);
332
+ } catch {
333
+ // expected: a stub hook that throws on the counter -- the count is lost, the wait is not
334
+ return;
335
+ }
295
336
  }
296
337
 
297
338
  /**
@@ -301,20 +342,27 @@ function _watchModeOfRoute(route, db) {
301
342
  */
302
343
  function watchModeFor(args = {}, hook = require('../lib/helper-rules/lead-call-hook'), db = _helperRulesDb()) {
303
344
  const routes = new Set();
304
- if (args.route) return null; // a route wait starts no watcher (WP-1)
345
+ if (args.route) return null; // a route wait starts no watcher, and is not a fallback (WP-1)
305
346
  try {
306
347
  if (args.ctm_session_id) {
307
348
  const entry = hook.workerRouteOf(args.ctm_session_id);
308
- if (!entry || !entry.route) return null; // unknown -> 'on'
349
+ if (!entry || !entry.route) {
350
+ _noteWatchFallback(hook, 'unknown_worker', args.ctm_session_id);
351
+ return null; // unknown -> 'on'
352
+ }
309
353
  routes.add(entry.route);
310
354
  } else {
311
355
  for (const worker of hook.leadWorkersOf(args.parent_agent_session_id) || []) {
312
356
  if (worker && worker.route) routes.add(worker.route);
313
357
  }
314
- if (!routes.size) return null; // nothing recorded -> 'on'
358
+ if (!routes.size) {
359
+ _noteWatchFallback(hook, 'no_lead_workers', args.parent_agent_session_id);
360
+ return null; // nothing recorded -> 'on'
361
+ }
315
362
  }
316
363
  } catch {
317
364
  // expected: the hook cannot answer -- 'on' is the fail-open default, never a failed wait
365
+ _noteWatchFallback(hook, 'hook_error', args.ctm_session_id || args.parent_agent_session_id);
318
366
  return null;
319
367
  }
320
368
  let mode = 'on';
@@ -403,5 +451,6 @@ module.exports = {
403
451
  resolveCallerParentAgentSessionId, callerBearerHeader, callerDoorBearerOk,
404
452
  isLoopbackHost, PROXY_NEXT_STEPS, proxyCallerDoorResponse, callerBearerStatus, withCallerBearerStatus,
405
453
  CALLER_CONTEXT_TOOLS, applyAdmissionHealth, normalizeWorkerExecutionOptions, resolveWorkerWaitResult, resolveWorkerStopResult,
454
+ LANDING_CALLER_TOOLS, CALLER_IDENTITY_TOOLS,
406
455
  LAUNCH_TOOLS, LAUNCH_TOOL_PROXY_TIMEOUT_MS, callerToolUseIdFromMeta, admittedToolTimeoutMs,
407
456
  };
@@ -632,6 +632,23 @@ function helperRulesSetGrade(id, gradeJson) {
632
632
  return require('../lib/helper-rules/store').setGrade(brain.getDb(), id, gradeJson);
633
633
  }
634
634
 
635
+ // WP-0 (§6.3): the v2 clock seed walk. One bounded page per call, on the OWNER's connection —
636
+ // the walk writes brain_row_clock / brain_local_seq / brain_vv, and its caller (the scheduler
637
+ // job, which runs in a worker holding a read-only handle) must not write them itself. Same
638
+ // CUSTOM_BRAIN_CALLS seam as the v1 backfill batches above; the walk's own kv cursor makes it
639
+ // resumable, and clock writes fire no capture trigger, so it enqueues no outbox row.
640
+ function brainSyncClockSeed(options = {}) {
641
+ return require('../brain/brain-sync-store').seedClockPage(brain.getDb(), options);
642
+ }
643
+
644
+ // WP-4 (§6.7): the join import's ONE bounded page per call. Like the clock seed above, the caller
645
+ // is a scheduler job; the page writes the four replicated tables with the connection-scoped
646
+ // sentinel on (inside brain/brain-join.js), so it must run on the owner's write connection, not
647
+ // the job's read-only handle. The kv cursor makes it resumable after a crash.
648
+ function brainSyncV2JoinStep(options = {}) {
649
+ return require('../brain/brain-join').joinImportStep(brain.getDb(), options);
650
+ }
651
+
635
652
  module.exports = {
636
653
  failConversationExtraction,
637
654
  markMemoriesExtractionSkipped,
@@ -665,4 +682,6 @@ module.exports = {
665
682
  helperRulesSetGrade,
666
683
  helperRulesCloseOutcomeByWorker,
667
684
  helperRulesRelabel,
685
+ brainSyncClockSeed,
686
+ brainSyncV2JoinStep,
668
687
  };
@@ -4,6 +4,8 @@ const eventBus = require('../events/event-bus');
4
4
  const parentBrainOwner = require('../lib/parent-brain-owner-client');
5
5
  const { brainWrite } = require('./brain-write');
6
6
  const memoryFileKnowledge = require('../adapters/memory-file-knowledge');
7
+ const { resolvePlacement } = require('../lib/derivation-home');
8
+ const { imessageIngestEnabled } = require('../adapters/imessage');
7
9
 
8
10
  const OWNER_WRITE_TIMEOUT_MS = 90 * 1000;
9
11
  // One commit per 200 rows: bounds the cross-process write-lock hold while still
@@ -129,6 +131,17 @@ function _adapterName(adapter) {
129
131
  return adapter.name || adapter.constructor?.name || 'unknown';
130
132
  }
131
133
 
134
+ // D-5/S-21 (shared-memory WP-2): one placement probe per ingest tick decides whether the
135
+ // iMessage adapter is active (the predicate lives with the adapter — adapters/imessage.js
136
+ // `imessageIngestEnabled`). Every other adapter is host-local and runs everywhere.
137
+ async function _activeAdapters(adapters, opts) {
138
+ const placement = opts.placement || await resolvePlacement();
139
+ const list = Array.isArray(adapters) ? adapters : [];
140
+ return list.filter((adapter) => (
141
+ _adapterName(adapter) !== 'imessage' || imessageIngestEnabled(placement)
142
+ ));
143
+ }
144
+
132
145
  // One adapter's tick: poll, insert, exchange pairs, reconcile, checkpoint.
133
146
  // `guard` throws once runOnce has abandoned this adapter for the tick. It runs immediately before every
134
147
  // commit point, so a poll that finally resolves after the abandonment writes no memory chunk, no exchange
@@ -300,8 +313,11 @@ async function runOnce(adapters, opts = {}) {
300
313
  let latestTimestamp = legacyCheckpoint?.last_memory_at || null;
301
314
  const adapterResults = {};
302
315
  const capMs = Number(opts.adapterCapMs) > 0 ? Number(opts.adapterCapMs) : ADAPTER_TICK_CAP_MS;
316
+ // WP-2 (D-5/S-21): one placement probe per ingest tick decides the iMessage adapter's
317
+ // activity; every other adapter is unaffected (host-local ingest runs everywhere).
318
+ const activeAdapters = await _activeAdapters(adapters, opts);
303
319
 
304
- for (const adapter of adapters) {
320
+ for (const adapter of activeAdapters) {
305
321
  const name = _adapterName(adapter);
306
322
  const inFlightKey = checkpointName(adapter);
307
323
  if (_abandonedBodies.has(inFlightKey)) {
@@ -10,6 +10,7 @@ const errorSink = require('../lib/error-sink');
10
10
  const { brainWrite } = require('./brain-write');
11
11
  const { listUnextractedProjection } = require('../memory/conversation-projection-v2');
12
12
  const { readSubscriberState } = require('../memory/conversation-subscriber');
13
+ const { resolvePlacement } = require('../lib/derivation-home');
13
14
  let embeddings;
14
15
  try { embeddings = require('../embeddings'); } catch { embeddings = null; }
15
16
 
@@ -138,6 +139,16 @@ async function runOnce(opts = {}) {
138
139
  const extractFn = opts.extractFn || extractKnowledge;
139
140
  const ownerName = brain.getOwnerName();
140
141
 
142
+ // D-5/S-18/S-20 (WP-2): the derivation home is the only node that runs the two steps whose
143
+ // INPUT is replicated rows — the conversation-projection top-up and rule-based entity
144
+ // learning over every memory's content. Extraction of THIS node's locally ingested pending
145
+ // memories (below) is host-local and stays on every node. `opts.placement` is the test seam;
146
+ // production resolves it from CTM (cached 60 s).
147
+ const placement = opts.placement || await resolvePlacement(opts);
148
+ const derivationHome = placement.home === true;
149
+ const learnEntitiesFn = opts.learnEntitiesFromText || learnEntitiesFromText;
150
+ const listUnextractedProjectionFn = opts.listUnextractedProjection || listUnextractedProjection;
151
+
141
152
  // Knowledge graph WP-2: memories outside the extraction allowlist
142
153
  // are marked skipped before the batch is selected, so they never count as backlog.
143
154
  const skipIds = brain.listMemoriesToSkipExtraction({ limit: SKIP_MARK_LIMIT });
@@ -147,10 +158,12 @@ async function runOnce(opts = {}) {
147
158
  const pending = brain.listMemories({ extractionRetryable: true, limit: batchSize });
148
159
  // D-10: top the batch up with un-extracted conversation projection rows created at or after
149
160
  // the subscriber's first bootstrap. extract_from_ms 0 = never bootstrapped: select none.
150
- if (pending.length < batchSize) {
161
+ // D-5 (WP-2): projection rows are replicated, so after WP-5 only the derivation home may
162
+ // extract them — a non-home node would re-extract the same transcript N times.
163
+ if (derivationHome && pending.length < batchSize) {
151
164
  const sinceMs = readSubscriberState(brain).extract_from_ms;
152
165
  if (sinceMs > 0) {
153
- pending.push(...listUnextractedProjection(brain.getDb(), { sinceMs, limit: batchSize - pending.length }));
166
+ pending.push(...listUnextractedProjectionFn(brain.getDb(), { sinceMs, limit: batchSize - pending.length }));
154
167
  }
155
168
  }
156
169
  if (pending.length === 0) {
@@ -274,10 +287,12 @@ async function runOnce(opts = {}) {
274
287
  }
275
288
 
276
289
  // Step 4a: Learn entities from memory content (rule-based, no API cost)
277
- await _measurePhase('entity_learning', { pending: pending.length }, () => {
290
+ // D-5/S-18 (WP-2): this scans ALL pending content, replicated rows included — the home only.
291
+ await _measurePhase('entity_learning', { pending: pending.length, derivation_home: derivationHome }, () => {
292
+ if (!derivationHome) return;
278
293
  for (const mem of pending) {
279
294
  if (mem.content && mem.content.length > 50) {
280
- learnEntitiesFromText(mem.content, ownerName);
295
+ learnEntitiesFn(mem.content, ownerName);
281
296
  }
282
297
  }
283
298
  }).catch(() => {});
@@ -218,6 +218,20 @@ const TOOL_OUTPUT_SCHEMAS = {
218
218
  walle_worker_wait: WORKER_WAIT_OUTPUT_SCHEMA,
219
219
  walle_resume_worker: RESUME_WORKER_OUTPUT_SCHEMA,
220
220
  walle_stop_worker: WORKER_STOP_OUTPUT_SCHEMA,
221
+ // WP-4 (§6.3/§6.4): the landing-queue tools. The status/conflicts bodies are CTM's own read
222
+ // model, so they stay open objects rather than a second, drifting copy of that shape.
223
+ walle_landing_status: ANY_OBJECT_SCHEMA,
224
+ walle_landing_submit: ANY_OBJECT_SCHEMA,
225
+ walle_landing_conflicts: ANY_OBJECT_SCHEMA,
226
+ walle_landing_wait: {
227
+ type: 'object',
228
+ properties: {
229
+ job: { anyOf: [ANY_OBJECT_SCHEMA, { type: 'null' }] },
230
+ woke_on: { type: 'string', enum: ['terminal', 'timeout'] },
231
+ },
232
+ required: ['job', 'woke_on'],
233
+ additionalProperties: true,
234
+ },
221
235
  };
222
236
 
223
237
  const READ_ONLY_TOOL_ANNOTATION = Object.freeze({
@@ -250,6 +264,17 @@ const IDEMPOTENT_WRITE_TOOL_ANNOTATION = Object.freeze({
250
264
  openWorldHint: false,
251
265
  });
252
266
 
267
+ // WP-2 (docs/remote-session-hub-bridge-2026-10-30.html §5 R-4/R-8, §6.4): `hub_exec` runs an
268
+ // arbitrary command on the hub Mac as the hub user, so nothing but the user's own grant bounds its
269
+ // effect. Destructive and non-idempotent; closed-world (the command runs on a machine in this pool,
270
+ // not against an open third-party service).
271
+ const DESTRUCTIVE_TOOL_ANNOTATION = Object.freeze({
272
+ readOnlyHint: false,
273
+ destructiveHint: true,
274
+ idempotentHint: false,
275
+ openWorldHint: false,
276
+ });
277
+
253
278
  // WP-11 (D-22, gate 7.5): every tool in MCP_TOOLS has an explicit entry here. There is
254
279
  // no read-only fallback — a tool with no entry throws at module load
255
280
  // (`mcp_tool_missing_annotation:<name>`), so a new tool cannot silently inherit a hint.
@@ -296,6 +321,13 @@ const TOOL_ANNOTATIONS = {
296
321
  walle_worker_wait: READ_ONLY_TOOL_ANNOTATION,
297
322
  walle_resume_worker: ADDITIVE_WRITE_TOOL_ANNOTATION,
298
323
  walle_stop_worker: IDEMPOTENT_WRITE_TOOL_ANNOTATION,
324
+ // WP-4 (local-landing-queue-multi-session-integration-2026-10-26.html §6.4): the landing tools.
325
+ // status/conflicts/wait only read CTM's queue; submit is a write that is idempotent -- a second
326
+ // submit of the same tip returns the existing job (CTM/CLI own that).
327
+ walle_landing_status: READ_ONLY_TOOL_ANNOTATION,
328
+ walle_landing_submit: IDEMPOTENT_WRITE_TOOL_ANNOTATION,
329
+ walle_landing_wait: READ_ONLY_TOOL_ANNOTATION,
330
+ walle_landing_conflicts: READ_ONLY_TOOL_ANNOTATION,
299
331
  // Slack + iMessage read tools (defined in mcp-tool-registry.js; their hints come from
300
332
  // this one table, resolved through buildMcpToolRegistry). The three Slack readers call
301
333
  // a live remote Slack API -> open world. The three iMessage readers read only the local
@@ -307,6 +339,20 @@ const TOOL_ANNOTATIONS = {
307
339
  walle_imessage_search: READ_ONLY_TOOL_ANNOTATION,
308
340
  walle_imessage_read_chat: READ_ONLY_TOOL_ANNOTATION,
309
341
  walle_imessage_list_chats: READ_ONLY_TOOL_ANNOTATION,
342
+ // WP-1 (remote-session-hub-bridge-2026-10-30.html §5 R-10, §6.4): reading a session that lives
343
+ // on ANOTHER machine in this pool is a closed-world read of the local hub-bridge lane.
344
+ hub_session_read: READ_ONLY_TOOL_ANNOTATION,
345
+ // WP-2 (remote-session-hub-bridge-2026-10-30.html §5 R-4/R-8/R-11, §6.4): the hub's own file
346
+ // system. Two readers are closed-world reads of a machine in this pool; `hub_exec` is the one
347
+ // destructive tool in the family — a command can write, and only the user's grant bounds it.
348
+ hub_read_file: READ_ONLY_TOOL_ANNOTATION,
349
+ hub_list: READ_ONLY_TOOL_ANNOTATION,
350
+ hub_exec: DESTRUCTIVE_TOOL_ANNOTATION,
351
+ // WP-3 (remote-session-hub-bridge-2026-10-30.html §3 P-2, §5 R-4, §6.4, §8 WP-3): listing a hub
352
+ // MCP server's tools is a closed-world read of a machine in this pool; calling one is DESTRUCTIVE
353
+ // — a browser tool can navigate, click and type in a real browser.
354
+ hub_mcp_list_tools: READ_ONLY_TOOL_ANNOTATION,
355
+ hub_mcp_call: DESTRUCTIVE_TOOL_ANNOTATION,
310
356
  };
311
357
 
312
358
  // Gate 7.5: the only way a tool gets hints. Throws (naming the tool) rather than
@@ -595,13 +641,14 @@ const BASE_MCP_TOOLS = [
595
641
  },
596
642
  {
597
643
  name: 'walle_get_session',
598
- description: 'Retrieve one bounded compact-envelope page of CTM session context by session/source id, or parse a bounded JSONL range when adapter_id and uri are provided. Continue with next_cursor; heavyweight provider payloads are never returned from CTM storage.',
644
+ description: 'Retrieve one bounded compact-envelope page of CTM session context by session/source id, by a session link or id from any machine in your pool (hub or box, via the `ref` arg), or parse a bounded JSONL range when adapter_id and uri are provided. Continue with next_cursor; heavyweight provider payloads are never returned from CTM storage.',
599
645
  inputSchema: {
600
646
  type: 'object',
601
647
  properties: {
602
648
  session_id: { type: 'string', description: 'CTM session id or agent session id to retrieve from cached DB tables' },
603
649
  session_ids: { type: 'array', items: { type: 'string' }, description: 'Several CTM/agent session ids to retrieve together' },
604
650
  source_id: { type: 'string', description: 'Stable source/session id to retrieve from memory' },
651
+ ref: { type: 'string', description: 'A session link (…#session=<id>), review=<id>, or id — the session can be on any machine in your pool' },
605
652
  adapter_id: { type: 'string', description: 'Optional adapter id for direct JSONL parse' },
606
653
  uri: { type: 'string', description: 'Optional JSONL path for direct parse' },
607
654
  limit: {
@@ -695,8 +742,8 @@ const BASE_MCP_TOOLS = [
695
742
  properties: {
696
743
  timeout_ms: { type: 'number', description: 'Timeout for each underlying CTM API call (default 5000)' },
697
744
  query: { type: 'string', description: 'Optional spoken model or route phrase (e.g. "glm 5.2"); when present the result adds `resolution` -- the same fail-closed resolution walle_delegate_implementation would apply.' },
698
- agent: { type: 'string', enum: ['claude', 'codex'], description: 'Worker CLI the resolution must be servable for (default claude)' },
699
- harness: { type: 'string', enum: ['claude-code', 'codex-cli'], description: 'Optional CLI harness; selects the effective worker agent for route servability' },
745
+ agent: { type: 'string', enum: ['claude', 'codex', 'dsh'], description: 'Worker CLI the resolution must be servable for (default claude)' },
746
+ harness: { type: 'string', enum: ['claude-code', 'codex-cli', 'dsh-acp'], description: 'Optional CLI harness; selects the effective worker agent for route servability' },
700
747
  },
701
748
  },
702
749
  },
@@ -711,8 +758,8 @@ const BASE_MCP_TOOLS = [
711
758
  timeout_ms: { type: 'number', description: 'Timeout for the CTM worker-start request (default 30000)' },
712
759
  route: { type: 'string', description: 'Provider row id, or the built-in anthropic-oauth. Omit (with `model` too) to use the lead\'s effective delegate pick -- Wall-E fills in both route and model before calling CTM, or answers lane "native" with no launch.' },
713
760
  model: { type: 'string', description: 'Model id, OR a spoken phrase such as "glm 5.2". Append " on <word>" to pin where it runs: an exact route id ("glm 5.3 on portkey-int-example-modal"), a class ("on portkey" = any Portkey-served route, "on direct" = a vendor-direct route), a connector type ("on modal", "on bedrock", "on vertex"), or tenant words ("on team-test"). The phrase is resolved against the registry for this agent: no match -> model_unknown; several models -> model_ambiguous with candidates; an identity whose every in-scope route is unhealthy -> route_unavailable with excluded[] reasons and offers[] you may name explicitly; an unknown word after "on" -> route_unavailable with reason route_not_found, tried[] and offers[] naming the routes that exist. chosen.reason starts with "pinned" when the qualifier was honoured -- never guessed. Omit both model and route to get the lead\'s effective delegate pick (result `source` is explicit when this field or route is given).' },
714
- agent: { type: 'string', enum: ['claude', 'codex'], description: 'Worker CLI agent (default claude)' },
715
- harness: { type: 'string', enum: ['claude-code', 'codex-cli'], description: 'Optional CLI harness alias; must agree with agent when both are supplied' },
761
+ agent: { type: 'string', enum: ['claude', 'codex', 'dsh'], description: 'Worker CLI agent (default claude)' },
762
+ harness: { type: 'string', enum: ['claude-code', 'codex-cli', 'dsh-acp'], description: 'Optional CLI harness alias; must agree with agent when both are supplied' },
716
763
  worker_profile: { type: 'string', enum: ['legacy', 'implementation', 'review'], description: 'Worker role profile (default implementation, bounded baseline; review = read-only census/research/review, report only, no workspace writes; legacy remains available for compatibility)' },
717
764
  allowed_tools: { type: 'array', items: { type: 'string' }, description: 'Optional explicit allow-list; default is .ctm.json worker.allowedTools, else a conservative built-in list' },
718
765
  max_turns: { type: 'number', description: 'Optional base step budget in provider requests (normally omit: CTM resolves the per-model base and renews the lease while the worker progresses)' },
@@ -777,6 +824,165 @@ const BASE_MCP_TOOLS = [
777
824
  },
778
825
  },
779
826
  },
827
+ // WP-4 (local-landing-queue-multi-session-integration-2026-10-26.html §6.3, §6.4, D-10): the
828
+ // landing-queue tools. CTM owns the queue (lib/api/landing.js); these read it and submit a
829
+ // branch to it -- an agent never merges or fast-forwards the target itself. `session` defaults to
830
+ // the caller's CTM session id when the stdio proxy supplies one (D-13); like the delegate tools
831
+ // it is not a documented public argument -- the proxy injects it, the server accepts it.
832
+ {
833
+ name: 'walle_landing_status',
834
+ description: 'Read the landing (merge) queue CTM manages for a repo: queue depth and order, per-job state/ETA, the conflict radar summary, and this session\'s own position. Read-only.',
835
+ inputSchema: {
836
+ type: 'object',
837
+ properties: {
838
+ repo: { type: 'string', description: 'Repository path (common dir or a worktree path); defaults to the caller session\'s repo' },
839
+ session: { type: 'string', description: 'CTM session id whose per-session view to include (defaults to the caller\'s session)' },
840
+ timeout_ms: { type: 'number', description: 'CTM call timeout (default 30000)' },
841
+ },
842
+ },
843
+ },
844
+ {
845
+ name: 'walle_landing_submit',
846
+ description: 'Submit the caller session\'s committed branch tip to CTM\'s landing queue and return its job (jobId, position, runner, eta_s) or the queue\'s typed refusal. Use this to integrate finished work; never merge or fast-forward the target branch yourself. Idempotent: a second submit of the same tip returns the existing job. Pass priority (with a reason) to move the job ahead.',
847
+ inputSchema: {
848
+ type: 'object',
849
+ properties: {
850
+ session: { type: 'string', description: 'CTM session id whose worktree to submit (defaults to the caller\'s session)' },
851
+ priority: {
852
+ type: 'string',
853
+ enum: ['normal', 'high', 'urgent'],
854
+ description: 'Queue priority. high = run next after the current gate; urgent = also stop a running lower-priority gate (only for a fix the target branch needs to go green). Re-submitting the same tip with a priority re-prioritizes the existing job.',
855
+ },
856
+ reason: {
857
+ type: 'string',
858
+ description: 'Required for high and urgent; shown in land status and recorded in the job audit trail.',
859
+ },
860
+ timeout_ms: { type: 'number', description: 'CTM call timeout (default 30000)' },
861
+ },
862
+ },
863
+ },
864
+ {
865
+ name: 'walle_landing_wait',
866
+ description: 'Wait for one landing job to reach a terminal state (landed, failed, blocked, canceled) by polling CTM\'s status route every 5 s (first poll immediate). Returns { job, woke_on: "terminal"|"timeout" }. Read-only; never a tight loop.',
867
+ inputSchema: {
868
+ type: 'object',
869
+ properties: {
870
+ jobId: { type: 'string', description: 'The landing job id returned by walle_landing_submit' },
871
+ session: { type: 'string', description: 'CTM session id (defaults to the caller\'s session)' },
872
+ repo: { type: 'string', description: 'Repository path to poll (defaults to the caller session\'s repo)' },
873
+ timeout_ms: { type: 'number', maximum: 540000, description: 'Maximum wait in milliseconds (default and maximum 540000)' },
874
+ },
875
+ required: ['jobId'],
876
+ },
877
+ },
878
+ {
879
+ name: 'walle_landing_conflicts',
880
+ description: 'Report the conflict radar for a repo: pairwise overlap between live branches (pairs), plus this session\'s own overlapping sessions. Derived from one landing-status call. Read-only.',
881
+ inputSchema: {
882
+ type: 'object',
883
+ properties: {
884
+ repo: { type: 'string', description: 'Repository path (common dir or a worktree path); defaults to the caller session\'s repo' },
885
+ session: { type: 'string', description: 'CTM session id whose overlaps to include (defaults to the caller\'s session)' },
886
+ timeout_ms: { type: 'number', description: 'CTM call timeout (default 30000)' },
887
+ },
888
+ },
889
+ },
890
+ {
891
+ // WP-1 (docs/remote-session-hub-bridge-2026-10-30.html §6.4, §8 WP-1): the one tool whose
892
+ // subject lives on ANOTHER machine. Every hub_* tool is HIDDEN from tools/list only for a session
893
+ // that is provably not a box session (hub-bridge-box-session-awareness-2026-10-31.html R-1/R-2 —
894
+ // see memory/hub-bridge-client.js isBoxSession and mcp-contract.js's `hideTools` option).
895
+ name: 'hub_session_read',
896
+ description: 'Read a CTM session that lives on another machine in your pool, normally the hub Mac driving this session. Use it for http://localhost:3456/...#session=<id> links, which point at the hub, not at this machine.',
897
+ inputSchema: {
898
+ type: 'object',
899
+ properties: {
900
+ ref: { type: 'string', description: 'The session to read: a hub URL containing #session=<id>, a review=<id> reference, or a bare session id' },
901
+ query: { type: 'string', description: 'Optional case-insensitive substring filter over the message text' },
902
+ max_messages: { type: 'number', description: 'Maximum messages to return, newest last (default 40, hard max 200)' },
903
+ machine: { type: 'string', description: 'Target machine (instance id or name). Default: the hub that created this session; pass it to choose another connected machine.' },
904
+ },
905
+ required: ['ref'],
906
+ },
907
+ },
908
+ {
909
+ // WP-2 (docs/remote-session-hub-bridge-2026-10-30.html §5 R-4/R-8, §6.4, §8 WP-2): read ONE
910
+ // file on the hub Mac — the machine driving this session — as the hub user. Hidden with the
911
+ // other hub_* tools when this machine shares a pool with nobody (R-10).
912
+ name: 'hub_read_file',
913
+ description: 'Read a file on the hub Mac (the machine driving this session), as the hub user. The first use may need the user to approve \'read\' for this session in the CTM session toolbar, then retry once.',
914
+ inputSchema: {
915
+ type: 'object',
916
+ properties: {
917
+ path: { type: 'string', description: 'Absolute path of the file to read (required)' },
918
+ offset: { type: 'number', description: 'First line to return, 0-based (default 0)' },
919
+ limit: { type: 'number', description: 'Maximum lines to return (default 2000, hard max 2000)' },
920
+ machine: { type: 'string', description: 'Target machine (instance id or name). Default: the hub that created this session; pass it to choose another connected machine.' },
921
+ },
922
+ required: ['path'],
923
+ },
924
+ },
925
+ {
926
+ // WP-2 (§6.4): one directory listing on the hub Mac. Same tier and same R-10 hiding as the read.
927
+ name: 'hub_list',
928
+ description: 'List a directory on the hub Mac (the machine driving this session), as the hub user. The first use may need the user to approve \'read\' for this session in the CTM session toolbar, then retry once.',
929
+ inputSchema: {
930
+ type: 'object',
931
+ properties: {
932
+ path: { type: 'string', description: 'Absolute path of the directory to list (required)' },
933
+ glob: { type: 'string', description: 'Optional simple name filter: * and ? only, matched against the entry name' },
934
+ machine: { type: 'string', description: 'Target machine (instance id or name). Default: the hub that created this session; pass it to choose another connected machine.' },
935
+ },
936
+ required: ['path'],
937
+ },
938
+ },
939
+ {
940
+ // WP-2 (§6.4): run a command on the hub Mac as the hub user. Annotations are DESTRUCTIVE — a
941
+ // command can write — and CTM gates it behind the user's own `exec` grant (R-4).
942
+ name: 'hub_exec',
943
+ description: 'Run a shell command on the hub Mac (the machine driving this session), as the hub user. DESTRUCTIVE: it can modify that machine. The first use needs the user to approve \'exec\' for this session in the CTM session toolbar, then retry once.',
944
+ inputSchema: {
945
+ type: 'object',
946
+ properties: {
947
+ command: { type: 'string', description: 'The command line to run (required; executed by the hub\'s login shell)' },
948
+ cwd: { type: 'string', description: 'Absolute working directory on the hub Mac (default: the hub user\'s home)' },
949
+ timeout_ms: { type: 'number', description: 'Kill the command after this many milliseconds (default 30000, hard max 120000)' },
950
+ machine: { type: 'string', description: 'Target machine (instance id or name). Default: the hub that created this session; pass it to choose another connected machine.' },
951
+ },
952
+ required: ['command'],
953
+ },
954
+ },
955
+ {
956
+ // WP-3 (docs/remote-session-hub-bridge-2026-10-30.html §3 P-2, D-4, §5 R-4, §6.4, §8 WP-3):
957
+ // list the tools of one HUB-side browser MCP server (tier `browser`). Hidden with the other
958
+ // hub_* tools when this machine shares a pool with nobody (R-10).
959
+ name: 'hub_mcp_list_tools',
960
+ description: 'List the tools of a browser MCP server running on the hub Mac (the machine driving this session). Use the hub Mac\'s browser. Server \'playwright\' is a separate automation browser (good for localhost pages). Server \'chrome-devtools\' attaches to the user\'s real Chrome, and Chrome asks the user to allow it the first time. Claude leads signed in with claude.ai may prefer native Claude in Chrome if it lists the hub browser. The first use needs the user to approve \'browser\' for this session in the CTM session toolbar, then retry once.',
961
+ inputSchema: {
962
+ type: 'object',
963
+ properties: {
964
+ server: { type: 'string', description: 'Which hub MCP server: \'playwright\' (automation browser) or \'chrome-devtools\' (the user\'s real Chrome)' },
965
+ machine: { type: 'string', description: 'Target machine (instance id or name). Default: the hub that created this session; pass it to choose another connected machine.' },
966
+ },
967
+ required: ['server'],
968
+ },
969
+ },
970
+ {
971
+ // WP-3 (§6.4): call one tool on one HUB-side browser MCP server. DESTRUCTIVE — a tool call can
972
+ // drive and modify a real browser — and CTM gates it behind the user's own `browser` grant (R-4).
973
+ name: 'hub_mcp_call',
974
+ description: 'Call a tool on a browser MCP server running on the hub Mac (the machine driving this session). DESTRUCTIVE: it can drive and modify a real browser. Use the hub Mac\'s browser. Server \'playwright\' is a separate automation browser (good for localhost pages). Server \'chrome-devtools\' attaches to the user\'s real Chrome, and Chrome asks the user to allow it the first time. Claude leads signed in with claude.ai may prefer native Claude in Chrome if it lists the hub browser. The first use needs the user to approve \'browser\' for this session in the CTM session toolbar, then retry once.',
975
+ inputSchema: {
976
+ type: 'object',
977
+ properties: {
978
+ server: { type: 'string', description: 'Which hub MCP server: \'playwright\' (automation browser) or \'chrome-devtools\' (the user\'s real Chrome)' },
979
+ tool: { type: 'string', description: 'The tool name to call on that server (see hub_mcp_list_tools)' },
980
+ arguments: { type: 'object', description: 'Arguments object for the tool, as its inputSchema describes' },
981
+ machine: { type: 'string', description: 'Target machine (instance id or name). Default: the hub that created this session; pass it to choose another connected machine.' },
982
+ },
983
+ required: ['server', 'tool'],
984
+ },
985
+ },
780
986
  ];
781
987
 
782
988
  function toolTitle(name) {
@@ -830,6 +1036,16 @@ const CONTROL_METHODS = Object.freeze([
830
1036
  ]);
831
1037
  const CONTROL_METHOD_SET = new Set(CONTROL_METHODS);
832
1038
 
1039
+ /**
1040
+ * R-1/R-2: `tools/list` is filtered through `options.hideTools` (a Set of names). A session that is
1041
+ * provably not a box session hides every `hub_*` tool — the caller (memory/hub-bridge-client.js via
1042
+ * bin/walle-mcp-stdio.js / mcp-server.js) owns that decision; this only refuses to advertise a name it was told to hide.
1043
+ */
1044
+ function _visibleTools(hideTools) {
1045
+ if (!hideTools || typeof hideTools.has !== 'function' || hideTools.size === 0) return MCP_TOOLS;
1046
+ return MCP_TOOLS.filter((tool) => !hideTools.has(tool.name));
1047
+ }
1048
+
833
1049
  function handleControlMessage(message, options = {}) {
834
1050
  const protocol = handleProtocolMessage(message, options);
835
1051
  if (protocol.handled) return protocol;
@@ -837,7 +1053,7 @@ function handleControlMessage(message, options = {}) {
837
1053
 
838
1054
  const protocolVersion = selectProtocolVersion(message.params?.protocolVersion);
839
1055
  const values = {
840
- 'tools/list': { tools: MCP_TOOLS },
1056
+ 'tools/list': { tools: _visibleTools(options.hideTools) },
841
1057
  'resources/list': { resources: MCP_RESOURCES },
842
1058
  'resources/templates/list': { resourceTemplates: MCP_RESOURCE_TEMPLATES },
843
1059
  'prompts/list': { prompts: MCP_PROMPTS },