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
@@ -0,0 +1,170 @@
1
+ 'use strict';
2
+
3
+ // WP-4 (local-landing-queue-multi-session-integration-2026-10-26.html §6.3, §6.4): the landing
4
+ // queue tools. CTM owns the queue (`GET /api/landing/status`, `POST /api/landing/submit`); these
5
+ // are thin shapers over ctm-context-client's two calls. The caller identity they default `session`
6
+ // to is injected by the stdio proxy (CALLER_IDENTITY_TOOLS in llm/worker-mcp-routing.js).
7
+ //
8
+ const path = require('node:path');
9
+
10
+ // Terminal job states, mirrored from CTM's lib/landing/ctm-view.js TERMINAL_STATES. COPIED, not
11
+ // required: Wall-E must never import a coding-task-manager module (WP-3 §5 D-7).
12
+ const TERMINAL_LANDING_STATES = Object.freeze(['landed', 'failed', 'blocked', 'canceled']);
13
+ // §6.4: the context-hint status read is a hard 300 ms budget -- a slow CTM must never delay a
14
+ // preflight, and a miss simply omits the line.
15
+ const LANDING_HINT_BUDGET_MS = 300;
16
+ // §6.4: the wait polls the status route every 5 s (first poll immediate), never a tight loop.
17
+ const LANDING_WAIT_POLL_MS = 5000;
18
+ const LANDING_WAIT_MAX_MS = 540000;
19
+
20
+ // The caller's CTM session id: an explicit `session`, else the stdio proxy's injected
21
+ // `parent_agent_session_id` (the same identity mechanism the delegate tools use -- D-13). `context`
22
+ // is the transport context (`executeTool`'s third argument); it is consulted only as a fallback for
23
+ // transports that carry the identity there rather than in the tool arguments.
24
+ function callerLandingSessionId(args = {}, context = {}) {
25
+ for (const value of [args.session, args.parent_agent_session_id, context && context.parentAgentSessionId, context && context.ctmSessionId]) {
26
+ if (typeof value === 'string' && value.trim()) return value.trim();
27
+ }
28
+ return '';
29
+ }
30
+
31
+ // WP-1 (§9 S-15): the job row is relayed verbatim, so the batch fields CTM's `jobSummary` carries
32
+ // (`batch: { id, members, attempt, index }`, null for a singleton) ride along without a second shape
33
+ // here. A row written by an older CTM simply has no `batch` key.
34
+ function landingJobById(status, jobId) {
35
+ const jobs = status && Array.isArray(status.jobs) ? status.jobs : [];
36
+ for (const job of jobs) {
37
+ if (job && String(job.id) === jobId) return job;
38
+ }
39
+ return null;
40
+ }
41
+
42
+ async function executeLandingStatus(ctmContextClient, args = {}, context = {}) {
43
+ const session = callerLandingSessionId(args, context);
44
+ const repo = typeof args.repo === 'string' && args.repo ? args.repo : undefined;
45
+ return ctmContextClient.landingStatus({ repo, session: session || undefined, timeoutMs: args.timeout_ms || 30000 });
46
+ }
47
+
48
+ // §6.4/D-11: land submit is idempotent -- a second submit of the same tip returns the SAME job (the
49
+ // CLI/CTM answer it), so the answer is relayed verbatim either way.
50
+ // WP-4 (§6.4): the two optional priority fields ride along as strings only. Nothing is validated
51
+ // here -- the CLI is the one validator (an unknown level or a missing reason for high/urgent is its
52
+ // exit 2, which CTM already maps to HTTP 400) -- and the client drops empty/absent values, so an
53
+ // unprioritized call still posts the historical `{session}` body.
54
+ async function executeLandingSubmit(ctmContextClient, args = {}, context = {}) {
55
+ const session = callerLandingSessionId(args, context);
56
+ return ctmContextClient.landingSubmit({
57
+ session: session || undefined,
58
+ priority: typeof args.priority === 'string' ? args.priority : undefined,
59
+ reason: typeof args.reason === 'string' ? args.reason : undefined,
60
+ timeoutMs: args.timeout_ms || 30000,
61
+ });
62
+ }
63
+
64
+ // §6.4: conflicts are derived from ONE status call -- the repo-wide radar pairs plus this session's
65
+ // own radar rows.
66
+ async function executeLandingConflicts(ctmContextClient, args = {}, context = {}) {
67
+ const session = callerLandingSessionId(args, context);
68
+ const status = await executeLandingStatus(ctmContextClient, args, context);
69
+ const radar = status && status.radar && typeof status.radar === 'object' ? status.radar : {};
70
+ const forSession = status && status.forSession && typeof status.forSession === 'object' ? status.forSession : {};
71
+ const entry = session ? forSession[session] : null;
72
+ return {
73
+ repo: status ? status.repo : undefined,
74
+ pairs: Array.isArray(radar.pairs) ? radar.pairs : [],
75
+ forSession: entry && entry.radar && Array.isArray(entry.radar.with) ? entry.radar.with : [],
76
+ };
77
+ }
78
+
79
+ // Test seam (§6.4 "the poll interval must be injectable for tests"): pollMs / now / sleep. Not a
80
+ // flag -- production always polls with the real clock and a real 5 s sleep.
81
+ let _landingWaitInjection = null;
82
+ function _setLandingWaitInjectionForTests(value) { _landingWaitInjection = value || null; }
83
+
84
+ function _defaultLandingSleep(ms) {
85
+ return new Promise((resolve) => setTimeout(resolve, ms));
86
+ }
87
+
88
+ // §6.4: poll GET /api/landing/status until jobs[] has this id in a terminal state or the timeout
89
+ // passes. First poll is immediate; the loop is bounded by the deadline, never a spin.
90
+ async function executeLandingWait(ctmContextClient, args = {}, context = {}) {
91
+ const jobId = typeof args.jobId === 'string' ? args.jobId.trim() : '';
92
+ if (!jobId) throw Object.assign(new Error('jobId is required'), { code: 'jobId_required' });
93
+ const injected = _landingWaitInjection || {};
94
+ const pollMs = Number.isInteger(injected.pollMs) ? injected.pollMs : LANDING_WAIT_POLL_MS;
95
+ const now = typeof injected.now === 'function' ? injected.now : Date.now;
96
+ const sleep = typeof injected.sleep === 'function' ? injected.sleep : _defaultLandingSleep;
97
+ const requested = Number.isInteger(args.timeout_ms) ? args.timeout_ms : LANDING_WAIT_MAX_MS;
98
+ const timeoutMs = Math.max(0, Math.min(LANDING_WAIT_MAX_MS, requested));
99
+ const session = callerLandingSessionId(args, context);
100
+ const repo = typeof args.repo === 'string' && args.repo ? args.repo : undefined;
101
+ const deadline = now() + timeoutMs;
102
+ let job = null;
103
+ for (;;) {
104
+ const remaining = Math.max(1000, deadline - now());
105
+ const status = await ctmContextClient.landingStatus({ repo, session: session || undefined, timeoutMs: Math.min(30000, remaining) });
106
+ job = landingJobById(status, jobId);
107
+ if (job && TERMINAL_LANDING_STATES.includes(job.state)) return { job, woke_on: 'terminal' };
108
+ if (now() >= deadline) return { job: job || null, woke_on: 'timeout' };
109
+ await sleep(pollMs);
110
+ }
111
+ }
112
+
113
+ // CTM names a repository by its git COMMON dir (`/x/tools/.git`), whose basename is `.git`; the
114
+ // line wants the repository's own name.
115
+ function repoDisplayName(repo) {
116
+ if (typeof repo !== 'string' || !repo) return '';
117
+ const base = path.basename(repo);
118
+ return base === '.git' ? path.basename(path.dirname(repo)) : base.replace(/\.git$/, '');
119
+ }
120
+
121
+ // §6.4/D-10: the ONE line walle_context_hint appends for a caller session with a queued job, or null
122
+ // when there is nothing to say (no entry, or a terminal state).
123
+ function landingHintLine(status, sessionId) {
124
+ if (!status || !sessionId) return null;
125
+ const forSession = status.forSession && typeof status.forSession === 'object' ? status.forSession : {};
126
+ const entry = forSession[sessionId];
127
+ if (!entry || !entry.jobId) return null;
128
+ if (TERMINAL_LANDING_STATES.includes(entry.state)) return null;
129
+ const order = status.queue && Array.isArray(status.queue.order) ? status.queue.order : [];
130
+ const index = order.indexOf(entry.jobId);
131
+ const position = Number.isInteger(entry.position) ? entry.position : (index >= 0 ? index + 1 : null);
132
+ const total = Number.isInteger(entry.total) ? entry.total : order.length;
133
+ const repo = repoDisplayName(status.repo);
134
+ const eta = Number.isFinite(entry.eta_s) ? ` · ETA ${Math.round(entry.eta_s / 60)}m` : '';
135
+ return `landing: job ${entry.jobId} #${position} of ${total} in ${repo} · ${entry.state}${eta} · do not re-gate or re-merge`;
136
+ }
137
+
138
+ // §6.4: the hint's status read, with the hard 300 ms budget. `null` means "no caller session -- do
139
+ // not call CTM, do not add a sources.landing key". `{ ok:false, error }` means the read was
140
+ // attempted and failed (line omitted, no error surfaces); `{ ok:true, line }` carries the line
141
+ // (null when the session simply has no non-terminal job).
142
+ async function landingHintForCaller(ctmContextClient, sessionId) {
143
+ if (!sessionId) return null;
144
+ let status;
145
+ try {
146
+ // `cached`: CTM answers from the view its sweep already holds -- a preflight must never start
147
+ // the `land status` child (a radar probe is N merge-trees).
148
+ status = await ctmContextClient.landingStatus({ session: sessionId, cached: true, timeoutMs: LANDING_HINT_BUDGET_MS });
149
+ } catch (err) {
150
+ // HANDLE: a timeout/refusal/unreachable CTM omits the line and reports the failure -- the hint
151
+ // itself never fails because of the landing probe.
152
+ return { ok: false, error: (err && err.code) || 'ctm_unreachable' };
153
+ }
154
+ if (!status || status.ok === false) {
155
+ const error = status && typeof status.error === 'string'
156
+ ? status.error
157
+ : (status && status.error && status.error.code) || 'ctm_unreachable';
158
+ // A caller CTM does not know as a session (e.g. a Codex thread id, or a non-CTM harness) simply
159
+ // has no landing state: same as "no job", so the hint stays byte-identical.
160
+ if (error === 'session_unknown') return null;
161
+ return { ok: false, error };
162
+ }
163
+ return { ok: true, line: landingHintLine(status, sessionId) };
164
+ }
165
+
166
+ module.exports = {
167
+ TERMINAL_LANDING_STATES, LANDING_HINT_BUDGET_MS, LANDING_WAIT_POLL_MS, LANDING_WAIT_MAX_MS,
168
+ callerLandingSessionId, executeLandingStatus, executeLandingSubmit, executeLandingConflicts,
169
+ executeLandingWait, landingHintLine, landingHintForCaller, repoDisplayName, _setLandingWaitInjectionForTests,
170
+ };
@@ -45,25 +45,33 @@ const ERROR_CODES = Object.freeze(Object.keys(ERROR_MESSAGES));
45
45
  const SECONDARY_PHASES = Object.freeze(['rollback', 'database-close', 'directory-close']);
