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
@@ -10,6 +10,7 @@
10
10
  if (root) root.BackgroundWork = api;
11
11
  })(typeof globalThis !== 'undefined' ? globalThis : this, function () {
12
12
  const LABEL_MAX = 80;
13
+ const GLOBAL = typeof globalThis === 'undefined' ? null : globalThis;
13
14
 
14
15
  function tasksOf(work) {
15
16
  return work && Array.isArray(work.tasks) ? work.tasks : [];
@@ -27,9 +28,10 @@
27
28
  return 'bg ' + word + (allQuiet ? ' · quiet ' + ageText(tasks[0].activeAt, now) : '');
28
29
  }
29
30
 
30
- function clip(label) {
31
+ function clip(label, max) {
31
32
  const text = String(label || '');
32
- return text.length > LABEL_MAX ? text.slice(0, LABEL_MAX - 1) + '…' : text;
33
+ const limit = Number(max) > 0 ? Number(max) : LABEL_MAX;
34
+ return text.length > limit ? text.slice(0, limit - 1) + '…' : text;
33
35
  }
34
36
 
35
37
  function ageText(since, now) {
@@ -45,34 +47,151 @@
45
47
  return tasksOf(work).map((t) => ((t && t.type) || 'task') + ': ' + clip(t && t.label) + ' · ' + ageText(t && t.since, now) + (t && t.quiet === true ? ' · quiet ' + ageText(t.activeAt, now) : '')).join('\n');
46
48
  }
47
49
 
48
- // Hover-card body: one row per task (type, label, age). fmt.cap(text, n) and fmt.age(ms) are the card's own
49
- // formatters. Returns null when there is nothing to list.
50
+ // §6.4 operator stop: the client half of POST /api/sessions/:id/background/:taskId/stop. One pending
51
+ // entry per (session, task) is the whole client state of one stop — armed by the click's confirm, and
52
+ // ended either by a render for that session no longer listing the task id, or STOP_PENDING_MS later.
53
+ const STOP_PENDING_MS = 30_000;
54
+ const pendingStops = new Map();
55
+ let nowMs = () => Date.now();
56
+
57
+ // Test seam (no timer is ever armed here): the pending window and every label age read this clock.
58
+ function setClock(fn) {
59
+ nowMs = typeof fn === 'function' ? fn : () => Date.now();
60
+ }
61
+
62
+ function pendingKey(sessionId, taskId) {
63
+ return sessionId + '\u0000' + String(taskId);
64
+ }
65
+
66
+ function readPending(key) {
67
+ const entry = pendingStops.get(key);
68
+ if (!entry) return null;
69
+ if (nowMs() - entry.at >= STOP_PENDING_MS) {
70
+ pendingStops.delete(key);
71
+ return null;
72
+ }
73
+ return entry;
74
+ }
75
+
76
+ // A render for one session drops every pending stop whose task that render no longer lists.
77
+ function prunePending(sessionId, tasks) {
78
+ const prefix = sessionId + '\u0000';
79
+ const listed = new Set(tasks.map((t) => String(t && t.id)));
80
+ for (const key of Array.from(pendingStops.keys())) {
81
+ if (key.startsWith(prefix) && !listed.has(key.slice(prefix.length))) pendingStops.delete(key);
82
+ }
83
+ }
84
+
85
+ function stopPath(sessionId, taskId) {
86
+ return '/api/sessions/' + encodeURIComponent(sessionId) + '/background/' + encodeURIComponent(taskId) + '/stop';
87
+ }
88
+
89
+ function stopConfirmText(task, fmt) {
90
+ return 'Stop background shell ' + task.id + '?\n' + fmt.cap(task.label, LABEL_MAX) + '\nrunning ' + fmt.age(task.since);
91
+ }
92
+
93
+ function askStop(task, fmt) {
94
+ const ask = typeof fmt.confirm === 'function'
95
+ ? fmt.confirm
96
+ : (GLOBAL && typeof GLOBAL.confirm === 'function' ? GLOBAL.confirm.bind(GLOBAL) : null);
97
+ return typeof ask === 'function' && ask(stopConfirmText(task, fmt)) === true;
98
+ }
99
+
100
+ // A non-2xx body is the only place an `<error code>` comes from; an unreadable body falls back to the status.
101
+ async function failureCode(res) {
102
+ let payload = null;
103
+ try { payload = await res.json(); } catch (err) { payload = null; }
104
+ const code = payload && (payload.error || payload.code);
105
+ if (code) return String(code);
106
+ return Number(res.status) >= 400 ? 'http_' + Number(res.status) : 'request_failed';
107
+ }
108
+
109
+ async function stopOutcome(request, path) {
110
+ try {
111
+ const res = await request(path, { method: 'POST' });
112
+ if (!res || res.ok === false || Number(res.status) >= 400) return { ok: false, code: res ? await failureCode(res) : 'request_failed' };
113
+ return { ok: true, code: '' };
114
+ } catch (err) {
115
+ const code = err && (err.payload?.error || err.payload?.code || err.code);
116
+ if (code) return { ok: false, code: String(code) };
117
+ return { ok: false, code: Number(err && err.status) >= 400 ? 'http_' + Number(err.status) : 'request_failed' };
118
+ }
119
+ }
120
+
121
+ function showStopState(status, button, entry) {
122
+ status.textContent = entry.code ? 'not stopped: ' + entry.code : 'stopping…';
123
+ button.disabled = !entry.code;
124
+ }
125
+
126
+ function defaultRequest(path, options) {
127
+ if (!GLOBAL || typeof GLOBAL.fetch !== 'function') return Promise.reject(new Error('fetch unavailable'));
128
+ return GLOBAL.fetch(path, options);
129
+ }
130
+
131
+ // One click: confirm, one POST (no body), then "stopping…" until the row leaves the next render or 30 s pass.
132
+ async function stopTask(status, button, sessionId, task, fmt, request, ev) {
133
+ if (ev && typeof ev.preventDefault === 'function') ev.preventDefault();
134
+ if (ev && typeof ev.stopPropagation === 'function') ev.stopPropagation();
135
+ if (button.disabled === true) return null;
136
+ if (!askStop(task, fmt)) return null;
137
+ const key = pendingKey(sessionId, task.id);
138
+ pendingStops.set(key, { code: '', at: nowMs() });
139
+ showStopState(status, button, pendingStops.get(key));
140
+ const outcome = await stopOutcome(typeof request === 'function' ? request : defaultRequest, stopPath(sessionId, task.id));
141
+ // A render may already have dropped the row (the task left the set): keep whatever that render wrote.
142
+ if (!pendingStops.has(key)) return outcome;
143
+ pendingStops.set(key, { code: outcome.ok ? '' : outcome.code, at: nowMs() });
144
+ showStopState(status, button, pendingStops.get(key));
145
+ return outcome;
146
+ }
147
+
148
+ // One declared task line: type, label, age (+ quiet). A shell line of a known session also carries the
149
+ // operator Stop button and its status text. Shared by the hover card and the phone sheet.
150
+ function taskLine(doc, task, sessionId, fmt, request) {
151
+ const line = doc.createElement('div');
152
+ line.style.cssText = 'display:flex;gap:6px;margin-top:3px;font-size:12px;line-height:1.35;';
153
+ const type = doc.createElement('span');
154
+ type.style.cssText = 'flex:0 0 auto;color:var(--fg-dim,#727aa1);';
155
+ type.textContent = String(task.type || 'task');
156
+ const label = doc.createElement('span');
157
+ label.dataset.tooltipBackgroundLabel = '1';
158
+ label.style.cssText = 'flex:1;min-width:0;overflow-wrap:anywhere;color:var(--fg,#e0e0e0);';
159
+ label.textContent = fmt.cap(task.label, LABEL_MAX);
160
+ const age = doc.createElement('span');
161
+ age.style.cssText = 'flex:0 0 auto;color:var(--fg-dim,#727aa1);font-size:11px;';
162
+ age.textContent = fmt.age(task.since);
163
+ line.append(type, label, age);
164
+ if (task.quiet === true) {
165
+ const quiet = doc.createElement('span');
166
+ quiet.style.cssText = 'flex:0 0 auto;color:var(--fg-dim,#727aa1);';
167
+ quiet.textContent = 'quiet ' + fmt.age(task.activeAt); // fmt.age takes a timestamp (stream-view _tooltipAge)
168
+ line.appendChild(quiet);
169
+ }
170
+ if (!sessionId || String(task.type || '') !== 'shell') return line;
171
+ const status = doc.createElement('span');
172
+ status.dataset.tooltipBackgroundStatus = '1';
173
+ status.style.cssText = 'flex:0 0 auto;color:var(--fg-dim,#727aa1);';
174
+ const stop = doc.createElement('button');
175
+ stop.type = 'button';
176
+ stop.dataset.tooltipBackgroundStop = '1';
177
+ stop.textContent = 'Stop';
178
+ stop.style.cssText = 'flex:0 0 auto;padding:1px 7px;border:1px solid var(--border,#3a4159);border-radius:6px;background:transparent;color:var(--fg,#e0e0e0);font-size:11px;line-height:1.2;cursor:pointer;';
179
+ stop.addEventListener('click', (ev) => stopTask(status, stop, sessionId, task, fmt, request, ev));
180
+ line.append(stop, status);
181
+ const entry = readPending(pendingKey(sessionId, task.id));
182
+ if (entry) showStopState(status, stop, entry);
183
+ return line;
184
+ }
185
+
186
+ // Hover-card body: one row per task (type, label, age) and — with fmt.sessionId — a Stop control on shell
187
+ // rows. fmt.cap(text, n) and fmt.age(ms) are the card's own formatters. Returns null when nothing is listed.
50
188
  function tooltipBody(doc, work, fmt) {
51
189
  const tasks = tasksOf(work);
190
+ const sessionId = typeof fmt?.sessionId === 'string' ? fmt.sessionId : '';
191
+ if (sessionId) prunePending(sessionId, tasks);
52
192
  if (!tasks.length) return null;
53
193
  const body = doc.createElement('div');
54
- for (const task of tasks) {
55
- const line = doc.createElement('div');
56
- line.style.cssText = 'display:flex;gap:6px;margin-top:3px;font-size:12px;line-height:1.35;';
57
- const type = doc.createElement('span');
58
- type.style.cssText = 'flex:0 0 auto;color:var(--fg-dim,#727aa1);';
59
- type.textContent = String(task.type || 'task');
60
- const label = doc.createElement('span');
61
- label.dataset.tooltipBackgroundLabel = '1';
62
- label.style.cssText = 'flex:1;min-width:0;overflow-wrap:anywhere;color:var(--fg,#e0e0e0);';
63
- label.textContent = fmt.cap(task.label, LABEL_MAX);
64
- const age = doc.createElement('span');
65
- age.style.cssText = 'flex:0 0 auto;color:var(--fg-dim,#727aa1);font-size:11px;';
66
- age.textContent = fmt.age(task.since);
67
- line.append(type, label, age);
68
- if (task.quiet === true) {
69
- const quiet = doc.createElement('span');
70
- quiet.style.cssText = 'flex:0 0 auto;color:var(--fg-dim,#727aa1);';
71
- quiet.textContent = 'quiet ' + fmt.age(task.activeAt); // fmt.age takes a timestamp (stream-view _tooltipAge)
72
- line.appendChild(quiet);
73
- }
74
- body.appendChild(line);
75
- }
194
+ for (const task of tasks) body.appendChild(taskLine(doc, task, sessionId, fmt, fmt.request));
76
195
  return body;
77
196
  }
78
197
 
@@ -94,6 +213,52 @@
94
213
  }
95
214
  }
96
215
 
216
+ // Phone: the bottom sheet listing the declared tasks of the card the detail view shows, with the same
217
+ // per-task line + Stop control as the hover card. Every write is textContent and every request goes
218
+ // through the injected `request` (the phone's own private api()), never global fetch.
219
+ function openStopSheet(doc, card, tasks, opts) {
220
+ const sessionId = String((card && (card.id || card.sessionId)) || '');
221
+ const fmt = { cap: clip, age: (since) => ageText(since, nowMs()), confirm: opts.confirm, request: opts.request, sessionId };
222
+ const old = typeof doc.querySelector === 'function' ? doc.querySelector('[data-background-stop-sheet]') : null;
223
+ if (old && typeof old.remove === 'function') old.remove();
224
+ const overlay = doc.createElement('div');
225
+ overlay.dataset.backgroundStopSheet = '1';
226
+ overlay.style.cssText = 'position:fixed;inset:0;z-index:60;display:flex;align-items:flex-end;background:rgba(0,0,0,0.55);';
227
+ const panel = doc.createElement('div');
228
+ panel.style.cssText = 'flex:1;max-height:70vh;overflow:auto;background:var(--bg,#161a24);color:var(--fg,#e0e0e0);padding:12px 14px calc(14px + env(safe-area-inset-bottom));border-radius:14px 14px 0 0;';
229
+ const title = doc.createElement('div');
230
+ title.style.cssText = 'font-size:12px;font-weight:600;color:var(--fg-dim,#727aa1);margin-bottom:6px;';
231
+ title.textContent = 'Background work';
232
+ panel.appendChild(title);
233
+ for (const task of tasks) panel.appendChild(taskLine(doc, task, sessionId, fmt, opts.request));
234
+ const close = doc.createElement('button');
235
+ close.type = 'button';
236
+ close.textContent = 'Close';
237
+ close.style.cssText = 'display:block;width:100%;margin-top:12px;padding:9px;border:1px solid var(--border,#3a4159);border-radius:10px;background:transparent;color:var(--fg,#e0e0e0);font-size:13px;';
238
+ close.addEventListener('click', () => { if (typeof overlay.remove === 'function') overlay.remove(); });
239
+ panel.appendChild(close);
240
+ overlay.appendChild(panel);
241
+ (doc.body || doc.documentElement).appendChild(overlay);
242
+ return overlay;
243
+ }
244
+
245
+ // One delegated tap on #detail-status: only a card whose declared work holds a shell task opens the
246
+ // sheet; any other tap does nothing.
247
+ function installPhoneStop(opts = {}) {
248
+ const doc = opts.document || (GLOBAL && GLOBAL.document) || null;
249
+ if (!doc || typeof doc.addEventListener !== 'function') return null;
250
+ const handler = (ev) => {
251
+ const target = ev && ev.target;
252
+ if (!target || typeof target.closest !== 'function' || !target.closest('#detail-status')) return null;
253
+ const card = typeof opts.currentCard === 'function' ? opts.currentCard() : null;
254
+ const tasks = tasksOf(card && card.backgroundWork);
255
+ if (!tasks.some((t) => t && t.type === 'shell')) return null;
256
+ return openStopSheet(doc, card, tasks, opts);
257
+ };
258
+ doc.addEventListener('click', handler);
259
+ return handler;
260
+ }
261
+
97
262
  // Phone: the verdict chip text for a Running card declared by background work (else the verdict's own label).
98
263
  function chipText(card, rendered) {
99
264
  const reason = String((card && (card.bgReason || card.statusReason)) || '');
@@ -105,5 +270,9 @@
105
270
  return details.backgroundWork === undefined ? {} : { backgroundWork: details.backgroundWork || null, bgReason: String(details.statusReason || '') };
106
271
  }
107
272
 
108
- return { pillText, titleLines, tooltipBody, syncTooltip, chipText, cardPatch, LABEL_MAX };
273
+ return {
274
+ pillText, titleLines, tooltipBody, syncTooltip, chipText, cardPatch, LABEL_MAX,
275
+ // §6.4 operator stop (client half).
276
+ taskLine, stopPath, installPhoneStop, setClock, STOP_PENDING_MS,
277
+ };
109
278
  });
