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
@@ -40,20 +40,28 @@ const CTM_MODEL_SYNC_SIGNATURE_TTL_MS = Number(process.env.CTM_MODEL_SYNC_SIGNAT
40
40
  // WP1B criterion 5: the production read-pool batch. The hard page guard stays MAX_AGENT_MODEL_ITEMS.
41
41
  const MODEL_SYNC_BATCH_ITEMS = 8;
42
42
 
43
- // Walk a JSONL chunk backwards for the two per-session model facts Claude Code records:
43
+ // Walk a JSONL chunk backwards for the per-session model facts Claude Code records:
44
44
  // `identity` (the `attachment.type === 'model'` record written at session start and on `/model` —
45
- // what the session was SET to, verbatim) and `turn` (the latest non-sidechain assistant row's
46
- // `message.model` — what actually SERVED). normalizeClaudeModelId refuses to invent a concrete id
47
- // for a bare alias literal such as "sonnet".
45
+ // what the session was SET to, verbatim), `turn` (the latest non-sidechain assistant row's
46
+ // `message.model` — what actually SERVED), and `failure` (the newest assistant row Claude Code
47
+ // flagged with `isApiErrorMessage`, which is what a REFUSED turn looks like: `message.model` is
48
+ // `<synthetic>` and `apiErrorStatus` carries the provider status when there was one).
49
+ // normalizeClaudeModelId refuses to invent a concrete id for a bare alias literal such as "sonnet".
50
+ //
51
+ // WP-1/D-1: `failure` is recorded ONLY while `turn` is still null in this newest-first walk, so a
52
+ // newer successful turn (which is reached first) clears it -- and a failure found first never stops
53
+ // the scan before the older good turn is found. The refusal row still can never become `turn`:
54
+ // `<synthetic>` keeps failing normalizeClaudeModelId.
48
55
  function _scanJsonlForClaudeModelInfo(raw) {
49
56
  const lines = raw.split('\n');
50
57
  let identity = null;
51
58
  let turn = null;
59
+ let failure = null;
52
60
  for (let i = lines.length - 1; i >= 0; i--) {
53
61
  const line = lines[i];
54
62
  if (!line || line[0] !== '{') continue;
55
63
  // Cheap pre-filter so we don't JSON.parse every user/system line.
56
- if (line.indexOf('"model"') === -1 && line.indexOf('"attachment"') === -1) continue;
64
+ if (line.indexOf('"model"') === -1 && line.indexOf('"attachment"') === -1 && line.indexOf('"isApiErrorMessage"') === -1) continue;
57
65
  try {
58
66
  const rec = JSON.parse(line);
59
67
  if (!rec) continue;
@@ -74,12 +82,17 @@ function _scanJsonlForClaudeModelInfo(raw) {
74
82
  if (norm) {
75
83
  const effort = [rec.effort, rec.perTurnEffort].find((v) => typeof v === 'string' && v.trim());
76
84
  turn = { model: norm.id, context1m: norm.context1m, observedAtMs: atMs, effort: effort ? effort.trim() : null };
85
+ } else if (!failure && rec.isApiErrorMessage === true) {
86
+ failure = {
87
+ status: Number.isSafeInteger(rec.apiErrorStatus) ? rec.apiErrorStatus : null,
88
+ atMs, turnId: rec.uuid ?? null, requestId: rec.requestId ?? null,
89
+ };
77
90
  }
78
91
  }
79
92
  if (identity && turn) break;
80
93
  } catch { /* skip malformed line */ }
81
94
  }
82
- return { identity, turn };
95
+ return { identity, turn, failure };
83
96
  }
84
97
 
85
98
  // Read just the TAIL of the transcript by default: the model lives in the most
@@ -117,9 +130,11 @@ function getClaudeCodeModelInfoFromJsonl(jsonlPath) {
117
130
  // The per-session Claude model truth (shape: claude-model-truth.js truthFromTranscriptFacts),
118
131
  // read ONLY from that session's own transcript. No global file is consulted: a `/model` switch in
119
132
  // one session must never relabel another (claude-model-truth-session-owned D-1).
133
+ // WP-1: the third transcript fact (a refused turn) rides along as `lastTurnFailure`; it feeds the
134
+ // lead-model switch's failure branch and NOTHING that names a model.
120
135
  function getClaudeSessionModelTruth({ jsonlPath } = {}) {
121
136
  const info = getClaudeCodeModelInfoFromJsonl(jsonlPath) || {};
122
- return truthFromTranscriptFacts(info.identity || null, info.turn || null);
137
+ return truthFromTranscriptFacts(info.identity || null, info.turn || null, info.failure || null);
123
138
  }
124
139
 
125
140
  function openCodexStateDb(homeDir = process.env.HOME) {
@@ -194,9 +209,9 @@ function getCodexTurnContextModelFromJsonl(jsonlPath) {
194
209
  // OpenCode persists the model REALLY in use for each session in its own SQLite
195
210
  // store (~/.local/share/opencode/opencode.db, `session.model` as JSON
196
211
  // {id, providerID}), and rewrites it the instant the user switches models inside
197
- // the TUI. CTM only injects an opinionated launch default (`--model zai/glm-5.2`),
212
+ // the TUI. CTM passes `--model` only for an explicit pick (and none otherwise),
198
213
  // so the model chip would otherwise lie whenever the session is actually running a
199
- // different model (e.g. the user picked Kimi). Read the live value back so the chip
214
+ // different model (e.g. the user picked Kimi inside the TUI). Read the live value back so the chip
200
215
  // reflects the truth. Matched by working directory — CTM launches one OpenCode per
201
216
  // (worktree) cwd, and OpenCode records the absolute directory on the session row.
202
217
  function opencodeDataDbPath(homeDir = process.env.HOME, env = process.env) {
@@ -576,7 +591,7 @@ function createCodingAgentModelSync({
576
591
  }
577
592
  }
578
593
  }
579
- if (changed && typeof broadcastSessionList === 'function') broadcastSessionList();
594
+ if (changed && typeof broadcastSessionList === 'function') broadcastSessionList(false, { reason: 'model-sync' });
580
595
  }
581
596
 
582
597
  // Off-main-loop variant of syncCodingSessionModels. The fs/DB-heavy resolution (claude JSONL
@@ -850,7 +865,7 @@ function createCodingAgentModelSync({
850
865
  && (agentType !== 'codex' || entry.titleSynced);
851
866
  if (complete) modelSyncState.cacheCompletedContext(context);
852
867
  }
853
- if (changed && typeof broadcastSessionList === 'function') broadcastSessionList();
868
+ if (changed && typeof broadcastSessionList === 'function') broadcastSessionList(false, { reason: 'model-sync' });
854
869
  },
855
870
  { context: () => ({ results: persistedById.size, sessions: contexts.length }) },
856
871
  );
@@ -893,7 +908,7 @@ function createCodingAgentModelSync({
893
908
  }
894
909
  const fieldsChanged = _applyClaudeTruthFields(session, truth);
895
910
  if (resolvedChanged || fieldsChanged) _persistSessionModel(session, model || (session.model_id ? { model_id: session.model_id, model_provider: session.model_provider } : null)); // I-5: a hook changing only `selected` (opus -> opusplan, same resolved id) must still be written, or the alias/Plan-mode tag is lost on RESTART and the next sync tick sees no diff either
896
- if ((resolvedChanged || fieldsChanged) && typeof broadcastSessionList === 'function') broadcastSessionList();
911
+ if ((resolvedChanged || fieldsChanged) && typeof broadcastSessionList === 'function') broadcastSessionList(false, { reason: 'claude-model-truth' });
897
912
  return { changed: observed.changed || resolvedChanged || fieldsChanged, view: observed.view };
898
913
  }
899
914
 
@@ -6,8 +6,8 @@
6
6
  // wall-e/skills/_templates/<dir>/templates/<agent>/SKILL.md (+ VERSION and
7
7
  // released-sha256.json). _templates/ is a plain template store, never a runnable Wall-E skill
8
8
  // directory (skill-loader.js only enumerates skills/_bundled/). This module copies a template out
9
- // to the CLI's own skills root (<claude config dir>/skills/<name>/, $CODEX_HOME/skills/<name>/)
10
- // with the dpkg conffile rule, adapted to a daemon that cannot prompt:
9
+ // to the CLI's own skills root (<claude config dir>/skills/<name>/, $CODEX_HOME/skills/<name>/,
10
+ // $DSH_HOME/skills/<name>/) with the dpkg conffile rule, adapted to a daemon that cannot prompt:
11
11
  //
12
12
  // * A copy is classified by the sha256 of the bytes on disk, never by version alone (D-3). The
13
13
  // known set is the shipped released manifest (every template text ever released) plus the hash
@@ -53,11 +53,28 @@ const SOURCE = 'ctm-coding-cli-skill-installer';
53
53
 
54
54
  // name -> the _templates/<dir> that holds templates/<agent>/SKILL.md + VERSION + released-sha256.json.
55
55
  // The delegate skill's template dir is named delegate-worker (not "delegate") because it is a
56
- // templates-only store, never itself a runnable/user-invocable skill name.
57
- const MANAGED_SKILLS = Object.freeze({ delegate: 'delegate-worker' });
58
- const MANAGED_AGENTS = Object.freeze(['claude', 'codex']);
56
+ // templates-only store, never itself a runnable/user-invocable skill name. `fleet-sync` (WP-4 of
57
+ // fleet-origin-main-sync-skill-2026-10-31.html §6.6) keeps its own name; every consumer below keys
58
+ // off this map (or `Object.hasOwn(MANAGED_SKILLS, name)`) rather than a single hardcoded skill.
59
+ const MANAGED_SKILLS = Object.freeze({ delegate: 'delegate-worker', 'fleet-sync': 'fleet-sync' });
60
+ // WP-12 (AC-12c): dsh (the DeepSeek Harness) joins the managed installers. Its root is $DSH_HOME/skills
61
+ // (default ~/.dsh/skills) -- design doc deepseek-harness-acp-agent-2026-10-28 C-9/OQ-9.
62
+ const MANAGED_AGENTS = Object.freeze(['claude', 'codex', 'dsh']);
59
63
  const MODES = Object.freeze(['boot', 'install', 'user']);
60
64
 
65
+ // WP-12: the template dir a managed copy is read from is `templates/<TEMPLATE_AGENT[agent] || agent>/`.
66
+ // dsh ships no template of its own yet (wall-e/skills/_templates/<dir>/templates/dsh/), and its skill
67
+ // format IS Claude Code's -- YAML frontmatter + markdown at <name>/SKILL.md, which is exactly what dsh's
68
+ // own skill filesystem reads (C-9/OQ-9) -- so a dsh install carries the claude text. Classification and
69
+ // the released manifest use the same mapping, so a pristine dsh copy is `noop`/`update` and never a
70
+ // permanent `create`. A dsh-specific template is a follow-up: when it lands, drop the entry below.
71
+ const TEMPLATE_AGENT = Object.freeze({ dsh: 'claude' });
72
+
73
+ function templateAgentFor(agent) {
74
+ assertAgent(agent);
75
+ return TEMPLATE_AGENT[agent] || agent;
76
+ }
77
+
61
78
  function templateDirFor(name) {
62
79
  if (typeof name !== 'string' || !Object.hasOwn(MANAGED_SKILLS, name)) {
63
80
  throw new Error(`No bundled template for skill "${name}"`);
@@ -70,12 +87,16 @@ function assertAgent(agent) {
70
87
  }
71
88
 
72
89
  /** D-4. Absolute skills root for the agent. Throws on an unknown agent. The Codex root honours
73
- * CODEX_HOME from the PASSED env (identical to codexHome() when env is process.env). */
90
+ * CODEX_HOME from the PASSED env (identical to codexHome() when env is process.env); the dsh root
91
+ * honours DSH_HOME the same way (WP-12, AC-12c). */
74
92
  function skillsRootFor(agent, { env = process.env, homeDir = os.homedir() } = {}) {
75
93
  assertAgent(agent);
76
94
  if (agent === 'claude') {
77
95
  return path.join(env.CLAUDE_CONFIG_DIR || path.join(homeDir, '.claude'), 'skills');
78
96
  }
97
+ if (agent === 'dsh') {
98
+ return path.join(env.DSH_HOME || path.join(homeDir, '.dsh'), 'skills');
99
+ }
79
100
  const home = env === process.env ? codexHome(homeDir) : (env.CODEX_HOME || path.join(homeDir, '.codex'));
80
101
  return path.join(home, 'skills');
81
102
  }
@@ -152,14 +173,16 @@ async function readBundledVersion(name) {
152
173
  return raw.trim();
153
174
  }
154
175
 
155
- /** The bundled SKILL.md for (name, agent) as raw bytes -- the exact bytes the installer writes. */
176
+ /** The bundled SKILL.md for (name, agent) as raw bytes -- the exact bytes the installer writes. The
177
+ * template dir is TEMPLATE_AGENT[agent] (dsh reads Claude Code's format; see TEMPLATE_AGENT). */
156
178
  async function readTemplateSkillMd(name, agent) {
157
- return fsp.readFile(path.join(templateDirFor(name), 'templates', agent, 'SKILL.md'));
179
+ return fsp.readFile(path.join(templateDirFor(name), 'templates', templateAgentFor(agent), 'SKILL.md'));
158
180
  }
159
181
 
160
- /** The shipped released manifest {schema, claude:{sha:version}, codex:{...}}. A missing or
161
- * malformed manifest throws: classifying without it would call every field copy `edited`. */
162
- async function readReleasedManifest(name = 'delegate') {
182
+ /** The shipped released manifest {schema, claude:{sha:version}, codex:{...}} for one managed skill
183
+ * (its name is required, exactly like readBundledVersion). A missing or malformed manifest throws:
184
+ * classifying without it would call every field copy `edited`. */
185
+ async function readReleasedManifest(name) {
163
186
  const raw = await fsp.readFile(path.join(templateDirFor(name), 'released-sha256.json'), 'utf8');
164
187
  const parsed = JSON.parse(raw);
165
188
  if (!parsed || typeof parsed !== 'object') throw new Error('released-sha256.json is not an object');
@@ -241,7 +264,9 @@ async function buildPlan(agent, name, root, { isPrimary, realHome, log }) {
241
264
  ? rootRecord.skills[name] : null;
242
265
 
243
266
  // D-3: known set = released manifest (agent) U marker's own hash (schema 2) U the bundled text.
244
- const known = new Map(Object.entries(mapOf(manifest[agent])));
267
+ // The manifest is keyed by the TEMPLATE agent, so a dsh copy of the claude text classifies the same
268
+ // way a claude copy does (TEMPLATE_AGENT).
269
+ const known = new Map(Object.entries(mapOf(manifest[templateAgentFor(agent)])));
245
270
  if (marker && marker.schema === 2) {
246
271
  // The marker is written BEFORE SKILL.md (D-6), so after a crash between the two the bytes on
247
272
  // disk are the text the marker replaced: previousSha256 keeps that old text pristine even when
@@ -441,6 +466,11 @@ module.exports = {
441
466
  planSkillInstall,
442
467
  applySkillInstall,
443
468
  syncManagedSkills,
444
- // Exported for tests / diagnostics.
445
- _internals: { compareVersions, sha256, readReleasedManifest, readMarker, readRootRecord, readBundledVersion, MARKER_FILE, ROOT_RECORD_FILE },
469
+ // Exported for tests / diagnostics, and for the other installer that shares this rule set:
470
+ // lib/agent-bundle/codex-install.js (D-14 Codex install-mode) reuses MARKER_FILE/ROOT_RECORD_FILE,
471
+ // readMarker, readRootRecord and writeRootRecord instead of growing a second copy of them.
472
+ _internals: {
473
+ compareVersions, sha256, readReleasedManifest, readMarker, readRootRecord, writeRootRecord,
474
+ readBundledVersion, templateAgentFor, MARKER_FILE, ROOT_RECORD_FILE,
475
+ },
446
476
  };
@@ -118,6 +118,19 @@ function claudeTurnCandidate(owner, rec, index) {
118
118
  effort: rec.effort ?? rec.perTurnEffort ?? null, turnId: rec.uuid ?? null, source: 'transcript:turn' };
119
119
  }
120
120
 
121
+ /*
122
+ * WP-1/D-1: the newest assistant row Claude Code flagged with `isApiErrorMessage` -- what a REFUSED
123
+ * turn looks like (`message.model` is `<synthetic>`, so `claudeTurnCandidate` can never see it).
124
+ * The record predicate is the tail scan's (lib/coding-agent-models.js), plus the same root/owner
125
+ * filters every other Claude candidate applies. It carries NO model: `value` is empty by design.
126
+ */
127
+ function claudeTurnFailureCandidate(owner, rec, index) {
128
+ if (!ownerOk(owner) || !validRecord(rec) || !claudeRootRecord(rec, owner)) return null;
129
+ if (rec.type !== 'assistant' || rec.isApiErrorMessage !== true) return null;
130
+ return { at: time(rec.timestamp), index, status: Number.isSafeInteger(rec.apiErrorStatus) ? rec.apiErrorStatus : null,
131
+ turnId: rec.uuid ?? null, requestId: rec.requestId ?? null, source: 'transcript:turn' };
132
+ }
133
+
121
134
  function claudeIdentityObservations(owner, candidate) {
122
135
  const out = [];
123
136
  if (!candidate) return out;
@@ -137,16 +150,40 @@ function claudeTurnObservations(owner, candidate) {
137
150
  return out;
138
151
  }
139
152
 
153
+ /*
154
+ * WP-1/D-1: a REFUSED turn, as a typed observation. `value` is the empty string on purpose -- there is
155
+ * no model to name -- so this cannot go through `observation()`, whose value bound is required. Every
156
+ * owner field is the same one every other observation carries; the status is the provider's own.
157
+ * lib/coding-session-model-state.js refuses the unknown kind, so this can never become model evidence.
158
+ */
159
+ function claudeTurnFailureObservations(owner, candidate) {
160
+ const out = [];
161
+ if (!candidate || !ownerOk(owner)) return out;
162
+ out.push({
163
+ ctmSessionId: owner.ctmSessionId, agentType: owner.agentType, providerSessionId: owner.providerSessionId,
164
+ processGeneration: owner.processGeneration, kind: 'failed-turn', value: '', providerId: null,
165
+ selectionKind: null, effort: null, source: 'transcript:turn', observedAtMs: candidate.at,
166
+ sourceRevision: candidate.turnId == null ? null : String(candidate.turnId),
167
+ outcome: 'failed', apiErrorStatus: candidate.status,
168
+ });
169
+ return out;
170
+ }
171
+
140
172
  function claudeModelObservations(owner, records) {
141
173
  const out = []; if (!ownerOk(owner) || !Array.isArray(records)) return out;
142
- let identity = null; let turn = null;
174
+ let identity = null; let turn = null; let failure = null;
143
175
  records.forEach((rec, index) => {
144
176
  const identityCandidate = claudeIdentityCandidate(owner, rec, index);
145
177
  if (later(identity, identityCandidate)) identity = identityCandidate;
146
178
  const turnCandidate = claudeTurnCandidate(owner, rec, index);
147
179
  if (later(turn, turnCandidate)) turn = turnCandidate;
180
+ const failureCandidate = claudeTurnFailureCandidate(owner, rec, index);
181
+ if (later(failure, failureCandidate)) failure = failureCandidate;
148
182
  });
149
183
  out.push(...claudeIdentityObservations(owner, identity), ...claudeTurnObservations(owner, turn));
184
+ // Only a refusal NEWER than the newest successful turn (timestamp, then index) is still open: the
185
+ // completed-turn observation above keeps its own, unchanged meaning.
186
+ if (later(turn, failure)) out.push(...claudeTurnFailureObservations(owner, failure));
150
187
  return out;
151
188
  }
152
189
 
@@ -292,8 +329,11 @@ function opencodeModelObservations(owner, { sessionRow, assistantRows } = {}) {
292
329
  const sessionId = sessionModel ? bounded(sessionModel.id ?? sessionModel.modelID, true) : (encodedModel ? null : bounded(sessionRow.model, true));
293
330
  const sessionProvider = sessionModel?.providerID == null ? null : bounded(sessionModel.providerID, true);
294
331
  if (sessionId && (typeof sessionRow.model === 'string' || sessionModel)) {
332
+ // OpenCode 1.x writes `session.model` once, at creation, and bumps `time_updated` after every turn
333
+ // (observed on 1.19.5: a turn on m2/m3 leaves it m1, updated ~2 ms after the turn completed). Stamped
334
+ // with `time_updated`, this fact outranked every completed turn; it is as old as the session row.
295
335
  for (const kind of ['selection', 'resolved']) emit(out, [owner, kind, sessionId, sessionProvider, 'concrete', null,
296
- 'opencode:session-store', time(sessionRow.time_updated), null]);
336
+ 'opencode:session-store', time(sessionRow.time_created ?? sessionRow.time_updated), null]);
297
337
  }
298
338
  let best = null;
299
339
  assistantRows.forEach((row, index) => {
@@ -319,6 +359,7 @@ module.exports = { claudeModelObservations, claudeHookModelObservations, codexMo
319
359
  // byte-identical to the one a whole-tail read would have produced.
320
360
  laterRank: later, isCodexRelatedRecord, codexThreadMatches,
321
361
  claudeIdentityCandidate, claudeTurnCandidate, claudeIdentityObservations, claudeTurnObservations,
362
+ claudeTurnFailureCandidate, claudeTurnFailureObservations,
322
363
  codexSettingsCandidate, codexSettingsObservations, codexTurnContextCandidate, codexTerminalCandidate,
323
364
  codexTurnObservations,
324
365
  // WP-0: the one shared "is this the reserved delegate alias?" predicate (see the doc comment above).
@@ -6,7 +6,7 @@
6
6
  // See docs/model-sync-owner-wire-contract-2026-10-15.html §6.1 (D-1..D-4).
7
7
  const OWNER_CORE_KEYS = Object.freeze(['ctmSessionId', 'agentType', 'providerSessionId', 'processGeneration']);
8
8
  const OWNER_ROUTE_KEYS = Object.freeze(['profileFingerprint', 'factsRevision', 'routeId']);
9
- const OWNER_AGENT_TYPES = Object.freeze(['claude', 'codex', 'gemini', 'opencode']);
9
+ const OWNER_AGENT_TYPES = Object.freeze(['claude', 'codex', 'gemini', 'opencode', 'dsh']);
10
10
  const OWNER_TEXT_CAP_BYTES = 256; // same cap as read-pool-model-collector safeText
11
11
 
12
12
  // Trimmed, non-empty string of ≤256 UTF-8 bytes, else null — the collector's safeText(value, 256) rule.
@@ -41,6 +41,12 @@ const HEALTH_STATUSES = Object.freeze(['current', 'restored', 'partial', 'unavai
41
41
  const HEALTH_REASONS = Object.freeze([
42
42
  'restored', 'owner_unavailable', 'scan_partial', 'no_model_evidence',
43
43
  'provider_read_failed', 'model_store_unavailable', 'invalid_observation', 'queue_full',
44
+ // WP-3 (§8/§9 S-12b): a LIVE OpenCode tab that has not been prompted yet — the publisher emits this
45
+ // instead of `owner_unavailable`; the shared presenter words it "waiting for the first prompt".
46
+ 'opencode_presession',
47
+ // WP-8 (§9b M-8): the same word for a live DeepSeek Harness session whose ACP owner row is not
48
+ // bound yet (the child is up, the config options have not landed).
49
+ 'dsh_presession',
44
50
  ]);
45
51
  const PUBLIC_EVENT_KEYS = Object.freeze([...EVENT_KEYS, 'id']);
46
52
  // The created-frame whitelist (server → client `created`), in the order §6 fixes it.
@@ -266,7 +272,7 @@ function buildCreatedSessionPayload({
266
272
 
267
273
  // The native CLI agents whose sessions have a LIVE-OWNER authority envelope. A durable startup-task
268
274
  // placeholder for one of these has no live owner yet, which is stated explicitly.
269
- const NATIVE_AGENT_TYPES = new Set(['claude', 'codex', 'gemini', 'opencode']);
275
+ const NATIVE_AGENT_TYPES = new Set(['claude', 'codex', 'gemini', 'opencode', 'dsh']);
270
276
 
271
277
  /*
272
278
  * WP1C transport correction (c): resolve the ACTUAL CLI identity with the existing detector, applied to
@@ -37,7 +37,7 @@ const MODEL_PROVIDER_ENV_KEYS = Object.freeze(['HOME', 'CODEX_HOME', 'CTM_CODEX_
37
37
  const MODEL_SWITCH_EVENT_KEY = 'model_switch_event';
38
38
  // WP1C: the agent types whose sessions have a native CLI owner. Every other session (a shell, native
39
39
  // Wall-E chat) has no native owner at all and therefore publishes NO authority envelope.
40
- const NATIVE_AGENT_TYPES = new Set(['claude', 'codex', 'gemini', 'opencode']);
40
+ const NATIVE_AGENT_TYPES = new Set(['claude', 'codex', 'gemini', 'opencode', 'dsh']); // WP-8 §9b M-5: 'dsh' has a native owner (bound from ACP config options at session start; no PTY, no argv model)
41
41
 
42
42
  function modelProviderEnv(session) { const source = session?._launchEnvOverrides; const result = {}; for (const key of MODEL_PROVIDER_ENV_KEYS) if (typeof source?.[key] === 'string') result[key] = source[key]; return result; }
43
43
 
@@ -225,6 +225,21 @@ function createCodingSessionModelRuntime({
225
225
  return agentType && NATIVE_AGENT_TYPES.has(agentType) ? agentType : null;
226
226
  }
227
227
 
228
+ /*
229
+ * WP-3 (design docs/opencode-lead-and-delegate-model-selection-2026-10-28.html §8 WP-3, §9 S-12b):
230
+ * a LIVE OpenCode 1.x tab that has not received its first prompt genuinely has no model owner —
231
+ * OpenCode creates its provider session (and therefore CTM's owner tuple) only on the first prompt.
232
+ * `owner_unavailable` is true there but unhelpful, so this distinct reason says what is actually
233
+ * happening. The scope is deliberately narrow: an OpenCode tab with a RUNNING process (a
234
+ * `ptyProcess` that is not a parked/`_restoreDeferred` placeholder). A parked OpenCode tab, an
235
+ * OpenCode tab with no process, every other native agent and the known-owner-without-a-health-record
236
+ * case all keep the established `owner_unavailable`. WP-8 §9b M-6: a LIVE dsh (DeepSeek Harness) session — a childless ACP child (`_acpProcess`, never a `ptyProcess`) — reports `dsh_presession` too.
237
+ */
238
+ function nullOwnerHealthReason(session, agentType) {
239
+ const live = !!session?.ptyProcess && session._restoreDeferred !== true, acp = !!session?._acpProcess && session._restoreDeferred !== true;
240
+ return agentType === 'dsh' ? (acp ? 'dsh_presession' : 'owner_unavailable') : agentType === 'opencode' && live ? 'opencode_presession' : 'owner_unavailable';
241
+ }
242
+
228
243
  // The CANONICAL owner, and the only live owner source: never a stored generation, a launch-plan
229
244
  // counter, a linked transcript list or a caller-supplied field.
230
245
  function canonicalOwnerOf(session) {
@@ -264,9 +279,12 @@ function createCodingSessionModelRuntime({
264
279
  function publicFields(session) {
265
280
  // A shell or native Wall-E chat session has NO native owner: it publishes no envelope at all, so
266
281
  // nothing downstream can mistake an explicit null owner for a native one.
267
- if (!nativeAgentFor(session)) return null;
282
+ const agentType = nativeAgentFor(session);
283
+ if (!agentType) return null;
268
284
  const owner = canonicalOwnerOf(session);
269
- if (!owner) return publicModelFields({ owner: null, health: { status: 'unavailable', reason: 'owner_unavailable', owner: null, lastSuccessRevision: null } });
285
+ // WP-3: a LIVE never-prompted OpenCode tab is the ONE null-owner case with its own reason; every
286
+ // other null-owner case keeps `owner_unavailable`.
287
+ if (!owner) return publicModelFields({ owner: null, health: { status: 'unavailable', reason: nullOwnerHealthReason(session, agentType), owner: null, lastSuccessRevision: null } });
270
288
  const entry = observationHealth.get(session) || null;
271
289
  const live = entry && sameOwner(entry.owner, owner) ? entry : null;
272
290
  const health = live
@@ -908,6 +926,7 @@ function createCodingSessionModelRuntime({
908
926
  committed = bound.changed === true;
909
927
  let revision = Number.isSafeInteger(bound.revision) ? bound.revision : finalState.revision;
910
928
  for (const observation of Array.isArray(result.observations) ? result.observations : []) {
929
+ if (observation?.kind === 'failed-turn') continue; // refused-turn evidence for the lead-model observer only, never model state
911
930
  if (!sameOwner(observation, owner)) { deferredReason = 'owner'; scanAborted = true; break; }
912
931
  if (!isCurrent(session, owner)) { deferredReason = 'superseded'; scanAborted = true; break; }
913
932
  // Correction 3: revalidate the captured switch lifetime immediately before EVERY owner
@@ -1490,7 +1509,7 @@ function createDurableModelResultApplier({ modelStateRuntime, isCurrent, isOwner
1490
1509
  if (entry.titleApplied && entry.title && entry.titleKind !== 'live') { const label = `Codex: ${entry.title}`; if (context.session.label !== label) { context.session.label = label; titleChanged = true; } }
1491
1510
  if (entry.titleSynced) cacheCompleted(context);
1492
1511
  }
1493
- if (titleChanged && typeof broadcastSessionList === 'function') broadcastSessionList();
1512
+ if (titleChanged && typeof broadcastSessionList === 'function') broadcastSessionList(false, { reason: 'model-title-apply' });
1494
1513
  return { rerun: false };
1495
1514
  };
1496
1515
  }
@@ -35,6 +35,7 @@ const transcriptSource = require('./transcript-source');
35
35
  const {
36
36
  laterRank,
37
37
  claudeIdentityCandidate, claudeTurnCandidate, claudeIdentityObservations, claudeTurnObservations,
38
+ claudeTurnFailureCandidate, claudeTurnFailureObservations,
38
39
  codexSettingsCandidate, codexSettingsObservations, codexTurnContextCandidate, codexTerminalCandidate,
39
40
  codexTurnObservations,
40
41
  } = require('./coding-session-model-adapters');
@@ -339,6 +340,13 @@ function runScan(run) {
339
340
  ops: run.ops, fd, readOptions: run.readOptions, stat,
340
341
  dev, ino, size, mtimeMs, headAnchor: null, nextRevision: prior ? prior.revision + 1 : 1,
341
342
  selection: null, completed: null, latestContext: null, latestContextPayload: null, turnContext: null,
343
+ /*
344
+ * WP-1b/D-1: `failure`/`failureRank` are the refused-turn slot's own pair. They mirror `completed`
345
+ * EXCEPT that no checkpoint carries them: a failure is emitted only for a candidate FOUND this
346
+ * tick, and it is compared against `completedRank` (this tick's winner or the acknowledged one) to
347
+ * decide whether it is still open.
348
+ */
349
+ failure: null, failureRank: null,
342
350
  sawContext: false, reachedBof: false, backfill: false, records: 0, iterations: 0, gapReason: null, eof: null,
343
351
  windowEvaluated: false, windowStart: 0, archiveRefused: false,
344
352
  edgeAt: baseEnd, edgeAnchor: null };
@@ -892,6 +900,17 @@ function reduceRecord(state, lane, record, start, end) {
892
900
  const candidate = { ...turn, start, end };
893
901
  if (laterRank(state.completedRank, candidate)) { state.completed = candidate; state.completedRank = candidate; }
894
902
  }
903
+ /*
904
+ * WP-1b/D-1: a REFUSED turn (assistant row with `isApiErrorMessage`, whose `<synthetic>` model
905
+ * `claudeTurnCandidate` can never name) keeps its OWN newest-wins slot, ranked by the SAME
906
+ * (timestamp, offset) order. It is emitted only while it is NEWER than `state.completedRank` -- see
907
+ * the emitter -- so a good turn after it wins and an acknowledged good turn still suppresses it.
908
+ */
909
+ const failure = claudeTurnFailureCandidate(owner, record, start);
910
+ if (failure) {
911
+ const candidate = { ...failure, start, end };
912
+ if (laterRank(state.failureRank, candidate)) { state.failure = candidate; state.failureRank = candidate; }
913
+ }
895
914
  return;
896
915
  }
897
916
  const terminal = codexTerminalCandidate(record);
@@ -1149,6 +1168,18 @@ function checkpointResult(state, lanes, inherited, blocked) {
1149
1168
  if (state.agentType === 'claude') {
1150
1169
  observations.push(...claudeIdentityObservations(state.owner, state.selection),
1151
1170
  ...claudeTurnObservations(state.owner, state.completed));
1171
+ /*
1172
+ * WP-1b/D-1: the refused-turn fact, under the rule the G2-5/G2-9 comment above states: `state.failure`
1173
+ * is a CANDIDATE FOUND THIS TICK, so a tick that read no new bytes emits nothing and no observation is
1174
+ * ever synthesized from a checkpoint ref (`state.failure` is deliberately not persisted). It is open
1175
+ * only while it ranks LATER than `state.completedRank`, which is the newest completed turn of THIS tick
1176
+ * or the one the checkpoint ACKNOWLEDGED (seeded at runScan from `state.acknowledged.completed`, see
1177
+ * `state.completedRank = rankFromRef(state.acknowledged.completed)`) -- the same (timestamp, offset)
1178
+ * order the whole-tail decoder `claudeModelObservations` applies to (timestamp, index).
1179
+ */
1180
+ if (laterRank(state.completedRank, state.failure)) {
1181
+ observations.push(...claudeTurnFailureObservations(state.owner, state.failure));
1182
+ }
1152
1183
  } else {
1153
1184
  observations.push(...codexSettingsObservations(state.owner, state.selection),
1154
1185
  ...codexTurnObservations(state.owner, state.completed));
@@ -23,6 +23,13 @@ const SOURCE_GROUPS = {
23
23
  resolved: ['opencode:session-store', 'opencode:plugin-model', 'db:restore'],
24
24
  'completed-turn': ['opencode:message', 'db:restore'],
25
25
  },
26
+ // DeepSeek Harness (ACP): the bridge's `configOptions` (session/new, session/resume,
27
+ // config_option_update) is both the selection and the resolved model; a settled turn confirms it.
28
+ dsh: {
29
+ selection: ['dsh:config-option', 'db:restore'],
30
+ resolved: ['dsh:config-option', 'db:restore'],
31
+ 'completed-turn': ['dsh:turn', 'db:restore'],
32
+ },
26
33
  };
27
34
 
28
35
  function normalizedString(value, required = false) {