46
46
  const SECONDARY_CODES = Object.freeze(['BUSY', 'IO_ERROR', 'OWNERSHIP', 'UNAVAILABLE']);
47
47
 
48
- // FU-9: WHICH client configuration refused, and WHY, as two more FIXED
48
+ // FU-9/D-3: WHICH client configuration refused, and WHY, as two more FIXED
49
49
  // vocabularies. Both exist only so one log line can name the failing client
50
50
  // and the kind of refusal — never a path, file name, parser message or any
51
51
  // other user text (the error class itself refuses free text in either field).
52
52
  //
53
- // DERIVED from mcp-gateway-migrate.js, the one migrator that captures, plans
54
- // and writes per-client documents (its path helpers, and the `client`-carrying
55
- // row it records for each of them):
53
+ // DERIVED from the two owners that capture, parse, plan and write per-client
54
+ // documents. `mcp-gateway-migrate.js` (its path helpers, and the `client`-
55
+ // carrying row it records for each of them):
56
56
  // 'claude-code' -> ~/.claude.json (_claudeJsonPath)
57
57
  // 'codex' -> ~/.codex/config.toml (_codexTomlPath)
58
58
  // 'gateway-config' -> ~/.walle/mcp-gateway.json (_gatewayConfigPath)
59
59
  // 'gateway-history' -> ~/.walle/live-data/mcp-gateway-snapshots/<stamp>/manifest.json