@@ -322,16 +322,24 @@
322
322
  // OWN properties win over the desktop `meta.*` representation, resolved PER FIELD, so an omitted
323
323
  // event/health can never borrow a conflicting value from another representation.
324
324
  const OWNER_CORE_KEYS = ['ctmSessionId', 'agentType', 'providerSessionId', 'processGeneration'];
325
- const OWNER_AGENT_TYPES = ['claude', 'codex', 'gemini', 'opencode'];
325
+ const OWNER_AGENT_TYPES = ['claude', 'codex', 'gemini', 'opencode', 'dsh'];
326
326
  const AUTHORITY_KEYS = ['model_owner', 'model_observation_health', 'model_switch_event'];
327
327
  const HEALTH_STATUSES = ['current', 'restored', 'partial', 'unavailable'];
328
328
  const HEALTH_REASONS = ['restored', 'owner_unavailable', 'scan_partial', 'no_model_evidence',
329
- 'provider_read_failed', 'model_store_unavailable', 'invalid_observation', 'queue_full'];
329
+ 'provider_read_failed', 'model_store_unavailable', 'invalid_observation', 'queue_full',
330
+ // WP-3 (§8 WP-3, §9 S-12b): a live, never-prompted OpenCode tab. The reason must be in this
331
+ // closed vocabulary or `normalizeHealth` rejects the receipt as an invalid observation.
332
+ 'opencode_presession',
333
+ // WP-8 step 4 (§9b M-14): the same state for a DeepSeek Harness tab — the ACP child is up (or the
334
+ // create is still binding) but no completed turn has confirmed a model yet.
335
+ 'dsh_presession'];
330
336
  const HEALTH_REASON_WORDS = {
331
337
  restored: 'restored from a stored snapshot', owner_unavailable: 'owner unavailable',
332
338
  scan_partial: 'scan partial', no_model_evidence: 'no model evidence',
333
339
  provider_read_failed: 'provider read failed', model_store_unavailable: 'model store unavailable',
334
340
  invalid_observation: 'invalid observation', queue_full: 'collector queue full',
341
+ opencode_presession: 'waiting for the first prompt',
342
+ dsh_presession: 'DeepSeek Harness is starting',
335
343
  };
