create-walle 0.10.2 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (488) hide show
  1. package/README.md +3 -1
  2. package/lib/release-schema.json +2 -2
  3. package/lib/runtime-closure-policy.json +8 -7
  4. package/package.json +1 -1
  5. package/template/coding-task-manager/api-prompts.js +45 -7
  6. package/template/coding-task-manager/bin/claude-hook.js +55 -1
  7. package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
  8. package/template/coding-task-manager/bin/land.js +2069 -0
  9. package/template/coding-task-manager/bin/memory-census.js +4 -2
  10. package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
  11. package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
  12. package/template/coding-task-manager/db.js +156 -32
  13. package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
  14. package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
  15. package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
  16. package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
  17. package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
  18. package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
  19. package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
  20. package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
  21. package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
  22. package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
  23. package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
  24. package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
  25. package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
  26. package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
  27. package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
  28. package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
  29. package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
  30. package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
  31. package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
  32. package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
  33. package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
  34. package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
  35. package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
  36. package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
  37. package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
  38. package/template/coding-task-manager/lib/agent-definitions.js +19 -0
  39. package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
  40. package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
  41. package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
  42. package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
  43. package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
  44. package/template/coding-task-manager/lib/agent-presets.js +84 -1
  45. package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
  46. package/template/coding-task-manager/lib/agent-version-service.js +74 -11
  47. package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
  48. package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
  49. package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
  50. package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
  51. package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
  52. package/template/coding-task-manager/lib/api/fleet.js +118 -0
  53. package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
  54. package/template/coding-task-manager/lib/api/ingress.js +9 -1
  55. package/template/coding-task-manager/lib/api/landing.js +403 -0
  56. package/template/coding-task-manager/lib/api/machines.js +691 -2
  57. package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
  58. package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
  59. package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
  60. package/template/coding-task-manager/lib/api/session-attach.js +623 -0
  61. package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
  62. package/template/coding-task-manager/lib/api/sessions.js +77 -51
  63. package/template/coding-task-manager/lib/api/setup-network.js +544 -16
  64. package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
  65. package/template/coding-task-manager/lib/api/setup.js +829 -10
  66. package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
  67. package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
  68. package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
  69. package/template/coding-task-manager/lib/auth-rules.js +292 -21
  70. package/template/coding-task-manager/lib/background-stop.js +369 -0
  71. package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
  72. package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
  73. package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
  74. package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
  75. package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
  76. package/template/coding-task-manager/lib/build-info.js +4 -2
  77. package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
  78. package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
  79. package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
  80. package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
  81. package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
  82. package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
  83. package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
  84. package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
  85. package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
  86. package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
  87. package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
  88. package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
  89. package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
  90. package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
  91. package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
  92. package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
  93. package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
  94. package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
  95. package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
  96. package/template/coding-task-manager/lib/conversation-sync.js +355 -0
  97. package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
  98. package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
  99. package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
  100. package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
  101. package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
  102. package/template/coding-task-manager/lib/db-domains.js +1 -0
  103. package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
  104. package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
  105. package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
  106. package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
  107. package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
  108. package/template/coding-task-manager/lib/feature-manifest.js +4 -0
  109. package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
  110. package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
  111. package/template/coding-task-manager/lib/fleet-hub.js +762 -0
  112. package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
  113. package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
  114. package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
  115. package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
  116. package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
  117. package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
  118. package/template/coding-task-manager/lib/fleet-update.js +798 -0
  119. package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
  120. package/template/coding-task-manager/lib/fs-watcher.js +58 -42
  121. package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
  122. package/template/coding-task-manager/lib/headless-term-service.js +84 -8
  123. package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
  124. package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
  125. package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
  126. package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
  127. package/template/coding-task-manager/lib/host-handoff.js +16 -19
  128. package/template/coding-task-manager/lib/host-stats.js +150 -3
  129. package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
  130. package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
  131. package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
  132. package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
  133. package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
  134. package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
  135. package/template/coding-task-manager/lib/hub-bridge.js +398 -0
  136. package/template/coding-task-manager/lib/idle-notify.js +491 -0
  137. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
  138. package/template/coding-task-manager/lib/instance-manifest.js +5 -1
  139. package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
  140. package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
  141. package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
  142. package/template/coding-task-manager/lib/landing/config.js +536 -0
  143. package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
  144. package/template/coding-task-manager/lib/landing/gate.js +360 -0
  145. package/template/coding-task-manager/lib/landing/git.js +344 -0
  146. package/template/coding-task-manager/lib/landing/lease.js +247 -0
  147. package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
  148. package/template/coding-task-manager/lib/landing/proof.js +223 -0
  149. package/template/coding-task-manager/lib/landing/queue.js +998 -0
  150. package/template/coding-task-manager/lib/landing/radar.js +489 -0
  151. package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
  152. package/template/coding-task-manager/lib/landing/state.js +263 -0
  153. package/template/coding-task-manager/lib/landing/stop.js +49 -0
  154. package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
  155. package/template/coding-task-manager/lib/landing/sync.js +456 -0
  156. package/template/coding-task-manager/lib/landing/train.js +885 -0
  157. package/template/coding-task-manager/lib/landing/window.js +57 -0
  158. package/template/coding-task-manager/lib/launch-environment.js +121 -0
  159. package/template/coding-task-manager/lib/launch-model-override.js +36 -10
  160. package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
  161. package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
  162. package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
  163. package/template/coding-task-manager/lib/lead-model-options.js +160 -3
  164. package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
  165. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
  166. package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
  167. package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
  168. package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
  169. package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
  170. package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
  171. package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
  172. package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
  173. package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
  174. package/template/coding-task-manager/lib/machine-registry.js +750 -5
  175. package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
  176. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
  177. package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
  178. package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
  179. package/template/coding-task-manager/lib/memory-join.js +337 -0
  180. package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
  181. package/template/coding-task-manager/lib/memory-sync.js +565 -0
  182. package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
  183. package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
  184. package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
  185. package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
  186. package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
  187. package/template/coding-task-manager/lib/model-availability.js +727 -0
  188. package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
  189. package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
  190. package/template/coding-task-manager/lib/model-id-rule.js +19 -0
  191. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
  192. package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
  193. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
  194. package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
  195. package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
  196. package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
  197. package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
  198. package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
  199. package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
  200. package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
  201. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
  202. package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
  203. package/template/coding-task-manager/lib/native-history-control.js +6 -4
  204. package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
  205. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
  206. package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
  207. package/template/coding-task-manager/lib/opencode-cli.js +480 -0
  208. package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
  209. package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
  210. package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
  211. package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
  212. package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
  213. package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
  214. package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
  215. package/template/coding-task-manager/lib/perf-summary.js +7 -0
  216. package/template/coding-task-manager/lib/perf-tracker.js +63 -2
  217. package/template/coding-task-manager/lib/project-config.js +7 -0
  218. package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
  219. package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
  220. package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
  221. package/template/coding-task-manager/lib/read-pool-client.js +89 -2
  222. package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
  223. package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
  224. package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
  225. package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
  226. package/template/coding-task-manager/lib/relay-client.js +57 -3
  227. package/template/coding-task-manager/lib/relink-audit.js +34 -5
  228. package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
  229. package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
  230. package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
  231. package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
  232. package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
  233. package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
  234. package/template/coding-task-manager/lib/restart-guard.js +18 -6
  235. package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
  236. package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
  237. package/template/coding-task-manager/lib/resume-admission.js +17 -3
  238. package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
  239. package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
  240. package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
  241. package/template/coding-task-manager/lib/runtime-contract.js +3 -1
  242. package/template/coding-task-manager/lib/schema-indexes.js +1 -0
  243. package/template/coding-task-manager/lib/session-context-locator.js +742 -0
  244. package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
  245. package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
  246. package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
  247. package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
  248. package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
  249. package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
  250. package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
  251. package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
  252. package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
  253. package/template/coding-task-manager/lib/session-create/response.js +7 -7
  254. package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
  255. package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
  256. package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
  257. package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
  258. package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
  259. package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
  260. package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
  261. package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
  262. package/template/coding-task-manager/lib/session-empty.js +13 -10
  263. package/template/coding-task-manager/lib/session-host-manager.js +60 -0
  264. package/template/coding-task-manager/lib/session-jobs.js +3 -1
  265. package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
  266. package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
  267. package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
  268. package/template/coding-task-manager/lib/session-park.js +738 -0
  269. package/template/coding-task-manager/lib/session-path-grant.js +13 -4
  270. package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
  271. package/template/coding-task-manager/lib/session-transport.js +17 -0
  272. package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
  273. package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
  274. package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
  275. package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
  276. package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
  277. package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
  278. package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
  279. package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
  280. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
  281. package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
  282. package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
  283. package/template/coding-task-manager/lib/submission-ack.js +90 -2
  284. package/template/coding-task-manager/lib/systemd-scope.js +115 -0
  285. package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
  286. package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
  287. package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
  288. package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
  289. package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
  290. package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
  291. package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
  292. package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
  293. package/template/coding-task-manager/lib/transcript-source.js +36 -4
  294. package/template/coding-task-manager/lib/transcript-store.js +9 -0
  295. package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
  296. package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
  297. package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
  298. package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
  299. package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
  300. package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
  301. package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
  302. package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
  303. package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
  304. package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
  305. package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
  306. package/template/coding-task-manager/lib/walle/turn.js +1 -1
  307. package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
  308. package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
  309. package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
  310. package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
  311. package/template/coding-task-manager/lib/walle-row-history.js +495 -0
  312. package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
  313. package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
  314. package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
  315. package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
  316. package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
  317. package/template/coding-task-manager/lib/ws/misc.js +1 -1
  318. package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
  319. package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
  320. package/template/coding-task-manager/oauth-proxy.js +112 -115
  321. package/template/coding-task-manager/package-lock.json +10 -94
  322. package/template/coding-task-manager/package.json +4 -3
  323. package/template/coding-task-manager/protocol/message-table.json +10 -0
  324. package/template/coding-task-manager/protocol/messages.js +10 -0
  325. package/template/coding-task-manager/protocol/ws-schema.json +20 -0
  326. package/template/coding-task-manager/protocol/ws-schema.md +2 -0
  327. package/template/coding-task-manager/public/css/app.css +170 -0
  328. package/template/coding-task-manager/public/css/walle-session.css +4 -0
  329. package/template/coding-task-manager/public/index.html +473 -243
  330. package/template/coding-task-manager/public/js/agent-command.js +86 -0
  331. package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
  332. package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
  333. package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
  334. package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
  335. package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
  336. package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
  337. package/template/coding-task-manager/public/js/background-work.js +196 -27
  338. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
  339. package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
  340. package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
  341. package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
  342. package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
  343. package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
  344. package/template/coding-task-manager/public/js/document-review-links.js +9 -1
  345. package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
  346. package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
  347. package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
  348. package/template/coding-task-manager/public/js/message-renderer.js +4 -3
  349. package/template/coding-task-manager/public/js/model-picker.js +3 -1
  350. package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
  351. package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
  352. package/template/coding-task-manager/public/js/pasted-content.js +236 -0
  353. package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
  354. package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
  355. package/template/coding-task-manager/public/js/prompts.js +11 -10
  356. package/template/coding-task-manager/public/js/protocol.js +10 -0
  357. package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
  358. package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
  359. package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
  360. package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
  361. package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
  362. package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
  363. package/template/coding-task-manager/public/js/stream-view.js +6 -5
  364. package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
  365. package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
  366. package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
  367. package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
  368. package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
  369. package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
  370. package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
  371. package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
  372. package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
  373. package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
  374. package/template/coding-task-manager/public/js/walle.js +6 -0
  375. package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
  376. package/template/coding-task-manager/public/m/app.css +140 -0
  377. package/template/coding-task-manager/public/m/app.js +507 -68
  378. package/template/coding-task-manager/public/m/index.html +17 -0
  379. package/template/coding-task-manager/public/m/machines.js +838 -4
  380. package/template/coding-task-manager/public/m/private-api.js +31 -1
  381. package/template/coding-task-manager/public/usage.html +1 -0
  382. package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
  383. package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
  384. package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
  385. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
  386. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
  387. package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
  388. package/template/coding-task-manager/server.js +1950 -11679
  389. package/template/coding-task-manager/session-integrity.js +64 -4
  390. package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
  391. package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
  392. package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
  393. package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
  394. package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
  395. package/template/coding-task-manager/workers/session-host-process.js +5 -5
  396. package/template/coding-task-manager/workers/watch-worker.js +105 -0
  397. package/template/coding-task-manager/workers/worktree-worker.js +168 -33
  398. package/template/ctm-relay/lib/protocol.js +14 -1
  399. package/template/package-lock.json +2 -2
  400. package/template/package.json +1 -1
  401. package/template/shared/backup-retention.js +82 -0
  402. package/template/shared/conversation-admission.js +2 -0
  403. package/template/shared/conversation-provenance.js +3 -7
  404. package/template/shared/conversation-storage-v2-contract.js +5 -0
  405. package/template/shared/linked-worktree.js +51 -0
  406. package/template/shared/macos-fda-target.js +57 -0
  407. package/template/shared/orphan-parents.js +55 -0
  408. package/template/shared/release-schema.json +2 -2
  409. package/template/shared/storage/contract.js +3 -0
  410. package/template/wall-e/adapters/imessage.js +12 -0
  411. package/template/wall-e/agent.js +71 -4
  412. package/template/wall-e/api-walle.js +21 -1
  413. package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
  414. package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
  415. package/template/wall-e/brain/brain-join.js +859 -0
  416. package/template/wall-e/brain/brain-sync-membership.js +20 -0
  417. package/template/wall-e/brain/brain-sync-store.js +131 -77
  418. package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
  419. package/template/wall-e/brain/brain-sync-v2.js +578 -0
  420. package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
  421. package/template/wall-e/brain/deterministic-id.js +51 -0
  422. package/template/wall-e/brain/memories.js +2 -2
  423. package/template/wall-e/brain/migrations.js +40 -6
  424. package/template/wall-e/brain/model-identity-migration.js +1 -1
  425. package/template/wall-e/brain/owner-call-whitelist.js +23 -7
  426. package/template/wall-e/brain/schema.js +45 -85
  427. package/template/wall-e/brain.js +171 -35
  428. package/template/wall-e/chat.js +3 -3
  429. package/template/wall-e/coding/agent-shell-env.js +7 -2
  430. package/template/wall-e/coding/prompt-bundle.js +66 -21
  431. package/template/wall-e/config/main-loop-exemptions.json +2 -2
  432. package/template/wall-e/http/admin-api.js +37 -0
  433. package/template/wall-e/http/gws-api.js +4 -0
  434. package/template/wall-e/http/helper-rules-api.js +7 -1
  435. package/template/wall-e/http/model-admin.js +8 -1
  436. package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
  437. package/template/wall-e/http/model-proxy-providers.js +174 -1
  438. package/template/wall-e/http/model-route-health.js +157 -0
  439. package/template/wall-e/http/sync-api.js +278 -464
  440. package/template/wall-e/jobs/job-runner.js +28 -1
  441. package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
  442. package/template/wall-e/lib/ctm-data-dir.js +26 -0
  443. package/template/wall-e/lib/derivation-home.js +147 -0
  444. package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
  445. package/template/wall-e/lib/helper-rules/grade.js +51 -8
  446. package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
  447. package/template/wall-e/lib/helper-rules/store.js +4 -2
  448. package/template/wall-e/lib/landing-mcp-tools.js +170 -0
  449. package/template/wall-e/lib/mcp-client-config.js +133 -14
  450. package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
  451. package/template/wall-e/lib/mcp-integration.js +58 -13
  452. package/template/wall-e/lib/parent-death.js +7 -1
  453. package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
  454. package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
  455. package/template/wall-e/llm/delegate-vendor-default.js +12 -5
  456. package/template/wall-e/llm/model-roles.js +1 -1
  457. package/template/wall-e/llm/native-delegate-selection.js +56 -8
  458. package/template/wall-e/llm/worker-delegate-args.js +72 -7
  459. package/template/wall-e/llm/worker-mcp-routing.js +66 -17
  460. package/template/wall-e/loops/brain-custom-writes.js +19 -0
  461. package/template/wall-e/loops/ingest.js +17 -1
  462. package/template/wall-e/loops/think.js +19 -4
  463. package/template/wall-e/mcp-contract.js +222 -6
  464. package/template/wall-e/mcp-protocol-contract.js +40 -5
  465. package/template/wall-e/mcp-server.js +128 -29
  466. package/template/wall-e/mcp-worker-schemas.js +5 -5
  467. package/template/wall-e/memory/ctm-context-client.js +85 -0
  468. package/template/wall-e/memory/ctm-session-context.js +9 -3
  469. package/template/wall-e/memory/hub-bridge-client.js +388 -0
  470. package/template/wall-e/memory/replica-origin.js +56 -0
  471. package/template/wall-e/memory/session-pool.js +135 -0
  472. package/template/wall-e/runtime/live-capabilities.js +8 -3
  473. package/template/wall-e/server.js +4 -2
  474. package/template/wall-e/shared/release-schema.json +2 -2
  475. package/template/wall-e/shared/sqlite-file-set.js +39 -0
  476. package/template/wall-e/shared/storage/contract.js +3 -0
  477. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  478. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
  479. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
  480. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
  481. package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
  482. package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
  483. package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
  484. package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
  485. package/template/wall-e/tools/chrome-automation.js +6 -0
  486. package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
  487. package/template/wall-e/workers/brain-owner-worker.js +18 -4
  488. package/template/wall-e/workers/mcp-gateway-process.js +5 -5