60
60
  // (_snapshotRoot)
61
- // Claude Desktop is deliberately absent: mcp-gateway-migrate.js never reads or
62
- // writes its config (only mcp-integration.js's MCP_TARGETS writer does, and
63
- // that writer attaches no client token).
61
+ // and `mcp-integration.js`'s MCP_TARGETS writer, whose MCP_TARGET_CLIENTS maps
62
+ // every ensure target id onto one of these tokens (D-3: no ensure target is
63
+ // anonymous):
64
+ // 'claude-code' -> ~/.claude.json (claude-code-user) and .mcp.json (claude-code-project)
65
+ // 'codex' -> ~/.codex/config.toml
66
+ // 'cursor' -> .cursor/mcp.json
67
+ // 'windsurf' -> .codeium/windsurf/mcp_config.json
68
+ // 'claude-desktop' -> Library/Application Support/Claude/claude_desktop_config.json
64
69
  const CLIENT_CONFIG_CLIENTS = Object.freeze([
65
70
  'claude-code',
66
71
  'codex',
72
+ 'cursor',
73
+ 'windsurf',
74
+ 'claude-desktop',
67
75
  'gateway-config',
68
76
  'gateway-history',
69
77
  ]);
@@ -278,6 +286,71 @@ function configError(code, options) {
278
286
  return new ClientConfigError(code, options);
279
287
  }
280
288
 