336
344
  // The phase-appropriate owner of a pending model transition. queued/preparing and their
337
345
  // source-side preparation equivalents still run on the SOURCE owner; relaunching/awaiting_turn and
@@ -504,12 +512,21 @@
504
512
  // tuple on a save -> load round trip (the bounded writer would have nothing to store, and
505
513
  // re-normalizing the stored claim would then read as a mismatch). `owner` is the resolver's own
506
514
  // validated tuple (`ownerTuple` copies), never the caller's object.
515
+ //
516
+ // WP-3 (§8 WP-3, §9 S-12b): `opencode_presession` is the producer saying "there is no owner yet,
517
+ // because OpenCode has not been prompted". It is kept ONLY when neither side names an owner; every
518
+ // other ownerless or mismatched annotation still degrades to `owner_unavailable`, so no claim can be
519
+ // borrowed from another owner.
520
+ const ownerless = !owner && !(declaredHealth && declaredHealth.owner)
521
+ && declaredHealth && (declaredHealth.reason === 'opencode_presession' || declaredHealth.reason === 'dsh_presession');
507
522
  const health = declaredHealth && diagnostic
508
523
  ? { status: declaredHealth.status, reason: declaredHealth.reason, owner: owner || null, lastSuccessRevision: declaredHealth.lastSuccessRevision }