@@ -0,0 +1,743 @@
1
+ 'use strict';
2
+
3
+ // Landing-throughput WP-6 shard S9 (design doc §5 D-10 "move-only", §6 "Shard
4
+ // module seam"): the fourteen Codex-rollout-history render/compose functions move out
5
+ // of server.js VERBATIM into this module behind the same configure(deps) seam as
6
+ // lib/api/session-messages.js (S3), lib/api/session-attach.js and
7
+ // lib/terminal-attach-geometry.js (S6) and lib/walle-history-serve.js (S8). It
8
+ // registers NO route and NO socket handler: lib/ws/lifecycle.js and lib/ws/state-sync.js
9
+ // (wsLifecycleApi / wsStateSyncApi) and attachGeometry keep their tables and now receive
10
+ // this module's exports, while server.js keeps the pass-through callers
11
+ // (codexRolloutHistory.<name>) plus this by-value configure() seam.
12
+ // Bodies are identical to server.js's declarations except for the `_deps.` prefix on
13
+ // every identifier that used to resolve to a server.js top-level binding (D-10 rule 1),
14
+ // proven by `node bin/move-only-check.js`. No moved body contains an inline
15
+ // `require(...)`, so there is no require rebase here (unlike S1/S3/S6/S8).
16
+ //
17
+ // The module deliberately lives at lib/codex-rollout-history.js and NOT under lib/ws/:
18
+ // these are payload/render helpers, not ws-router handlers.
19
+ //
20
+ // Injected deps, per function:
21
+ // _codexRowCandidateIds: (none)
22
+ // _sessionHasFocusedViewer: (none)
23
+ // requestRowCursorRepublish: _codexHistoryCursorRepairAt, recordSessionDiagnostic,
24
+ // requestTargetedConversationImport
25
+ // _codexRowHistoryBase: dbModule
26
+ // _matchingPublishedCodexRollout: (none)
27
+ // _transcriptHistoryProvider: CTM_CODEX_ROLLOUT_HISTORY_ENABLED, detectAgentType
28
+ // _codexRolloutHistoryActive: (none)
29
+ // _codexHistoryRenderCacheEntry: CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION
30
+ // _codexHistoryRenderNull: recordSessionDiagnostic
31
+ // _codexHistoryRenderInputForBase: CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION
32
+ // _runCodexHistoryRenderQueue: CODEX_ROLLOUT_HISTORY_TAIL_MAX_MSGS,
33
+ // CODEX_ROLLOUT_HISTORY_TAIL_SEED_MSGS, CTM_READPOOL_INTERACTIVE_LANE_ENABLED,
34
+ // CTM_SNAPSHOT_SHALLOW_GUARD_ENABLED, RESUME_PRIORITY_LANE_ENABLED,
35
+ // _SESSION_MESSAGES_READPOOL_TIMEOUT_MS, _offthreadRead, _rolloutRenderBreaker,
36
+ // _scheduleSecondaryPush, _snapshotSessionScrollbackToFile,
37
+ // _testHistoryRenderNullsRemaining, dbModule, recordSessionDiagnostic, sessions
38
+ // _requestCodexHistoryRender: CTM_READPOOL_INTERACTIVE_LANE_ENABLED
39
+ // _scheduleCodexHistoryRender: (none)
40
+ // _composeCodexRolloutResp: CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION,
41
+ // CODEX_HISTORY_ROWS_STALE_ALARM_MS, CODEX_ROLLOUT_DURABLE_STALE_RENDER_MS,
42
+ // CODEX_ROLLOUT_HISTORY_MAX_LINES, CODEX_ROLLOUT_HISTORY_REFLOW_MAX_LINES,
43
+ // CTM_READPOOL_INTERACTIVE_LANE_ENABLED, CTM_SEAM_CONTENT_TRIM_ENABLED,
44
+ // RESUME_REPLAY_DEDUP_ENABLED, _buildCodexComposedMemoKey,
45
+ // _canReuseDurableHistoryRender, _codexViewportLooksSettled,
46
+ // _composeCodexHistorySnapshot, _decideCodexComposedMemoReuse,
47
+ // _hashCodexComposeViewport, _mirrorGridLinesForCompose,
48
+ // _observeCodexHistoryStaleRows, _selectCodexHistoryLineCap,
49
+ // _shouldSuppressMidTurnRestore, normalizeSnapshotScrollbackRows,
50
+ // recordSessionDiagnostic
51
+ //
52
+ // Mutable module state (D-10 rule 2): _testHistoryRenderNullsRemaining is the ONE
53
+ // server.js binding a moved body WRITES (_runCodexHistoryRenderQueue's
54
+ // `_testHistoryRenderNullsRemaining -= 1`), so it is injected as a getter/setter pair --
55
+ // exactly how S3 (lib/api/session-messages.js) re-homed the two bindings its moved
56
+ // bodies assign -- so the write reaches the same server.js binding instead of a copy
57
+ // frozen at configure() time. _codexHistoryCursorRepairAt is a const Map that is only
58
+ // mutated in place (never rebound), so it is passed by value like S8's per-session Maps.
59
+ // Every other dep is a by-value reference; calls between the fourteen moved functions
60
+ // stay direct (no _deps.).
61
+
62
+ let _deps = null;
63
+
64
+ function configure(deps = {}) {
65
+ _deps = deps;
66
+ }
67
+
68
+ function _codexRowCandidateIds(session, sessionId) {
69
+ const ids = [];
70
+ const add = (value) => {
71
+ const id = String(value || '').trim();
72
+ if (id && !ids.includes(id)) ids.push(id);
73
+ };
74
+ add(sessionId);
75
+ add(session && session._claudeSessionId);
76
+ return ids;
77
+ }
78
+
79
+ function _sessionHasFocusedViewer(session, sessionId) {
80
+ if (!session || !sessionId || !Array.isArray(session.clients)) return false;
81
+ return session.clients.some((ws) => (
82
+ ws?.readyState === 1
83
+ && ws.focused === sessionId
84
+ && (!(ws.viewing instanceof Set) || ws.viewing.has(sessionId))
85
+ ));
86
+ }
87
+
88
+ function requestRowCursorRepublish(sessionId, sourceId) {
89
+ const id = String(sessionId || '');
90
+ const source = String(sourceId || id);
91
+ if (!id || !source) return false;
92
+ const now = Date.now();
93
+ if (now - Number(_deps._codexHistoryCursorRepairAt.get(id) || 0) < 60000) return false;
94
+ _deps._codexHistoryCursorRepairAt.set(id, now);
95
+ void _deps.requestTargetedConversationImport(source, 'codex-history-stale-repair', { cursorOnly: false })
96
+ .then((result) => {
97
+ _deps.recordSessionDiagnostic(id, 'codex-history-row-cursor-republished', {
98
+ sourceId: source,
99
+ accepted: result?.accepted !== false,
100
+ completed: result?.completed !== false,
101
+ });
102
+ })
103
+ .catch((error) => {
104
+ _deps.recordSessionDiagnostic(id, 'codex-history-row-cursor-republish-failed', {
105
+ sourceId: source,
106
+ code: error?.code || '',
107
+ error: error?.message || String(error),
108
+ });
109
+ });
110
+ if (_deps._codexHistoryCursorRepairAt.size > 1000) {
111
+ for (const [repairId, at] of _deps._codexHistoryCursorRepairAt) {
112
+ if (now - at > 5 * 60 * 1000) _deps._codexHistoryCursorRepairAt.delete(repairId);
113
+ }
114
+ }
115
+ return true;
116
+ }
117
+
118
+ function _codexRowHistoryBase(session, sessionId) {
119
+ for (const id of _codexRowCandidateIds(session, sessionId)) {
120
+ try {
121
+ const state = _deps.dbModule.getSessionRowSourceCursorState(id);
122
+ const count = Number(state?.rowCount || 0);
123
+ if (count > 0) {
124
+ const projectionEpoch = Math.max(0, Number(state.projectionEpoch || 0));
125
+ const renderFresh = state.renderFresh === true;
126
+ const version = [
127
+ count,
128
+ state.checked ? 1 : 0,
129
+ renderFresh ? 1 : 0,
130
+ Number(state.importedSize || 0),
131
+ Number(state.maxTranscriptEventId || 0),
132
+ Number(state.rowBackfillCursorEventId || 0),
133
+ projectionEpoch,
134
+ ].join(':');
135
+ return {
136
+ id,
137
+ count,
138
+ fresh: !state.checked || state.fresh === true,
139
+ renderFresh,
140
+ state: String(state.state || ''),
141
+ cursorLagBytes: Math.max(0, Number(state.cursorLagBytes || 0)),
142
+ pendingEvents: Math.max(0, Number(state.pendingEvents || 0)),
143
+ parserVersion: Math.max(0, Number(state.parserVersion || 0)),
144
+ projectionEpoch,
145
+ projectionState: String(state.projectionState || 'ready'),
146
+ maxRowId: Math.max(0, Number(state.maxRowId || 0)),
147
+ version,
148
+ };
149
+ }
150
+ } catch { /* registry publication is best-effort; retry on the next snapshot */ }
151
+ }
152
+ return null;
153
+ }
154
+
155
+ // Published metadata only: a cache miss never discovers a transcript on main.
156
+ function _matchingPublishedCodexRollout(session, sessionId) {
157
+ const threadId = session?._claudeSessionId || session?._providerResumeId || sessionId || session?.id;
158
+ const alias = session?._providerResumeId && session._providerResumeId !== threadId ? session._providerResumeId : '';
159
+ const cache = session?._codexRolloutPathCache;
160
+ return cache && cache.threadId === threadId
161
+ && (cache.providerResumeId === undefined || cache.providerResumeId === alias) ? cache : null;
162
+ }
163
+
164
+ // The provider-neutral transcript source for this session, or null if neither applies (wrong
165
+ // provider or codex's kill switch is off). Two independent consumers key off this: (1) the
166
+ // paged older-transcript-history API (apiSessionHistoryWindow / serveTranscriptHistoryV2),
167
+ // which serves both codex and claude and has no kill switch of its own for claude, and
168
+ // (2) the composed-terminal-seed gate (_codexRolloutHistoryActive below), which additionally
169
+ // requires 'codex' — WP-5 retired the composed seed for claude, not this provider lookup.
170
+ function _transcriptHistoryProvider(session) {
171
+ const agentType = _deps.detectAgentType((session && session.cmd) || '');
172
+ if (agentType === 'codex' && _deps.CTM_CODEX_ROLLOUT_HISTORY_ENABLED) return 'codex';
173
+ if (agentType === 'claude') return 'claude';
174
+ return null;
175
+ }
176
+
177
+ // Is the rollout-backed composed terminal seed active for this session? Codex only (WP-5
178
+ // retired the claude compose) + a usable durable row source. Terminal UX never reads JSONL
179
+ // directly; if rows are unavailable, callers behave exactly like today (serialize the
180
+ // headless blob) -- and a claude session always behaves like today now, unconditionally.
181
+ function _codexRolloutHistoryActive(session, sessionId) {
182
+ if (!session || _transcriptHistoryProvider(session) !== 'codex') return false;
183
+ return !!_codexRowHistoryBase(session, sessionId);
184
+ }
185
+
186
+ function _codexHistoryRenderCacheEntry(input, rendered) {
187
+ return {
188
+ key: input.renderKey,
189
+ ansi: rendered.ansi,
190
+ lineCount: rendered.lineCount,
191
+ renderedLineCount: rendered.renderedLineCount,
192
+ fellBack: rendered.fellBack,
193
+ messages: rendered.messages,
194
+ capped: !!rendered.capped,
195
+ elidedLines: Number(rendered.elidedLines || 0),
196
+ bound: input.historyLineCap,
197
+ source: input.sourceKey,
198
+ sourceKey: input.sourceKey,
199
+ lookupId: input.lookupId,
200
+ cols: input.cols,
201
+ rowMessages: Number(rendered.rowMessages || 0),
202
+ rowBaseCount: Number(input.rowBaseCount || 0),
203
+ rowBaseVersion: String(input.rowBaseVersion || ''),
204
+ sourceRowHwm: Math.max(0, Number(input.sourceRowHwm || 0)),
205
+ displayMode: rendered.displayMode || 'terminal-markdown',
206
+ historyLineCap: input.historyLineCap,
207
+ messageSpans: Array.isArray(rendered.spans) ? rendered.spans : [],
208
+ elidedMessages: Number(rendered.elidedMessages || 0),
209
+ rendererVersion: _deps.CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION,
210
+ historyRenderFidelity: true,
211
+ createdAt: Date.now(),
212
+ // WP-0: worker-measured render time (see workers/read-pool-worker.js 'renderRolloutHistory'),
213
+ // threaded through the cache entry so a cache-hit compose can still report it.
214
+ renderMs: Number.isFinite(Number(rendered.workerRenderMs)) ? Number(rendered.workerRenderMs) : undefined,
215
+ };
216
+ }
217
+
218
+ function _codexHistoryRenderNull(sessionId, reason, details = {}) {
219
+ _deps.recordSessionDiagnostic(sessionId, 'codex-history-render-null', { reason, ...details });
220
+ return { retryable: true, cause: reason };
221
+ }
222
+
223
+ function _codexHistoryRenderInputForBase(input, rowBase) {
224
+ const sourceKey = rowBase.renderFresh ? 'rows' : 'rows-stale';
225
+ return {
226
+ ...input,
227
+ renderKey: `${input.agentType}:${sourceKey}:${rowBase.id}:${rowBase.version}:${input.cols}:${input.historyLineCap}:renderer${_deps.CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION}:fidelity1`,
228
+ lookupId: rowBase.id,
229
+ sourceKey,
230
+ rowBaseCount: rowBase.count || 0,
231
+ rowBaseVersion: rowBase.version,
232
+ sourceRowHwm: rowBase.maxRowId || 0,
233
+ };
234
+ }
235
+
236
+ function _runCodexHistoryRenderQueue(session) {
237
+ if (!session || session._codexHistoryRenderInFlight) return;
238
+ const queue = session._codexHistoryRenderQueue;
239
+ if (!Array.isArray(queue) || queue.length === 0) return;
240
+ const request = queue.shift();
241
+ if (_deps.sessions.get(request.sessionId) !== session) {
242
+ request.resolve(_codexHistoryRenderNull(request.sessionId, 'session-swap'));
243
+ setImmediate(() => _runCodexHistoryRenderQueue(session));
244
+ return;
245
+ }
246
+ const input = request.input;
247
+ session._codexHistoryRenderInFlight = request;
248
+ void _deps._offthreadRead({
249
+ breaker: _deps._rolloutRenderBreaker,
250
+ op: 'renderRolloutHistory',
251
+ timeoutMs: _deps._SESSION_MESSAGES_READPOOL_TIMEOUT_MS,
252
+ payload: {
253
+ dbPath: _deps.dbModule.getDbPath(),
254
+ rowSourceId: input.lookupId,
255
+ messageLimit: _deps.CODEX_ROLLOUT_HISTORY_TAIL_MAX_MSGS,
256
+ minSeedMessages: _deps.CODEX_ROLLOUT_HISTORY_TAIL_SEED_MSGS,
257
+ seedMsgs: Number(input.seedMsgs || 0),
258
+ agentType: input.agentType,
259
+ cols: input.cols,
260
+ cliVersion: input.cliVersion || '',
261
+ historyLineCap: input.historyLineCap,
262
+ historyRenderFidelity: true,
263
+ // WP-3 (terminal-memory-endgame S-11): the true store depth (session_message_rows
264
+ // COUNT), NOT the render window. The worker uses this — not the page's own `total`,
265
+ // which reflects whatever store getMessagesPage happens to read (v2 turns can be a
266
+ // much smaller count than the granular row store) — as the denominator for the
267
+ // elided-messages marker, so "N elided" is honest against the full transcript depth.
268
+ rowBaseCount: Number(input.rowBaseCount || 0),
269
+ telemetryReason: 'rollout-history-render',
270
+ },
271
+ // WI-7c: downgrade a durable (background persistence) render off the declared 'service'
272
+ // class so it can never head-of-line block a foreground render behind a bulk/durable
273
+ // backlog — see resolveReadPoolClass (a downgrade-only ceiling, never an escalation).
274
+ requestClass: _deps.CTM_READPOOL_INTERACTIVE_LANE_ENABLED && input.requestClass
275
+ ? input.requestClass
276
+ : (_deps.RESUME_PRIORITY_LANE_ENABLED && input.durable ? 'batch' : undefined),
277
+ onSuccess: (result) => result && typeof result === 'object' ? result : null,
278
+ onFail: (error) => input.requestClass === 'interactive'
279
+ ? {
280
+ composePending: true,
281
+ retryAfterMs: 1000,
282
+ errorCode: String(error?.code || ''),
283
+ }
284
+ : null,
285
+ }).then((renderedResult) => {
286
+ let rendered = renderedResult;
287
+ if (input.requestClass === 'interactive' && _deps._testHistoryRenderNullsRemaining > 0) {
288
+ _deps._testHistoryRenderNullsRemaining -= 1;
289
+ rendered = null;
290
+ _deps.recordSessionDiagnostic(request.sessionId, 'codex-history-render-null', {
291
+ reason: 'test-worker-null',
292
+ remaining: _deps._testHistoryRenderNullsRemaining,
293
+ });
294
+ }
295
+ if (rendered?.composePending) {
296
+ session._codexHistoryComposePending = {
297
+ until: Date.now() + Math.max(250, Number(rendered.retryAfterMs) || 1000),
298
+ retryAfterMs: Math.max(250, Number(rendered.retryAfterMs) || 1000),
299
+ };
300
+ request.resolve(rendered);
301
+ return;
302
+ }
303
+ if (!rendered?.ansi || session._codexHistoryRenderInFlight !== request
304
+ || _deps.sessions.get(request.sessionId) !== session) {
305
+ const reason = _deps.sessions.get(request.sessionId) !== session ? 'session-swap'
306
+ : (rendered?.composePending ? 'pool-fail' : 'worker-error');
307
+ request.resolve(rendered?.composePending || _codexHistoryRenderNull(request.sessionId, reason));
308
+ return;
309
+ }
310
+ const completedInput = request.input;
311
+ const current = _codexRowHistoryBase(session, request.sessionId);
312
+ if (!current || current.id !== completedInput.lookupId
313
+ || current.version !== completedInput.rowBaseVersion) {
314
+ if (!current || current.id !== completedInput.lookupId) {
315
+ request.resolve(_codexHistoryRenderNull(request.sessionId, current ? 'source-swap' : 'session-swap'));
316
+ return;
317
+ }
318
+ const completed = {
319
+ ..._codexHistoryRenderCacheEntry(completedInput, rendered),
320
+ staleByVersions: true,
321
+ currentRowBaseVersion: current.version,
322
+ };
323
+ _deps.recordSessionDiagnostic(request.sessionId, 'codex-history-render-version-advanced', {
324
+ fromVersion: completedInput.rowBaseVersion,
325
+ toVersion: current.version,
326
+ });
327
+ request.resolve(completed);
328
+ _scheduleCodexHistoryRender(session, request.sessionId, _codexHistoryRenderInputForBase(completedInput, current));
329
+ return;
330
+ }
331
+ session._rolloutHistoryTailSeed = Number(rendered.nextSeed || 0);
332
+ const cacheEntry = _codexHistoryRenderCacheEntry(completedInput, rendered);
333
+ session._codexHistoryRenderCache = cacheEntry;
334
+ session._codexHistoryComposePending = null;
335
+ // WP-4 (S-5/D-6): a DURABLE render request means the caller was
336
+ // _snapshotSessionScrollbackToFile's own compose attempt bailing (nothing cached
337
+ // yet) -- this render landing is exactly the deferred completion the shallow-
338
+ // overwrite guard above told the caller to wait for. Re-persist once now that a
339
+ // composed render exists, so the durable file catches up to full depth instead of
340
+ // waiting for the next periodic sweep (30s) or shutdown.
341
+ if (_deps.CTM_SNAPSHOT_SHALLOW_GUARD_ENABLED && completedInput.durable === true) {
342
+ setImmediate(() => {
343
+ if (_deps.sessions.get(request.sessionId) !== session) return;
344
+ _deps._snapshotSessionScrollbackToFile(request.sessionId, 5000).catch(() => { /* expected: best-effort re-persist -- a failure here just leaves the file at whatever the shallow-skip guard kept, which the next periodic sweep or shutdown snapshot still catches up */ });
345
+ });
346
+ }
347
+ _deps.recordSessionDiagnostic(request.sessionId, 'codex-rollout-history-render-ready', {
348
+ agent: completedInput.agentType,
349
+ cols: completedInput.cols,
350
+ rows: rendered.lineCount,
351
+ messages: rendered.messages,
352
+ capped: !!rendered.capped,
353
+ });
354
+ request.resolve(cacheEntry);
355
+ if (completedInput.settled === true
356
+ && Number(session._ptyCols || 0) === Number(completedInput.cols)
357
+ && typeof session._sendCleanSnapshot === 'function') {
358
+ setImmediate(() => {
359
+ if (_deps.sessions.get(request.sessionId) !== session) return;
360
+ session._sendCleanSnapshot(request.sessionId, null, {
361
+ restoreSource: 'rollout-history-render-ready',
362
+ reason: 'rollout-history-render-ready',
363
+ skipIfStale: true,
364
+ });
365
+ });
366
+ }
367
+ if (session._hasSecondaryViewers) _deps._scheduleSecondaryPush(session, request.sessionId, 'rollout-history-render-ready');
368
+ }).catch((err) => {
369
+ console.error('[rollout-history] worker render completion failed:', err.message);
370
+ request.resolve(_codexHistoryRenderNull(request.sessionId, 'worker-error', {
371
+ code: String(err?.code || ''),
372
+ }));
373
+ }).finally(() => {
374
+ if (session._codexHistoryRenderInFlight === request) session._codexHistoryRenderInFlight = null;
375
+ setImmediate(() => _runCodexHistoryRenderQueue(session));
376
+ });
377
+ }
378
+
379
+ function _requestCodexHistoryRender(session, sessionId, input) {
380
+ if (!session || !input?.renderKey) return Promise.resolve(null);
381
+ const cached = session._codexHistoryRenderCache;
382
+ if (cached?.key === input.renderKey && cached.ansi) return Promise.resolve(cached);
383
+
384
+ const inFlight = session._codexHistoryRenderInFlight;
385
+ if (inFlight?.key === input.renderKey) {
386
+ if (input.settled === true) inFlight.input.settled = true;
387
+ return inFlight.promise;
388
+ }
389
+ if (!Array.isArray(session._codexHistoryRenderQueue)) session._codexHistoryRenderQueue = [];
390
+ const queued = session._codexHistoryRenderQueue.find((entry) => entry.key === input.renderKey);
391
+ if (queued) {
392
+ if (input.settled === true) queued.input.settled = true;
393
+ return queued.promise;
394
+ }
395
+
396
+ let resolveRequest;
397
+ const promise = new Promise((resolve) => { resolveRequest = resolve; });
398
+ const request = {
399
+ key: input.renderKey,
400
+ sessionId,
401
+ input: { ...input },
402
+ promise,
403
+ resolve: resolveRequest,
404
+ };
405
+ if (_deps.CTM_READPOOL_INTERACTIVE_LANE_ENABLED && input.requestClass === 'interactive') {
406
+ session._codexHistoryRenderQueue.unshift(request);
407
+ } else {
408
+ session._codexHistoryRenderQueue.push(request);
409
+ }
410
+ _runCodexHistoryRenderQueue(session);
411
+ return promise;
412
+ }
413
+
414
+ function _scheduleCodexHistoryRender(session, sessionId, input) {
415
+ void _requestCodexHistoryRender(session, sessionId, input);
416
+ }
417
+
418
+ // Given a serialize reply that was requested at scrollback:0 (the native live
419
+ // region only), prepend the rollout-synthesized settled history (rendered at the
420
+ // SAME cols so the client never reflows it) and return a resp with composed data.
421
+ // Codex only (WP-5 retired the claude compose path) — a non-codex session (including
422
+ // claude, whose local scrollback is now served exactly like any other normal-buffer
423
+ // session) returns resp UNCHANGED, never gets misrouted into this render path.
424
+ // FAIL-SAFE: any problem returns the original resp unchanged (the native viewport),
425
+ // so a bad render degrades to "live region only", never to corruption or a throw.
426
+ function _composeCodexRolloutResp(session, sessionId, resp, opts = {}) {
427
+ if (!resp || !resp.data) return resp;
428
+ const agentType = _transcriptHistoryProvider(session);
429
+ if (agentType !== 'codex') return resp;
430
+ // durable: this snapshot is being PERSISTED to file (cold-resume seed), not sent
431
+ // live. The interactive transcript pager is kept for live sends but dropped for
432
+ // durable persistence so a cold resume never restores into a dead pager.
433
+ const durable = !!(opts && opts.durable);
434
+ const isReflow = !!(opts && opts.reflow);
435
+ try {
436
+ const cols = Number(resp.cols) || session._ptyCols || 80;
437
+ const liveViewportData = String(resp.data || '');
438
+ const settled = _deps._codexViewportLooksSettled(liveViewportData);
439
+ const gridSample = _deps._mirrorGridLinesForCompose(session, resp);
440
+ const capPolicy = _deps._selectCodexHistoryLineCap({
441
+ isReflow,
442
+ cols,
443
+ lastComposedCols: session._lastCodexHistoryComposeCols,
444
+ normalMaxLines: _deps.CODEX_ROLLOUT_HISTORY_MAX_LINES,
445
+ reflowMaxLines: _deps.CODEX_ROLLOUT_HISTORY_REFLOW_MAX_LINES,
446
+ });
447
+ const historyLineCap = capPolicy.cap;
448
+ const rowBase = _codexRowHistoryBase(session, sessionId);
449
+ if (!rowBase) return resp;
450
+ const lookupId = rowBase && rowBase.id;
451
+ if (!lookupId) return resp;
452
+ const sourceKey = rowBase.renderFresh ? 'rows' : 'rows-stale';
453
+ // Cheap content-version so repeated snapshots of unchanged row history
454
+ // (tab-switch, reconnect, secondary-push, reflow at the same width) skip the
455
+ // row fetch + render entirely. Terminal compose is row-only; rollout JSONL
456
+ // tails are not merged into this surface.
457
+ const version = rowBase.version;
458
+ // agentType-prefixed so a cached codex render can never serve a claude session (the
459
+ // cache lives on the session object and is per-session anyway; this is paranoia).
460
+ const renderKey = `${agentType}:${sourceKey}:${lookupId}:${version}:${cols}:${historyLineCap}:renderer${_deps.CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION}:fidelity1`;
461
+ let historyAnsi; let lineCount; let renderedLineCount; let historyElidedLines = 0; let fellBack; let msgCount; let historyCapped = false; let displayMode = 'terminal-markdown'; let messageSpans = []; let historyElidedMessages = 0;
462
+ let source = sourceKey; let rowMsgCount = 0; let renderMs; // WP-0: worker-measured, undefined when not from a fresh/cached render
463
+ const rc = session._codexHistoryRenderCache;
464
+ const exactCacheHit = rc && rc.key === renderKey && !!rc.ansi;
465
+ const reusedStaleRender = !exactCacheHit && _deps._canReuseDurableHistoryRender({
466
+ durable,
467
+ cacheEntry: rc,
468
+ lookupId,
469
+ sourceKey,
470
+ cols,
471
+ historyLineCap,
472
+ rowBaseCount: rowBase.count || 0,
473
+ rendererVersion: _deps.CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION,
474
+ historyRenderFidelity: true,
475
+ settled,
476
+ now: Date.now(),
477
+ maxAgeMs: _deps.CODEX_ROLLOUT_DURABLE_STALE_RENDER_MS,
478
+ });
479
+ const cacheHit = exactCacheHit || reusedStaleRender;
480
+ if (cacheHit) {
481
+ ({ ansi: historyAnsi, lineCount, renderedLineCount, fellBack, messages: msgCount } = rc);
482
+ messageSpans = Array.isArray(rc.messageSpans) ? rc.messageSpans : [];
483
+ historyElidedMessages = Number(rc.elidedMessages || 0);
484
+ displayMode = rc.displayMode || displayMode;
485
+ historyCapped = !!rc.capped;
486
+ historyElidedLines = Number(rc.elidedLines || 0);
487
+ source = rc.source || source;
488
+ rowMsgCount = Number(rc.rowMessages || 0);
489
+ renderMs = Number.isFinite(Number(rc.renderMs)) ? Number(rc.renderMs) : undefined;
490
+ } else {
491
+ const renderRequestClass = _deps.CTM_READPOOL_INTERACTIVE_LANE_ENABLED
492
+ ? (opts.requestClass || (
493
+ durable
494
+ ? 'batch'
495
+ : (_sessionHasFocusedViewer(session, sessionId) ? 'interactive' : 'service')
496
+ ))
497
+ : undefined;
498
+ const pending = session._codexHistoryComposePending;
499
+ if (renderRequestClass === 'interactive' && Number(pending?.until) > Date.now()) {
500
+ return {
501
+ ...resp,
502
+ data: null,
503
+ composePending: true,
504
+ retryAfterMs: Math.max(250, Number(pending.retryAfterMs) || 1000),
505
+ };
506
+ }
507
+ _scheduleCodexHistoryRender(session, sessionId, {
508
+ renderKey,
509
+ lookupId,
510
+ sourceKey,
511
+ rowBaseCount: rowBase.count || 0,
512
+ rowBaseVersion: rowBase.version,
513
+ agentType,
514
+ cols,
515
+ cliVersion: session._codexCliVersion || '',
516
+ historyLineCap,
517
+ seedMsgs: session._rolloutHistoryTailSeed || 0,
518
+ settled,
519
+ // WI-7c: a durable (persistence/cold-resume-seed) render is background work — it isn't
520
+ // shown to any connected client — so it must never queue ahead of a foreground render's
521
+ // own renderRolloutHistory read on the read pool (see _runCodexHistoryRenderQueue).
522
+ durable,
523
+ requestClass: renderRequestClass,
524
+ });
525
+ return resp;
526
+ }
527
+ // The live region is owned by Codex/state-sync. A flap/divergence-driven
528
+ // reflow (opts.deferMidTurn) that restores history while the turn is still
529
+ // streaming can reset over Codex's live inline repaint. Keep the current
530
+ // frame mid-turn; the settle-time reconcile applies H and then forces L.
531
+ // Returns data:null + a marker so the caller sends "keep-current".
532
+ if (_deps._shouldSuppressMidTurnRestore({
533
+ deferrableSource: !!(opts && opts.deferMidTurn),
534
+ settled,
535
+ forceMidTurnSnapshot: !!(opts && opts.forceMidTurnSnapshot),
536
+ })) {
537
+ _deps.recordSessionDiagnostic(sessionId, 'codex-midturn-restore-suppressed', { agent: agentType, cols, source });
538
+ return { ...resp, data: null, _codexMidTurnDeferred: true };
539
+ }
540
+ // WI-9 step 2: _composeCodexHistorySnapshot (seam compute + string concat of potentially
541
+ // multi-MB historyAnsi + liveViewportData) is a PURE function of (renderKey resolved above,
542
+ // the live viewport bytes, durable/reflow/rows/scrollbackRows) — a repeated snapshot request
543
+ // for a session sitting idle at the same settled screen (tab-switch, reconnect, secondary-
544
+ // push) recomputes byte-identical output every time. Memoize the COMPOSED result (not just
545
+ // the history render, already cached via session._codexHistoryRenderCache) per that tuple so
546
+ // an unchanged snapshot skips compose entirely.
547
+ const composeRows = Number(resp.rows) || Number(session._ptyRows) || 0;
548
+ const composeScrollbackRows = _deps.normalizeSnapshotScrollbackRows(session._snapshotScrollbackRows);
549
+ const composedMemoKey = _deps._buildCodexComposedMemoKey({
550
+ renderKey,
551
+ viewportHash: _deps._hashCodexComposeViewport(liveViewportData),
552
+ rows: composeRows,
553
+ durable,
554
+ reflow: isReflow,
555
+ scrollbackRows: composeScrollbackRows,
556
+ });
557
+ // Two memo slots (durable persistence vs live/client compose) so the interleaved durable
558
+ // scrollback-snapshot job and the client settle-reconcile composes stop EVICTING each other
559
+ // from a single slot — the cause of memo-hit=0 on a session with an active persistence job AND
560
+ // a viewer (prod 16864329 2026-07-22: 49 recomposes/2h, 0 memo hits, ~250 KB each). `durable`
561
+ // is already part of composedMemoKey, so a slot only ever reuses a same-durable payload;
562
+ // splitting slots changes hit rate, never correctness.
563
+ const composedMemoSlot = durable ? 'durable' : 'live';
564
+ const composedMemoStore = (session._codexComposedRespMemo && typeof session._codexComposedRespMemo === 'object')
565
+ ? session._codexComposedRespMemo : null;
566
+ const composedMemo = composedMemoStore ? composedMemoStore[composedMemoSlot] : null;
567
+ const staleRows = !!(rowBase && !rowBase.renderFresh);
568
+ const staleAlarm = _deps._observeCodexHistoryStaleRows(session, {
569
+ staleRows,
570
+ lookupId,
571
+ count: rowBase.count || 0,
572
+ state: rowBase.state || '',
573
+ cursorLagBytes: rowBase.cursorLagBytes || 0,
574
+ pendingEvents: rowBase.pendingEvents || 0,
575
+ parserVersion: rowBase.parserVersion || 0,
576
+ now: Date.now(),
577
+ thresholdMs: _deps.CODEX_HISTORY_ROWS_STALE_ALARM_MS,
578
+ });
579
+ if (staleAlarm) {
580
+ _deps.recordSessionDiagnostic(sessionId, 'codex-history-rows-stale-persistent', { agent: agentType, ...staleAlarm });
581
+ requestRowCursorRepublish(sessionId, lookupId);
582
+ }
583
+ if (_deps._decideCodexComposedMemoReuse({
584
+ enabled: _deps.RESUME_REPLAY_DEDUP_ENABLED,
585
+ memoKey: composedMemoKey,
586
+ lastMemoKey: composedMemo && composedMemo.key,
587
+ hasComposedPayload: !!(composedMemo && composedMemo.payload),
588
+ })) {
589
+ _deps.recordSessionDiagnostic(sessionId, 'codex-rollout-history-composed-memo-hit', {
590
+ agent: agentType,
591
+ cols,
592
+ bytes: composedMemo.payload.data ? composedMemo.payload.data.length : 0,
593
+ });
594
+ return { ...resp, ...composedMemo.payload };
595
+ }
596
+ const composed = _deps._composeCodexHistorySnapshot({
597
+ historyAnsi,
598
+ viewportAnsi: liveViewportData,
599
+ gridLines: gridSample.gridLines,
600
+ messageSpans,
601
+ settled,
602
+ gridStable: true, // agentType is guaranteed 'codex' here (claude compose retired, WP-5)
603
+ contentTrim: _deps.CTM_SEAM_CONTENT_TRIM_ENABLED,
604
+ durable,
605
+ opts: {
606
+ seam: true,
607
+ cols,
608
+ stale: staleRows,
609
+ // State-sync owns the live grid. Live snapshots restore H only; the
610
+ // restore-applied ACK resets the diff baseline and forces L over the
611
+ // visible history tail. Durable files still include the native viewport
612
+ // because no client/keyframe handshake exists while persisting.
613
+ frameOwnedViewport: !durable,
614
+ // Blank-viewport padding when the alt-screen live region is dropped (claude
615
+ // fullscreen): keeps history + seam in scrollback instead of letting the next
616
+ // keyframe paint the live screen over the history tail. Live sends only (the
617
+ // compose ignores padRows for durable persists).
618
+ padRows: Number(resp.rows) || Number(session._ptyRows) || 0,
619
+ },
620
+ });
621
+ if (!composed || !composed.data) return resp;
622
+ const terminalSurface = {
623
+ agent: agentType,
624
+ viewport: composed.droppedAltViewport
625
+ ? 'alt-screen'
626
+ : (composed.frameOwnedViewport ? 'frame-owned' : 'live'),
627
+ scrollback: {
628
+ witnessed: composed.witnessed,
629
+ recomposed: {
630
+ rows: Number(lineCount || 0),
631
+ cols,
632
+ bound: historyLineCap,
633
+ elided: historyElidedLines,
634
+ elidedMessages: historyElidedMessages,
635
+ parity: 'codex-tui',
636
+ stale: staleRows,
637
+ },
638
+ seam: {
639
+ present: !!(composed.seam && composed.seam.present),
640
+ text: (composed.seam && composed.seam.text) || '',
641
+ },
642
+ trimSkipReason: composed.trimSkipReason || '',
643
+ },
644
+ widths: {
645
+ pty: Number(resp.cols) || cols,
646
+ mirror: Number(resp.cols) || cols,
647
+ },
648
+ reason: opts && opts.reflow
649
+ ? (capPolicy.reflowWidthChanged ? 'width-change' : 'same-width-reflow')
650
+ : (opts && opts.deferMidTurn ? 'settle-reconcile' : (durable ? 'durable-persist' : 'settle-reconcile')),
651
+ };
652
+ _deps.recordSessionDiagnostic(sessionId, 'codex-rollout-history-composed', {
653
+ agent: agentType,
654
+ cols,
655
+ source,
656
+ cached: cacheHit,
657
+ reusedStaleRender: reusedStaleRender || undefined,
658
+ settled,
659
+ historyLines: lineCount,
660
+ historyLineCap,
661
+ reflow: isReflow || undefined,
662
+ reflowWidthChanged: capPolicy.reflowWidthChanged || undefined,
663
+ messages: msgCount,
664
+ rowMessages: rowMsgCount || undefined,
665
+ staleRows: rowBase && !rowBase.renderFresh || undefined,
666
+ capped: historyCapped,
667
+ bound: historyLineCap,
668
+ elidedLines: historyElidedLines || undefined,
669
+ elidedMessages: historyElidedMessages || undefined,
670
+ contentTrimmedLines: Number(composed.trimmed) || undefined,
671
+ trimSkipReason: composed.trimSkipReason || undefined,
672
+ fellBack,
673
+ displayMode,
674
+ terminalSurface,
675
+ bytes: composed.data.length,
676
+ // WP-0: worker-measured renderRolloutHistoryTail duration (undefined when this
677
+ // compose reused a durable/stale-tolerant render entry with no timing recorded).
678
+ renderMs,
679
+ // Codex gpt-5.5's full-screen (alt-screen) native viewport can't be inlined
680
+ // after the main-buffer history — the compose drops it and serves
681
+ // history-only so the browser doesn't switch to the alt buffer and hide the
682
+ // composer. Surface that so the "no input box" garble is diagnosable.
683
+ droppedAltViewport: composed.droppedAltViewport || undefined,
684
+ });
685
+ _deps.recordSessionDiagnostic(sessionId, 'terminal-surface-decision', terminalSurface);
686
+ session._lastCodexHistoryComposeCols = cols;
687
+ session._lastCodexHistoryComposeAt = Date.now();
688
+ // Report the full requested scrollback budget so cache-reuse matching treats
689
+ // this as a full-scrollback snapshot (the composed history covers it).
690
+ // Tag the result so the client applies H, acknowledges the restore, and lets
691
+ // the forced state-sync keyframe paint L. Interactive alt-screen composes do
692
+ // not carry frameOwnedViewport and remain owned by their native viewport.
693
+ const composedPayload = {
694
+ data: composed.data,
695
+ codexRolloutComposed: true,
696
+ frameOwnedViewport: !!composed.frameOwnedViewport,
697
+ terminalDisplayMode: displayMode,
698
+ terminalSurface,
699
+ renderProjection: {
700
+ surface: 'terminal',
701
+ displayMode,
702
+ source: 'codex-rollout-history',
703
+ terminalSurface,
704
+ },
705
+ scrollback: _deps.normalizeSnapshotScrollbackRows(session._snapshotScrollbackRows),
706
+ snapshotScrollbackFp: composed.snapshotScrollbackFp || undefined,
707
+ snapshotViewportOffset: Number(composed.snapshotViewportOffset || 0),
708
+ rendererVersion: _deps.CODEX_HISTORY_EFFECTIVE_RENDERER_VERSION,
709
+ composedAt: Date.now(),
710
+ _durableViewportData: durable ? liveViewportData : undefined,
711
+ };
712
+ // WI-9 step 2: stash for the next compose call on this session — see the memo-key check
713
+ // near the top of this function. Only meaningful while the flag is on; harmless dead weight
714
+ // otherwise (never read when RESUME_REPLAY_DEDUP_ENABLED is false).
715
+ if (!session._codexComposedRespMemo || typeof session._codexComposedRespMemo !== 'object') {
716
+ session._codexComposedRespMemo = {};
717
+ }
718
+ session._codexComposedRespMemo[composedMemoSlot] = { key: composedMemoKey, payload: composedPayload, createdAt: Date.now() };
719
+ return { ...resp, ...composedPayload };
720
+ } catch (e) {
721
+ _deps.recordSessionDiagnostic(sessionId, 'codex-rollout-history-compose-error', { error: e.message });
722
+ return resp;
723
+ }
724
+ }
725
+
726
+
727
+ module.exports = {
728
+ configure,
729
+ _codexRowCandidateIds,
730
+ _sessionHasFocusedViewer,
731
+ requestRowCursorRepublish,
732
+ _codexRowHistoryBase,
733
+ _matchingPublishedCodexRollout,
734
+ _transcriptHistoryProvider,
735
+ _codexRolloutHistoryActive,
736
+ _codexHistoryRenderCacheEntry,
737
+ _codexHistoryRenderNull,
738
+ _codexHistoryRenderInputForBase,
739
+ _runCodexHistoryRenderQueue,
740
+ _requestCodexHistoryRender,
741
+ _scheduleCodexHistoryRender,
742
+ _composeCodexRolloutResp,
743
+ };