289
+ // ---------------------------------------------------------------------------
290
+ // FU-9, D-3: per-client error attribution. This module OWNS the fixed client
291
+ // vocabulary (CLIENT_CONFIG_CLIENTS), so the two helpers that put a client
292
+ // token onto an owned refusal live here too — one implementation, used by both
293
+ // per-client writers (mcp-gateway-migrate.js and mcp-integration.js).
294
+ //
295
+ // A refusal raised while handling ONE client's configuration — its capture, its
296
+ // parse/discovery, its plan, its write — is re-thrown as the SAME fixed code
297
+ // carrying that client's token, so the boot line names the failing file instead
298
+ // of only "could not be parsed safely".
299
+ //
300
+ // Only a genuinely OWNED ClientConfigError (private-field brand + immutable
301
+ // fixed fields, re-validated by isClientConfigError) is copied, and only its
302
+ // bounded fields travel with it. Anything else — a raw Error, a string, a falsy
303
+ // throw — is rethrown UNCHANGED, and no path, message, parser text or byte ever
304
+ // enters the copy (the error class refuses anything outside its fixed
305
+ // vocabulary).
306
+ // ---------------------------------------------------------------------------
307
+
308
+ // Descriptor-only read: an accessor is never executed, so a hostile getter can
309
+ // neither run nor substitute a value here.
310
+ function _readFixedField(error, key) {
311
+ const descriptor = Object.getOwnPropertyDescriptor(error, key);
312
+ return descriptor && 'value' in descriptor ? descriptor.value : undefined;
313
+ }
314
+
315
+ function attributeClient(client, error) {
316
+ if (!isClientConfigError(error)) return error;
317
+ if (_readFixedField(error, 'client') !== undefined) return error; // already attributed
318
+ const code = _readFixedField(error, 'code');
319
+ const options = attributionOptions(error);
320
+ options.client = client;
321
+ if (_readFixedField(error, 'operationCompleted') === true) options.operationCompleted = true;
322
+ const secondaryIssues = _readFixedField(error, 'secondaryIssues');
323
+ if (secondaryIssues !== undefined) options.secondaryIssues = secondaryIssues;
324
+ return new ClientConfigError(code, options);
325
+ }
326
+
327
+ // The bounded WHICH-client attribution of an OWNED refusal, as a fresh options
328
+ // bag for a REBUILT error: `{client?}` plus `{refusal?}` while the code stays
329
+ // CLIENT_CONFIG_PARSE_REFUSED (the error class refuses `refusal` on any other
330
+ // code). This is the ONE place the two field NAMES are read off a refusal —
331
+ // `attributeClient` copies them onto the same error, and a caller that has to
332
+ // REBUILD one (a later fixed code, merged cleanup rows) carries them across
333
+ // with this, so a rebuild can never quietly drop the attribution again.
334
+ function attributionOptions(error) {
335
+ const options = {};
336
+ const client = _readFixedField(error, 'client');
337
+ if (client !== undefined) options.client = client;
338
+ if (_readFixedField(error, 'code') === 'CLIENT_CONFIG_PARSE_REFUSED') {
339
+ const refusal = _readFixedField(error, 'refusal');
340
+ if (refusal !== undefined) options.refusal = refusal;
341
+ }
342
+ return options;
343
+ }
344
+
345
+ // Run ONE per-client operation, attributing whatever owned refusal it raises.
346
+ function asClient(client, run) {
347
+ try {
348
+ return run();
349
+ } catch (error) {
350
+ throw attributeClient(client, error);
351
+ }
352
+ }
353
+
281
354
  // ---------------------------------------------------------------------------
282
355
  // Small structural utilities. `__proto__` (and any other dangerous key) must
283
356
  // never reach a native object's prototype, so every decoded member is written