509
524
  : declaredHealth
510
525
  ? (owner && declaredHealth.owner && sameOwner(declaredHealth.owner, owner)
511
526
  ? { status: declaredHealth.status, reason: declaredHealth.reason, owner, lastSuccessRevision: declaredHealth.lastSuccessRevision }
512
- : { status: 'unavailable', reason: 'owner_unavailable', lastSuccessRevision: null })
527
+ : (ownerless
528
+ ? { status: 'unavailable', reason: declaredHealth.reason, lastSuccessRevision: null }
529
+ : { status: 'unavailable', reason: 'owner_unavailable', lastSuccessRevision: null }))
513
530
  : (owner ? missingHealth(owner) : null);
514
531
  return {
515
532
  owner,
@@ -652,6 +669,10 @@
652
669
  lead_default_unsupported: 'Claude Code’s default is its own setting.',
653
670
  lead_switch_in_flight: 'This session is already restarting for a model switch. Wait for it to finish.',
654
671
  lead_switch_relaunched: 'The session already restarted; it confirms on the next turn.',
672
+ // Carried over from the Codex lead-switch work: the two settled-phase refusals that otherwise
673
+ // render as a bare "HTTP 409".
674
+ lead_switch_recovery_in_flight: 'An earlier switch on this session is still being recovered. Wait for it to settle, then pick again.',
675
+ lead_transition_committing: 'A switch on this session is committing right now. Wait for it to settle, then pick again.',
655
676
  invalid_model_id: 'That model id is not valid.',
656
677
  invalid_scope: 'That scope is not valid.',
657
678
  session_not_found: 'This session is no longer open.',
@@ -661,11 +682,26 @@
661
682
  walle: 'Wall-E tabs pick their model in the Wall-E picker.',
662
683
  agent_unknown: 'CTM cannot switch this agent’s model.',
663
684
  no_resume_id: 'This session has not been restored yet, so its model cannot change. Open it first.',
664
- source_launch_environment_unavailable: 'CTM cannot recover this session’s original launch environment (it was restored after a restart), so its model and effort are frozen. Close and reopen the session to switch.',
685
+ };
686
+ // D-6/§9 S-19: an unavailable launch environment names WHY (the server's `cause`, from
687
+ // LAUNCH_ENV_REASONS or 'no_capture'), so the sentence is per cause. An unknown or absent cause
688
+ // falls through to the server's own message and then the generic line — never a restart story
689
+ // (after D-3 a restart is never the cause).
690
+ const LAUNCH_ENV_CAUSE_SENTENCES = {
691
+ legacy_worker_private_env: 'Worker sessions keep their launch environment private; a worker’s model can’t be switched here.',
692
+ legacy_no_receipt: 'This session was launched by an older CTM without a launch receipt. Close and reopen it to switch.',
693
+ credential_keys: 'This session’s launch environment holds a credential CTM won’t carry across a host handoff. Close and reopen it to switch.',
694
+ too_many_entries: 'This session was launched with an environment CTM can’t carry. Close and reopen it to switch.',
695
+ too_many_bytes: 'This session was launched with an environment CTM can’t carry. Close and reopen it to switch.',
696
+ bad_key: 'This session was launched with an environment CTM can’t carry. Close and reopen it to switch.',
697
+ bad_value: 'This session was launched with an environment CTM can’t carry. Close and reopen it to switch.',
698
+ not_object: 'This session was launched with an environment CTM can’t carry. Close and reopen it to switch.',
699
+ no_capture: 'This session was attached outside CTM’s launcher, so its launch environment was never captured.',
665
700
  };
666
701
  function leadErrorMessage(status, body) {
667
702
  const b = body || {};
668
703
  if (b.code === MODEL_ACTION_SNAPSHOT_STALE_CODE) return MODEL_ACTION_SNAPSHOT_STALE_GUIDANCE;
704
+ if (b.code === 'lead_switch_unsupported' && b.reason === 'source_launch_environment_unavailable') return LAUNCH_ENV_CAUSE_SENTENCES[b.cause] || b.message || 'This session cannot switch its lead model.';
669
705
  if (b.code === 'lead_switch_unsupported') return UNSUPPORTED_SENTENCES[b.reason] || b.message || 'This session cannot switch its lead model.';
670
706
  // U-8: the routed refusals carry server facts (a reason / a message), so they are built here.
671
707
  if (b.code === 'lead_route_invalid') return 'That gateway route can’t run this model as your lead right now'
@@ -730,7 +766,18 @@
730
766
  const owner = modelAuthority(authority);
731
767
  if (!owner) return presentLegacyLeadModel(state, request, fallbackModelId);
732
768
  state = state && typeof state === 'object' && !Array.isArray(state) ? state : {};
733
- return presentTypedLeadModel(state, request || null, owner);
769
+ const typed = presentTypedLeadModel(state, request || null, owner);
770
+ // WP-3: a never-prompted OpenCode tab has no owner yet, but CTM launched it with an explicit
771
+ // `--model` (the session's own model id). That launch model is SELECTED, not confirmed: it is
772
+ // verified by the first prompt's opencode:message observation, exactly like a pending switch.
773
+ // WP-8 step 4 (§9b M-14): a dsh tab is the same shape — the ACP child was created on a routed model
774
+ // (the session's own model id) and the first completed turn's `dsh:config-option` binds the owner.
775
+ if (typed.state === 'unknown' && !owner.owner && owner.health
776
+ && (owner.health.reason === 'opencode_presession' || owner.health.reason === 'dsh_presession')) {
777
+ const launchModel = isReservedModelAlias(fallbackModelId) ? null : optionalString(fallbackModelId);
778
+ if (launchModel) return { ...typed, modelId: launchModel, state: 'selected-awaiting-turn', selectedValue: launchModel, source: 'ctm:launch' };
779
+ }
780
+ return typed;
734
781
  }