@@ -540,10 +613,14 @@ function _tomlMakeNode(kind, segment, parentPath, extra) {
540
613
 
541
614
  // Walk (creating, when needed) the implicit/declared table named by one dotted
542
615
  // segment. Traversing a DECLARED table is legal (`[a.b]` after `[a]`);
543
- // traversing a scalar or an array-of-tables entry is not.
616
+ // traversing a scalar is not. Traversing an ARRAY OF TABLES is legal TOML 1.0
617
+ // (`[[a.b]]` / `[a.b]` refer to the most recent element) — the node is RETURNED
618
+ // and the caller absorbs the whole header+body range into it (D-2); nothing
619
+ // under an array of tables is ever decoded, indexed or edited.
544
620
  function _tomlChildContainer(parent, segment, start) {
545
621
  const existing = parent.children.get(segment);
546
622
  if (existing) {
623
+ if (existing.kind === 'array-table') return existing;
547
624
  if (existing.kind !== 'table') refuse('CLIENT_CONFIG_PARSE_REFUSED', 'shape');
548
625
  return existing;
549
626
  }
@@ -561,7 +638,12 @@ function _insertTomlKeyValue(container, kvNode, text) {
561
638
  const range = _nodeRange(kvNode);
562
639
  if (!segments || !range) refuse('CLIENT_CONFIG_PARSE_REFUSED', 'shape');
563
640
  let parent = container;
564
- for (let i = 0; i < segments.length - 1; i += 1) parent = _tomlChildContainer(parent, segments[i], range[0]);
641
+ for (let i = 0; i < segments.length - 1; i += 1) {
642
+ parent = _tomlChildContainer(parent, segments[i], range[0]);
643
+ // S-5: a dotted key whose prefix passes THROUGH an array of tables stays
644
+ // refused `shape` (valid TOML, but not a shape this contract can index).
645
+ if (parent.kind !== 'table') refuse('CLIENT_CONFIG_PARSE_REFUSED', 'shape');
646
+ }
565
647
  const segment = segments[segments.length - 1];
566
648
  if (parent.children.has(segment)) refuse('CLIENT_CONFIG_PARSE_REFUSED', 'duplicate-key');
567
649
  const native = kvNode.value;
@@ -586,18 +668,46 @@ function _insertTomlKeyValue(container, kvNode, text) {
586
668
  // Insert a `[a.b]` header and its body. The header extent is derived from the
587
669
  // native KEY token plus the closing bracket, never from table.range[1] (which
588
670
  // the parser extends over the table BODY).
671
+ //
672
+ // D-1/D-2: an array-of-tables node owns `entries: [{start,end}]`, one per
673
+ // source region, in source order. A repeated `[[a]]` APPENDS an entry instead
674
+ // of refusing, and any header (`[a.x]` / `[[a.x…]]`) whose path passes through
675
+ // an existing array-table is ABSORBED the same way — TOML 1.0 says such a
676
+ // reference names the most recently defined element. Nothing under an array of
677
+ // tables is decoded, indexed or editable.
678
+ function _absorbTomlArrayTableEntry(node, start, end) {
679
+ node.entries.push({ start, end });
680
+ return node;
681
+ }
682
+
589
683
  function _insertTomlTable(root, tableNode, text) {
590
684
  const segments = _tomlKeySegments(tableNode);
591
685
  const range = _nodeRange(tableNode);
592
686
  if (!segments || !range) refuse('CLIENT_CONFIG_PARSE_REFUSED', 'shape');
593
687
  const isArray = String(tableNode.kind || 'standard') === 'array';
594
688
  let container = root;
595
- for (let i = 0; i < segments.length - 1; i += 1) container = _tomlChildContainer(container, segments[i], range[0]);
689
+ for (let i = 0; i < segments.length - 1; i += 1) {
690
+ container = _tomlChildContainer(container, segments[i], range[0]);
691
+ // D-2: this header descends into an array of tables — absorb its whole
692
+ // range (header + body) and stop. Its body is never walked.
693
+ if (container.kind === 'array-table') return _absorbTomlArrayTableEntry(container, range[0], range[1]);
694
+ }
596
695
  const segment = segments[segments.length - 1];
597
696
  const existing = container.children.get(segment);
598
697
  if (isArray) {
599
- if (existing) refuse('CLIENT_CONFIG_PARSE_REFUSED', 'shape');
600
- const node = _tomlMakeNode('array-table', segment, container.path, { header: tableNode, start: range[0], end: range[1] });
698
+ if (existing) {
699
+ // D-1: a second `[[a]]` appends an entry to the SAME node. Any other
700
+ // existing kind (a scalar, or a table declared by `[a]`/`a.b = 1`) is
701
+ // not this contract's shape and keeps refusing.
702
+ if (existing.kind !== 'array-table') refuse('CLIENT_CONFIG_PARSE_REFUSED', 'shape');
703
+ return _absorbTomlArrayTableEntry(existing, range[0], range[1]);
704
+ }
705
+ const node = _tomlMakeNode('array-table', segment, container.path, {
706
+ header: tableNode,
707
+ entries: [{ start: range[0], end: range[1] }],
708
+ start: range[0],
709
+ end: range[1],
710
+ });
601
711
  container.children.set(segment, node);
602
712
  return node;
603
713
  }
@@ -640,7 +750,9 @@ function _collectTomlItems(node, out) {
640
750
  out.push({ start: node.headerStart, end: node.headerEnd, path: node.path, header: true });
641
751
  }
642
752
  } else if (node.kind === 'array-table') {
643
- out.push({ start: node.start, end: node.end, path: node.path, arrayTable: true });
753
+ // S-3: one item PER source entry, so the region/contiguity math sees each
754
+ // `[[a]]` (and every absorbed descendant header) separately.
755
+ for (const entry of node.entries) out.push({ start: entry.start, end: entry.end, path: node.path, arrayTable: true });
644
756
  return;
645
757
  }
646
758
  if (node.children) for (const child of node.children.values()) _collectTomlItems(child, out);
@@ -658,7 +770,11 @@ function _tomlPathIsUnder(prefix, path) {
658
770
  // header for).
659
771
  function _tomlNodeExtent(node) {
660
772
  if (!node) return null;
661
- if (node.kind === 'value' || node.kind === 'array-table') {
773
+ if (node.kind === 'array-table') {
774
+ // S-4: the union of every owned source entry (D-1); entries are in source order.
775
+ return { start: node.entries[0].start, end: Math.max(...node.entries.map((entry) => entry.end)) };
776
+ }
777
+ if (node.kind === 'value') {
662
778
  return node.start == null ? null : { start: node.start, end: node.end };
663
779
  }
664
780
  let start = node.headerStart != null ? node.headerStart : null;
@@ -1579,6 +1695,9 @@ module.exports = {
1579
1695
  UNSUPPORTED_CONVERSION_FIELDS,
1580
1696
  admitThirdPartyMigrationTuple,
1581
1697
  applySourceEdits,
1698
+ asClient,
1699
+ attributeClient,
1700
+ attributionOptions,
1582
1701
  buildOwnershipManifest,
1583
1702
  configError,
1584
1703
  BOUNDARY_VALUES,
@@ -41,6 +41,8 @@ const {
41
41
  SECONDARY_PHASES,
42
42
  admitThirdPartyMigrationTuple,
43
43
  applySourceEdits,
44
+ asClient,
45
+ attributionOptions,
44
46
  buildOwnershipManifest,
45
47
  deepEqualJson,
46
48
  creationBoundaryEvidence,
@@ -103,49 +105,13 @@ function _readTextSafe(filePath) {
103
105
  }
104
106
 
105
107
  // ---------------------------------------------------------------------------
106
- // FU-9: per-client error attribution (docs: mcp-client-config.js's
107
- // CLIENT_CONFIG_CLIENTS). A refusal raised while handling ONE client's
108
- // configuration — its capture, its parse/discovery, its plan, its write — is
109
- // re-thrown as the SAME fixed code carrying that client's token, so the boot
110
- // line names the failing file instead of only "could not be parsed safely".
111
- //
112
- // Only a genuinely OWNED ClientConfigError (private-field brand + immutable
113
- // fixed fields, re-validated by isClientConfigError) is copied, and only its
114
- // bounded fields travel with it. Anything else — a raw Error, a string, a falsy
115
- // throw — is rethrown UNCHANGED, and no path, message, parser text or byte ever
116
- // enters the copy (the error class refuses anything outside its fixed
117
- // vocabulary).
108
+ // FU-9/D-3: per-client error attribution now lives in the leaf that OWNS the
109
+ // fixed client vocabulary — `attributeClient` / `asClient` in
110
+ // mcp-client-config.js (see the block above them). Only its callers remain
111
+ // here: every per-client capture/parse/plan step below runs inside
112
+ // `asClient(clientToken, fn)` so a refusal names the failing client.
118
113
  // ---------------------------------------------------------------------------
119
114
 
120
- // Descriptor-only read: an accessor is never executed, so a hostile getter can
121
- // neither run nor substitute a value here.
122
- function _readFixedField(error, key) {
123
- const descriptor = Object.getOwnPropertyDescriptor(error, key);
124
- return descriptor && 'value' in descriptor ? descriptor.value : undefined;
125
- }
126
-
127
- function _attributeClient(client, error) {
128
- if (!isClientConfigError(error)) return error;
129
- if (_readFixedField(error, 'client') !== undefined) return error; // already attributed
130
- const code = _readFixedField(error, 'code');
131
- const options = { client };
132
- const refusal = _readFixedField(error, 'refusal');
133
- if (code === 'CLIENT_CONFIG_PARSE_REFUSED' && refusal !== undefined) options.refusal = refusal;
134
- if (_readFixedField(error, 'operationCompleted') === true) options.operationCompleted = true;
135
- const secondaryIssues = _readFixedField(error, 'secondaryIssues');
136
- if (secondaryIssues !== undefined) options.secondaryIssues = secondaryIssues;
137
- return new ClientConfigError(code, options);
138
- }
139
-
140
- // Run ONE per-client operation, attributing whatever owned refusal it raises.
141
- function _asClient(client, run) {
142
- try {
143
- return run();
144
- } catch (error) {
145
- throw _attributeClient(client, error);
146
- }
147
- }
148
-
149
115
  // ---------------------------------------------------------------------------
150
116
  // Minimal span-tracking JSON reader — only what this module needs: given raw
151
117
  // JSON text, returns a tree of {start, end, value|entries|items} nodes so a
@@ -987,12 +953,10 @@ function _migrationBodyFailure(primary, cleanupIssues, progress) {
987
953
  // the code stays CLIENT_CONFIG_PARSE_REFUSED (it is meaningless, and refused
988
954
  // by the error class, on any other code).
989
955
  if (owned) {
990
- const client = _readFixedField(primary, 'client');
991
- if (client !== undefined) options.client = client;
992
- if (primary.code === 'CLIENT_CONFIG_PARSE_REFUSED') {
993
- const refusal = _readFixedField(primary, 'refusal');
994
- if (refusal !== undefined) options.refusal = refusal;
995
- }
956
+ // `attributionOptions` (mcp-client-config.js) is the ONE reader of those two
957
+ // fixed field names: the rebuild cannot lose — and cannot re-spell — the
958
+ // attribution the raising `asClient` attached.
959
+ Object.assign(options, attributionOptions(primary));
996
960
  }
997
961
  if (changed) {
998
962
  if (completed) options.operationCompleted = true;
@@ -1085,27 +1049,27 @@ async function enableGateway({ homeDir, port, lockDir, lockTimeoutMs } = {}) {
1085
1049
  let bodyFailed = false;
1086
1050
  try {
1087
1051
  // FU-9: each capture/discovery/plan below is ONE client's operation, so
1088
- // its refusal carries that client's token (`_asClient`).
1089
- const claudeSource = _asClient('claude-code', () => captureClientConfigFile(claudePath, { mutexContext: context, allowMissing: true }));
1052
+ // its refusal carries that client's token (`asClient`).
1053
+ const claudeSource = asClient('claude-code', () => captureClientConfigFile(claudePath, { mutexContext: context, allowMissing: true }));
1090
1054
  acquired.push(claudeSource);
1091
- const codexSource = _asClient('codex', () => captureClientConfigFile(codexPath, { mutexContext: context, allowMissing: true }));
1055
+ const codexSource = asClient('codex', () => captureClientConfigFile(codexPath, { mutexContext: context, allowMissing: true }));
1092
1056
  acquired.push(codexSource);
1093
- const gatewaySource = _asClient('gateway-config', () => captureClientConfigFile(gatewayPath, { mutexContext: context, allowMissing: true }));
1057
+ const gatewaySource = asClient('gateway-config', () => captureClientConfigFile(gatewayPath, { mutexContext: context, allowMissing: true }));
1094
1058
  acquired.push(gatewaySource);
1095
1059
  // Strict, in-hold discovery: a parse/read failure REFUSES (never "empty").
1096
1060
  const discovered = [
1097
- ...(claudeSource.text === null ? [] : _asClient('claude-code', () => _discoverClaudeJsonStrict(claudeSource.text))),
1098
- ...(codexSource.text === null ? [] : _asClient('codex', () => _discoverCodexTomlStrict(codexSource.text))),
1061
+ ...(claudeSource.text === null ? [] : asClient('claude-code', () => _discoverClaudeJsonStrict(claudeSource.text))),
1062
+ ...(codexSource.text === null ? [] : asClient('codex', () => _discoverCodexTomlStrict(codexSource.text))),
1099
1063
  ];
1100
1064
  const claudeEntries = discovered.filter((entry) => entry.client === 'claude');
1101
1065
  const codexEntries = discovered.filter((entry) => entry.client === 'codex');
1102
1066
  const claudePlan = claudeEntries.length
1103
- ? _asClient('claude-code', () => _planClaudeMigration(claudeSource.text, claudeEntries, gatewayPort))
1067
+ ? asClient('claude-code', () => _planClaudeMigration(claudeSource.text, claudeEntries, gatewayPort))
1104
1068
  : { text: claudeSource.text, rows: [] };
1105
1069
  const codexPlan = codexEntries.length
1106
- ? _asClient('codex', () => _planCodexMigration(codexSource.text, codexEntries, gatewayPort))
1070
+ ? asClient('codex', () => _planCodexMigration(codexSource.text, codexEntries, gatewayPort))
1107
1071
  : { text: codexSource.text, rows: [] };
1108
- const merged = _asClient('gateway-config', () => _mergedGatewayConfig(scopedHome, discovered, gatewayPort, {
1072
+ const merged = asClient('gateway-config', () => _mergedGatewayConfig(scopedHome, discovered, gatewayPort, {
1109
1073
  claude: claudeSource.text,
1110
1074
  codex: codexSource.text,
1111
1075
  gatewayText: gatewaySource.text,
@@ -1244,7 +1208,7 @@ async function disableGateway({ homeDir, lockDir, lockTimeoutMs } = {}) {
1244
1208
  const scopedHome = context.homeDir;
1245
1209
  // The reader selects the gateway-enable operation EXPLICITLY, so an
1246
1210
  // own-inject (ensure-walle-entry) record can never become this proof.
1247
- const manifestInfo = _asClient('gateway-history', () => _newestManifest(scopedHome, OPERATIONS[0]));
1211
+ const manifestInfo = asClient('gateway-history', () => _newestManifest(scopedHome, OPERATIONS[0]));
1248
1212
  const acquired = [];
1249
1213
  // GEN11: this disable's own business-write progress — one write per
1250
1214
  // document, consumed so a later physical failure is reported honestly.
@@ -1256,9 +1220,9 @@ async function disableGateway({ homeDir, lockDir, lockTimeoutMs } = {}) {
1256
1220
  let bodyFailure = null;
1257
1221
  let bodyFailed = false;
1258
1222
  try {
1259
- const claudeSource = _asClient('claude-code', () => captureClientConfigFile(_claudeJsonPath(scopedHome), { mutexContext: context, allowMissing: true }));
1223
+ const claudeSource = asClient('claude-code', () => captureClientConfigFile(_claudeJsonPath(scopedHome), { mutexContext: context, allowMissing: true }));
1260
1224
  acquired.push(claudeSource);
1261
- const codexSource = _asClient('codex', () => captureClientConfigFile(_codexTomlPath(scopedHome), { mutexContext: context, allowMissing: true }));
1225
+ const codexSource = asClient('codex', () => captureClientConfigFile(_codexTomlPath(scopedHome), { mutexContext: context, allowMissing: true }));
1262
1226
  acquired.push(codexSource);
1263
1227
  // GEN11 (brief criterion 3): EVERY restore is PLANNED here, before the
1264
1228
  // FIRST physical write — the legacy proof-based restore for each client
@@ -1279,12 +1243,12 @@ async function disableGateway({ homeDir, lockDir, lockTimeoutMs } = {}) {
1279
1243
  const claudeRows = rows.filter((row) => row.client === 'claude');
1280
1244
  const codexRows = rows.filter((row) => row.client === 'codex');
1281
1245
  if (claudeRows.length && claudeText !== null) {
1282
- const plan = _asClient('claude-code', () => _planRestoreWithProof(parseClientConfig(claudeText, { format: 'json' }), claudeRows));
1246
+ const plan = asClient('claude-code', () => _planRestoreWithProof(parseClientConfig(claudeText, { format: 'json' }), claudeRows));
1283
1247
  claudeText = plan.text;
1284
1248
  restored += plan.restored;
1285
1249
  }
1286
1250
  if (codexRows.length && codexText !== null) {
1287
- const plan = _asClient('codex', () => _planRestoreWithProof(parseClientConfig(codexText, { format: 'toml' }), codexRows));
1251
+ const plan = asClient('codex', () => _planRestoreWithProof(parseClientConfig(codexText, { format: 'toml' }), codexRows));
1288
1252
  codexText = plan.text;
1289
1253
  restored += plan.restored;
1290
1254
  }
@@ -1298,7 +1262,7 @@ async function disableGateway({ homeDir, lockDir, lockTimeoutMs } = {}) {
1298
1262
  // the plugin revert) — no second write, no intermediate on-disk state.
1299
1263
  let pluginResult = { ok: true, reverted: 0, reason: 'no_manifest' };
1300
1264
  if (claudeText !== null) {
1301
- const revertPlan = _asClient('claude-code', () => _planPluginRevertEdits(claudeText, scopedHome));
1265
+ const revertPlan = asClient('claude-code', () => _planPluginRevertEdits(claudeText, scopedHome));
1302
1266
  pluginResult = { ok: true, reverted: revertPlan.reverted };
1303
1267
  if (revertPlan.reason) pluginResult.reason = revertPlan.reason;
1304
1268
  claudeText = revertPlan.text;
@@ -1762,12 +1726,12 @@ async function revertPluginOverrides({ homeDir, lockDir, lockTimeoutMs } = {}) {
1762
1726
  return withClientConfigLock((context) => {
1763
1727
  const scopedHome = context.homeDir;
1764
1728
  const claudeJsonPath = _claudeJsonPath(scopedHome);
1765
- const source = _asClient('claude-code', () => captureClientConfigFile(claudeJsonPath, { mutexContext: context, allowMissing: true }));
1729
+ const source = asClient('claude-code', () => captureClientConfigFile(claudeJsonPath, { mutexContext: context, allowMissing: true }));
1766
1730
  try {
1767
1731
  if (source.text === null) return { ok: true, reverted: 0, reason: 'no_claude_json' };
1768
1732
  let plan;
1769
1733
  try {
1770
- plan = _asClient('claude-code', () => _planPluginRevertEdits(source.text, scopedHome));
1734
+ plan = asClient('claude-code', () => _planPluginRevertEdits(source.text, scopedHome));
1771
1735
  } catch (error) {
1772
1736
  if (isClientConfigError(error) && error.code === 'CLIENT_CONFIG_RESTORE_REFUSED') throw error;
1773
1737
  if (isClientConfigError(error) && error.code === 'CLIENT_CONFIG_PARSE_REFUSED') {