735
782
 
736
783
  function nativeModelChipDecoration(presentation, modelState, currentModelId, hasCtmRequest, authority = null) {
@@ -769,6 +816,19 @@
769
816
  };
770
817
  }
771
818
 
819
+ // WP-3 (§8): an OpenCode lead runs the FIXED gateway ref `ctm-lead/lead` (the route rides env +
820
+ // configPatch, R-1), so its OBSERVED model is the ref — never the route's model, which is what a
821
+ // routed Claude/Codex lead observes directly. A session's stored `lead_route.model` is the one source
822
+ // that names the route in both cases, so the chip label joins through it whenever the observed id is
823
+ // the gateway ref. Claude/Codex stay byte-identical: their provider/model is never `ctm-lead`.
824
+ function leadRouteDisplayId(session, modelId, providerId) {
825
+ const route = session && session.meta && session.meta.lead_route;
826
+ const id = String(modelId || '');
827
+ if (!route || !route.model) return id;
828
+ const isGatewayRef = String(providerId || '') === 'ctm-lead' || id === 'ctm-lead' || id.indexOf('ctm-lead/') === 0;
829
+ return isGatewayRef ? String(route.model) : id;
830
+ }
831
+
772
832
  function sessionModelChipView(presentation, modelState, currentModelId, hasActiveRequest, context, session) {
773
833
  presentation = presentation || {};
774
834
  // WP-0: the raw session `model_id` is a legacy fallback; the reserved delegate alias is never a
@@ -797,9 +857,10 @@
797
857
  const providerId = view
798
858
  ? (presentation.typed === true ? (view.providerId || null) : (view.providerId || legacyProviderId))
799
859
  : (presentation.providerId || legacyProviderId);
800
- const label = modelId && typeof context.labelFor === 'function' ? context.labelFor(modelId) : '';
860
+ const labelModelId = leadRouteDisplayId(session, modelId, providerId);
861
+ const label = labelModelId && typeof context.labelFor === 'function' ? context.labelFor(labelModelId) : '';
801
862
  const modelText = modelId
802
- ? ((typeof context.glyphFor === 'function' ? context.glyphFor(modelId, providerId) : '') + (label || modelId))
863
+ ? ((typeof context.glyphFor === 'function' ? context.glyphFor(labelModelId, providerId) : '') + (label || labelModelId))
803
864
  : (view && view.unknown || context.modelDetectionStale ? 'Model unavailable' : '(detecting…)');
804
865
  const tokenTitle = typeof context.tokenTitle === 'function' ? context.tokenTitle : function() { return ''; };
805
866
  const modelTitle = typeof context.modelTitle === 'function' ? context.modelTitle : function() { return ''; };
@@ -881,6 +942,46 @@
881
942
  return LAUNCH_EFFORT_RE.test(value) ? value : null;
882
943
  }
883
944
 
945
+ // WP-3 (codex-native-subagent-pick-enforcement-2026-10-28.html §5 D-6, §6, §9 S-8): the PASSIVE
946
+ // lead-row chip, shared by the desktop row and the phone card. Like `launchEffortOf` it is a pure,
947
+ // host-free rule defined once at module scope and returned by BOTH the factory and the module
948
+ // surface, so a client can render it without constructing a presenter (the desktop and the phone
949
+ // both load this file, neither may require() it). It is a LABEL only: no click handler, no new WS
950
+ // message, and it never states what a child ran.
951
+ //
952
+ // The rule reads the fact the LAUNCH recorded (`subagent_pick.native_subagents`, WP-1's v58
953
+ // projection) and never re-derives it from today's rule: only the exact `'disabled'` value yields a
954
+ // chip. `''` is a KNOWN "not denied", `null`/absent is unknown (a pre-v58 row), and a malformed
955
+ // value never claims a deny. Callers gate it to Codex rows; a Claude launch never carries the fact.
956
+ function nativeSubagentChip(subagentPick) {
957
+ if (!subagentPick || typeof subagentPick !== 'object' || Array.isArray(subagentPick)) return null;
958
+ if (subagentPick.native_subagents !== 'disabled') return null;
959
+ return {
960
+ text: 'native sub-agents off',
961
+ title: 'The saved delegate pick is a routed worker; this launch refuses spawn_agent. /delegate runs the pick. '
962
+ + 'To use native sub-agents, pick a native model and relaunch.',
963
+ };
964
+ }
965
+
966
+ // The desktop lead row's DOM half, kept here so the one-line call in index.html adds no lines to the
967
+ // hard-ceilinged page: a Codex row gets a sibling span after the model chip when the recorded launch
968
+ // fact says native sub-agents were refused, and the span is removed again once the rule yields null.
969
+ function syncNativeSubagentChip(chip, session, agent) {
970
+ if (!chip || !chip.parentElement) return null;
971
+ var host = chip.parentElement;
972
+ var node = host.querySelector('.model-chip-native-off');
973
+ var view = agent === 'codex' ? nativeSubagentChip(session && session.meta && session.meta.subagent_pick) : null;
974
+ if (!view) { if (node) node.remove(); return null; }
975
+ if (!node) {
976
+ node = document.createElement('span');
977
+ node.className = 'model-chip model-chip-native-off';
978
+ host.insertBefore(node, chip.nextSibling);
979
+ }
980
+ node.textContent = view.text;
981
+ node.title = view.title;
982
+ return node;
983
+ }
984
+
884
985
  // WP-5 (§8 AC-0/AC-2/AC-2b/AC-4/AC-5/AC-6b): every sentence about what /delegate RESOLVES and
885
986
  // what this session's native subagents were CONFIGURED with is a pure rule here, shared by the
886
987
  // desktop chip and the phone sheet (both load this file). The picker supplies its own words and
@@ -907,7 +1008,16 @@
907
1008
 
908
1009
  // AC-3/AC-6b: this refusal is about THIS transport and only about native subagents. It is not an
909
1010
  // account or login claim, and it never promises that the saved selection already ran.
910
- function subagentReasonSentence(reason) {
1011
+ //
1012
+ // WP-2 (§5 D-4, §6, §8 AC-2a): `launch` is the launch-time projection the caller already holds
1013
+ // (`session.meta.subagent_pick`). When that launch RECORDED the deny (`native_subagents ===
1014
+ // 'disabled'`) the sentence states what this process did about native sub-agents and the remedy;
1015
+ // every other value — `''` (a known "not denied"), `null`/absent (a pre-v58 row, which must never
1016
+ // be described as denied), or malformed — keeps today's reason-keyed sentences unchanged.
1017
+ function subagentReasonSentence(reason, launch) {
1018
+ if (launch && launch.native_subagents === 'disabled') {
1019
+ return 'native sub-agents are off for this launch (spawn_agent is refused) because the saved pick is a routed worker — /delegate runs it. To use native sub-agents, pick a native model here and relaunch.';
1020
+ }
911
1021
  var code = String(reason || '');
912
1022
  if (code === 'codex_lead_not_on_proxy') {
913
1023
  return 'this transport can’t redirect native subagents — use /delegate for an external worker; no lead account or model change is required';
@@ -917,6 +1027,16 @@
917
1027
  if (code === 'codex_inherit_unenforceable') {
918
1028
  return 'Codex can’t enforce follow-lead routing for its native subagents — use /delegate for an external worker';
919
1029
  }
1030
+ // subagent-pick-unreachable-origin-2026-10-28 R-6: the route exists; THIS machine can't dial its server.
1031
+ if (code === 'origin_unreachable') {
1032
+ return 'the picked route’s server can’t be reached from this machine — use /delegate with a route this machine can reach';
1033
+ }
1034
+ // WP-4/WP-5 R-10 (docs/opencode-lead-and-delegate-model-selection-2026-10-28.html §5 R-10, §9 S-12):
1035
+ // an OpenCode lead's routed worker is started by the Wall-E MCP server inside the session. Without
1036
+ // it, CTM refuses the launch instead of implying the CLI's own subagents can run a routed model.
1037
+ if (code === 'opencode_routed_requires_mcp') {
1038
+ return 'OpenCode’s built-in subagents can’t run a routed worker model — routed workers need the Wall-E MCP server in this session';
1039
+ }
920
1040
  if (code.indexOf('route_') === 0) return 'the picked route can’t serve this agent (' + code + ')';
921
1041
  return code;
922
1042
  }
@@ -1012,7 +1132,9 @@
1012
1132
  var launchEffort = launchEffortOf(projected);
1013
1133
  var text;
1014
1134
  if (launchKind === 'unservable') {
1015
- text = 'Native subagents: CLI default — ' + subagentReasonSentence(projected && projected.reason);
1135
+ // WP-2: the launch pick itself carries the recorded fact (`native_subagents`), so the sentence
1136
+ // is keyed on what THIS process did rather than on today's rule.
1137
+ text = 'Native subagents: CLI default — ' + subagentReasonSentence(projected && projected.reason, projected);
1016
1138
  } else if (launchKind === 'none') {
1017
1139
  // M-6: a failed Wall-E read with no mirrored row is not the same as "no pick".
1018
1140
  text = (projected && projected.reason === 'read_failed')
@@ -1105,6 +1227,9 @@
1105
1227
 
1106
1228
  return {
1107
1229
  subagentReasonSentence: subagentReasonSentence,
1230
+ // WP-3 (§6): the passive chip rides the factory surface too, so a caller that already holds a
1231
+ // presenter (the phone sheet, the desktop picker) reads both rules from the same object.
1232
+ nativeSubagentChip: nativeSubagentChip,
1108
1233
  subagentLine: subagentLine,
1109
1234
  nativeEffortNote: nativeEffortNote,
1110
1235
  delegateEffortNote: delegateEffortNote,
@@ -1114,7 +1239,10 @@
1114
1239
  };
1115
1240
  }
1116
1241
 
1117
- return { presentLeadModel, presentLeadModelCompat, nativeModelChipDecoration, sessionModelChipView, requestTransitionPresentation, requestToastPresentation, createDelegateRoutePresentation, createDelegationPresentation, launchEffortOf,
1242
+ return { presentLeadModel, presentLeadModelCompat, nativeModelChipDecoration, sessionModelChipView, leadRouteDisplayId, requestTransitionPresentation, requestToastPresentation, createDelegateRoutePresentation, createDelegationPresentation, launchEffortOf,
1243
+ // WP-3: the passive native-subagents-off chip — module-level like `launchEffortOf`, so the desktop
1244
+ // row and the phone card render it straight off the shared surface they both load.
1245
+ nativeSubagentChip, syncNativeSubagentChip,
1118
1246
  // WP-2A: the Lead action's bounded error copy — pure, no private-runtime lookup.
1119
1247
  leadErrorMessage,
1120
1248
  // WP1C: the ONE owner/health/event normalizer and the shared lead status/detail lines.