mixdog 1.4.1 → 1.4.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 (630) hide show
  1. package/package.json +4 -3
  2. package/scripts/build-shipped-history.mjs +125 -33
  3. package/scripts/gate-local.mjs +220 -63
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +139 -32
  6. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  7. package/scripts/lib/run-node-tests.mjs +71 -34
  8. package/scripts/lib/scoped-temp.mjs +1 -0
  9. package/scripts/lib/test-failure-records.mjs +14 -1
  10. package/scripts/lib/test-failure-summary.mjs +9 -4
  11. package/scripts/lib/test-spawn-ledger.mjs +43 -3
  12. package/scripts/post-release-check.mjs +26 -16
  13. package/scripts/pptx-kit-index.mjs +5 -6
  14. package/scripts/provider-pingpong-live.mjs +1 -1
  15. package/scripts/prune-embedding-runtime.mjs +3 -1
  16. package/scripts/release-paths.mjs +7 -1
  17. package/scripts/suite-health.mjs +110 -28
  18. package/scripts/test.mjs +9 -14
  19. package/src/agents/advisor/AGENT.md +4 -4
  20. package/src/agents/advisor/agent.json +1 -1
  21. package/src/agents/explore/AGENT.md +22 -0
  22. package/src/agents/explore/agent.json +6 -0
  23. package/src/cli.mjs +7 -0
  24. package/src/defaults/agents.json +7 -0
  25. package/src/defaults/shipped-history.json +38 -2
  26. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  27. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  28. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  29. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  30. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  31. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  32. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  33. package/src/defaults/skills/setup/SKILL.md +2 -2
  34. package/src/defaults/skills/setup/references/actions.md +28 -9
  35. package/src/defaults/skills/setup/references/surfaces.md +5 -2
  36. package/src/defaults/skills/setup-guide/SKILL.md +11 -3
  37. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  38. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  39. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  40. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  41. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  42. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  43. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  44. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  45. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  46. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  47. package/src/defaults/skills/visualize/SKILL.md +6 -2
  48. package/src/lib/instruction-text.cjs +36 -0
  49. package/src/lib/rules-builder.cjs +40 -50
  50. package/src/orchestration/balanced.md +23 -0
  51. package/src/orchestration/focused.md +22 -0
  52. package/src/orchestration/none.md +5 -0
  53. package/src/orchestration/swarm.md +24 -0
  54. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  55. package/src/rules/agent-mode/MIXY.md +2 -2
  56. package/src/rules/lead/LEAD.md +3 -3
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/60-verification.md +10 -9
  60. package/src/rules/shared/70-delivery.md +4 -3
  61. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  62. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
  65. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
  66. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  69. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  71. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  72. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
  79. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  81. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  82. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  84. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
  85. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  86. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  90. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  91. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  92. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  96. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  98. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  99. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  103. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  104. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  105. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  107. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  113. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  116. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  118. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  119. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  120. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  121. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  122. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
  123. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  124. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
  125. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  126. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  127. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  129. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  130. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  131. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  132. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  133. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  134. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  136. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  137. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  138. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  139. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  140. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
  141. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  142. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  146. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  149. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  150. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  151. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  152. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  153. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  155. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  156. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  159. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  160. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  161. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
  162. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
  163. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
  164. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  165. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  166. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  167. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
  169. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  172. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  174. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  175. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  176. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  177. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  178. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  179. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  181. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  182. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
  183. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
  184. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  185. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  186. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  187. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  188. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
  189. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  190. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  191. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  192. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  193. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  194. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  195. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  196. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  197. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  198. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  199. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  200. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  201. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  202. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  203. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  204. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
  205. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
  206. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  207. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
  208. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  210. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
  211. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  212. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
  213. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  214. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  215. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  216. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
  217. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  218. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  219. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  220. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  221. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  222. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
  223. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  224. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  225. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  226. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
  227. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  228. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  229. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  230. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  231. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  232. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  233. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  234. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  235. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  236. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  237. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  238. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  239. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
  240. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  241. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  242. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  243. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  244. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  245. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  246. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  247. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  248. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  249. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  250. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  251. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  252. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  253. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  254. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
  255. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
  256. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  257. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  258. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  259. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  260. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  261. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  262. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
  263. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  264. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  265. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  266. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  267. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  269. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  270. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  271. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  272. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  273. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  274. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  275. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
  276. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  277. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  278. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  279. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
  280. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  281. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  282. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
  283. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  284. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  285. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  286. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  287. package/src/runtime/attachments/store.d.mts +1 -0
  288. package/src/runtime/attachments/store.mjs +2 -2
  289. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  290. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  291. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  292. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  293. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  294. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  295. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  296. package/src/runtime/channels/lib/whisper-server.mjs +22 -13
  297. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  298. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  299. package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
  300. package/src/runtime/connectors/gmail-app-password.mjs +4 -4
  301. package/src/runtime/connectors/google-mcp.mjs +1 -1
  302. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  303. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  304. package/src/runtime/explore/explorer.mjs +88 -0
  305. package/src/runtime/explore/tool-defs.mjs +35 -0
  306. package/src/runtime/explore/tool.mjs +123 -0
  307. package/src/runtime/local-provider/hardware.mjs +1 -1
  308. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  309. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  310. package/src/runtime/media/media-usage.mjs +1 -1
  311. package/src/runtime/media/store.mjs +1 -1
  312. package/src/runtime/memory/index.mjs +15 -1
  313. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  314. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  315. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  316. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  317. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  318. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  319. package/src/runtime/memory/lib/memory.mjs +17 -0
  320. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  321. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  322. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  323. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  324. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  325. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  326. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  327. package/src/runtime/office/capabilities.mjs +1 -1
  328. package/src/runtime/office/core/office-core.mjs +1 -1
  329. package/src/runtime/office/design/content-model.mjs +3 -3
  330. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  331. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  332. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  333. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  334. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  335. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  336. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  337. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  338. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  339. package/src/runtime/shared/agent-route-config.mjs +17 -2
  340. package/src/runtime/shared/atomic-file.d.mts +8 -0
  341. package/src/runtime/shared/atomic-file.mjs +103 -2
  342. package/src/runtime/shared/background-tasks.mjs +37 -10
  343. package/src/runtime/shared/background-wait.mjs +66 -0
  344. package/src/runtime/shared/child-guardian.mjs +17 -7
  345. package/src/runtime/shared/config.mjs +313 -16
  346. package/src/runtime/shared/connector-accounts.mjs +5 -5
  347. package/src/runtime/shared/connector-catalog.d.mts +14 -8
  348. package/src/runtime/shared/connector-catalog.mjs +70 -52
  349. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  350. package/src/runtime/shared/file-has-data.mjs +26 -2
  351. package/src/runtime/shared/file-lock.mjs +21 -18
  352. package/src/runtime/shared/git-launch.d.mts +9 -0
  353. package/src/runtime/shared/git-launch.mjs +213 -0
  354. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  355. package/src/runtime/shared/git-runner.mjs +7 -2
  356. package/src/runtime/shared/idle-gc.mjs +30 -7
  357. package/src/runtime/shared/llm/cost.mjs +6 -1
  358. package/src/runtime/shared/llm/http-agent.mjs +316 -29
  359. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  360. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  361. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  362. package/src/runtime/shared/llm/system-proxy.mjs +453 -0
  363. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  364. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  365. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  366. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  367. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  368. package/src/runtime/shared/process-runner.mjs +8 -4
  369. package/src/runtime/shared/provider-accounts.mjs +52 -2
  370. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  371. package/src/runtime/shared/routine-trigger.mjs +34 -0
  372. package/src/runtime/shared/run-child.d.mts +2 -1
  373. package/src/runtime/shared/run-child.mjs +70 -18
  374. package/src/runtime/shared/session-scratch.mjs +14 -2
  375. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  376. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  377. package/src/runtime/shared/staged-update.mjs +47 -2
  378. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  379. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  380. package/src/runtime/shared/tool-surface.mjs +110 -36
  381. package/src/runtime/shared/tool-work-units.mjs +35 -6
  382. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  383. package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
  384. package/src/runtime/shared/worker-requests.mjs +17 -3
  385. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  386. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  387. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  388. package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
  389. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  390. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  391. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  392. package/src/runtime/shared/worktrees/git.mjs +97 -7
  393. package/src/runtime/shared/worktrees/include.mjs +6 -4
  394. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  395. package/src/runtime/shared/worktrees/manager.mjs +962 -197
  396. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  397. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  398. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  399. package/src/runtime/tidy/install.mjs +95 -15
  400. package/src/runtime/tidy/languages.mjs +17 -15
  401. package/src/runtime/tidy/process.mjs +9 -5
  402. package/src/runtime/tidy/resolve.mjs +19 -16
  403. package/src/runtime/tidy/runners/biome.mjs +3 -3
  404. package/src/runtime/tidy/tool.mjs +1 -1
  405. package/src/runtime/tidy/worktree.mjs +10 -6
  406. package/src/runtime/visualize-bridge/client.mjs +4 -1
  407. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  408. package/src/runtime/web-search/index.mjs +4 -23
  409. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  410. package/src/runtime/web-search/tool-defs.mjs +17 -26
  411. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  412. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  413. package/src/session-runtime/boot/apis.mjs +27 -4
  414. package/src/session-runtime/boot/begin.mjs +2 -0
  415. package/src/session-runtime/boot/config.mjs +10 -1
  416. package/src/session-runtime/boot/facade.mjs +1 -0
  417. package/src/session-runtime/boot/providers.mjs +70 -3
  418. package/src/session-runtime/boot/session.mjs +2 -0
  419. package/src/session-runtime/boot/tools.mjs +71 -25
  420. package/src/session-runtime/bot-status.mjs +103 -103
  421. package/src/session-runtime/channel-config-api.mjs +1 -0
  422. package/src/session-runtime/config-change-effects.mjs +179 -0
  423. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  424. package/src/session-runtime/config-lifecycle.mjs +160 -24
  425. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  426. package/src/session-runtime/conversation-import/discovery.mjs +245 -47
  427. package/src/session-runtime/conversation-import/service.mjs +12 -5
  428. package/src/session-runtime/goal-facade-api.mjs +49 -3
  429. package/src/session-runtime/handoff-attachments.mjs +1 -1
  430. package/src/session-runtime/held-requests.mjs +3 -1
  431. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  432. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  433. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
  434. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  435. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
  436. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  437. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  438. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  439. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  440. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  441. package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
  442. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  443. package/src/session-runtime/lifecycle-api.mjs +1 -0
  444. package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
  445. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  446. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  447. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  448. package/src/session-runtime/model-route/set-route.mjs +40 -7
  449. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  450. package/src/session-runtime/provider-auth/login.mjs +2 -2
  451. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  452. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  453. package/src/session-runtime/provider-readiness.mjs +53 -4
  454. package/src/session-runtime/resource-api.mjs +1 -1
  455. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  456. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  457. package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
  458. package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
  459. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  460. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  461. package/src/session-runtime/routine-executor.mjs +152 -0
  462. package/src/session-runtime/routine-home-turn.mjs +46 -5
  463. package/src/session-runtime/runtime-facade.mjs +5 -0
  464. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  465. package/src/session-runtime/schedule-session-run.mjs +1 -0
  466. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  467. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  468. package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
  469. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  470. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  471. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  472. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
  473. package/src/session-runtime/services/agent-tool.mjs +51 -1
  474. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  475. package/src/session-runtime/services/channel-admin.mjs +18 -0
  476. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  477. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  478. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  479. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  480. package/src/session-runtime/services/plugin-admin.mjs +14 -6
  481. package/src/session-runtime/services/provider-admin.mjs +281 -10
  482. package/src/session-runtime/services/seeds.mjs +7 -0
  483. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  484. package/src/session-runtime/session-create/materialize.mjs +4 -2
  485. package/src/session-runtime/session-create/session-options.mjs +2 -0
  486. package/src/session-runtime/session-turn-api.mjs +2 -0
  487. package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
  488. package/src/session-runtime/settings-system-api.mjs +1 -1
  489. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  490. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  491. package/src/session-runtime/setup-tool/executor.mjs +14 -3
  492. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  493. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  494. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
  495. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  496. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  497. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  498. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  499. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  500. package/src/session-runtime/tool-surface.mjs +38 -1
  501. package/src/session-runtime/turn/agent-ops.mjs +33 -2
  502. package/src/session-runtime/turn/session-ops.mjs +2 -0
  503. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  504. package/src/session-runtime/turn/turn-run.mjs +1 -1
  505. package/src/session-runtime/webhook-session-run.mjs +2 -0
  506. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
  507. package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
  508. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  509. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  510. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  511. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  512. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  513. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  514. package/src/session-runtime/workspace/session-view.mjs +149 -0
  515. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  516. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  517. package/src/session-runtime/workspace/transitions.mjs +128 -1070
  518. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  519. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  520. package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
  521. package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
  522. package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
  523. package/src/standalone/daemon-agent-control.mjs +25 -8
  524. package/src/standalone/daemon-desktop-runtime.mjs +8 -2
  525. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  526. package/src/standalone/daemon-session-control.mjs +151 -136
  527. package/src/standalone/daemon.mjs +61 -2
  528. package/src/standalone/desktop-service-registry.mjs +9 -0
  529. package/src/standalone/local-session-runtime.mjs +21 -1
  530. package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
  531. package/src/standalone/session-client.mjs +5 -1
  532. package/src/standalone/session-frame-stream.mjs +83 -11
  533. package/src/standalone/session-protocol.mjs +15 -0
  534. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  535. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  536. package/src/standalone/session-service/agent-tree.mjs +45 -9
  537. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  538. package/src/standalone/session-service/quota-resume.mjs +9 -0
  539. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  540. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  541. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  542. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  543. package/src/standalone/session-service/session-calls.mjs +2 -1
  544. package/src/standalone/session-service/stored-reader.mjs +127 -40
  545. package/src/tui/App.jsx +162 -164
  546. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  547. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  548. package/src/tui/app/clipboard.mjs +22 -11
  549. package/src/tui/app/create-app-pickers.mjs +2 -0
  550. package/src/tui/app/doctor.mjs +2 -2
  551. package/src/tui/app/panel-signature.mjs +1 -1
  552. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  553. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  554. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  555. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  556. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  557. package/src/tui/app/provider-setup-picker.mjs +20 -13
  558. package/src/tui/app/settings-picker.mjs +53 -8
  559. package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
  560. package/src/tui/app/slash-commands.mjs +2 -1
  561. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  562. package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
  563. package/src/tui/app/slash-dispatch.mjs +1 -1
  564. package/src/tui/app/use-btw-panel.mjs +29 -0
  565. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  566. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  567. package/src/tui/app/use-mouse-input.mjs +11 -0
  568. package/src/tui/app/use-onboarding-start.mjs +8 -3
  569. package/src/tui/app/use-panel-transition.mjs +10 -1
  570. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  571. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  572. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  573. package/src/tui/app/use-prompt-queue-history.mjs +5 -4
  574. package/src/tui/app/use-selection-focus.mjs +11 -2
  575. package/src/tui/app/use-selection-geometry.mjs +18 -9
  576. package/src/tui/app/use-selection-paint.mjs +4 -4
  577. package/src/tui/app/use-selection-stitch.mjs +3 -3
  578. package/src/tui/app/use-slash-palette.mjs +62 -0
  579. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  580. package/src/tui/app/use-transcript-activity.mjs +48 -33
  581. package/src/tui/app/use-transcript-follow.mjs +12 -4
  582. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  583. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  584. package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
  585. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  586. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  587. package/src/tui/app/use-transcript-window.mjs +21 -11
  588. package/src/tui/app/use-tui-ready.mjs +18 -0
  589. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  590. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  591. package/src/tui/components/Picker.jsx +27 -3
  592. package/src/tui/components/SignInUrl.jsx +68 -0
  593. package/src/tui/components/TextEntryPanel.jsx +76 -46
  594. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  595. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  596. package/src/tui/components/question-panel-model.mjs +4 -4
  597. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  598. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  599. package/src/tui/components/user-message-skills.mjs +1 -1
  600. package/src/tui/dist/index.mjs +2205 -1371
  601. package/src/tui/markdown/render-ansi.mjs +1 -1
  602. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  603. package/src/tui/session/agent-job-feed.mjs +2 -0
  604. package/src/tui/session/context-state.mjs +3 -0
  605. package/src/tui/session/goal-turn-state.mjs +6 -2
  606. package/src/tui/session/quota-resume.mjs +1 -1
  607. package/src/tui/session/session-api/controls.mjs +4 -0
  608. package/src/tui/session/session-api/extensions.mjs +8 -0
  609. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  610. package/src/tui/session/session-api/intake.mjs +2 -0
  611. package/src/tui/session/session-api/integrations.mjs +2 -2
  612. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  613. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  614. package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
  615. package/src/tui/session/session-api/settings.mjs +2 -2
  616. package/src/tui/session/session-api/worktree.mjs +13 -1
  617. package/src/tui/session/session-flow/drain.mjs +11 -14
  618. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  619. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  620. package/src/tui/session/transcript-spill.mjs +92 -4
  621. package/src/tui/session/transcript-store.mjs +2 -0
  622. package/src/tui/session/turn-quiet.mjs +1 -1
  623. package/src/tui/session/turn.mjs +3 -0
  624. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  625. package/src/tui/spinner-meta.mjs +3 -3
  626. package/src/tui/spinner-verbs.mjs +2 -2
  627. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  628. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
  629. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  630. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -17,9 +17,9 @@
17
17
 
18
18
  import { createHash } from 'node:crypto';
19
19
 
20
- // Serialized (UTF-8 JSON) bytes of the retained PROJECTIONS. A tail-window
21
- // projection is ~0.1-1 MB; a legacy 512-item page of a worker transcript can
22
- // reach ~16 MB, so this keeps a couple of those or dozens of tail windows.
20
+ // Serialized (UTF-8 JSON) bytes of the retained PROJECTIONS: windows and pages
21
+ // sliced from a session's display history (which itself stays with the thread
22
+ // that built it); one larger than the whole budget is not retained.
23
23
  const STORED_TRANSCRIPT_CACHE_MAX_BYTES = 32 * 1024 * 1024;
24
24
  // Coarse filesystems stamp mtime at whole seconds (FAT: two). A write landing
25
25
  // inside that window after our read could keep the same stat, so only a file
@@ -70,22 +70,42 @@ export function nextProjectionStamp() {
70
70
  return `${stampEpoch}:${stampSequence}`;
71
71
  }
72
72
 
73
- export function createStoredTranscriptCache({
74
- // Bound retained content, not the number of small sessions. An eight-entry
75
- // LRU reparsed every unchanged record when nine visible sessions refreshed.
76
- maxEntries = Number.POSITIVE_INFINITY,
77
- maxBytes = STORED_TRANSCRIPT_CACHE_MAX_BYTES,
78
- maxIdleBytes = STORED_TRANSCRIPT_IDLE_MAX_BYTES,
79
- } = {}) {
73
+ const producedSlices = new WeakSet();
74
+ /** What a `produce` returns for a slice of a display history it may already
75
+ * hold: the value, its serialized `bytes` (measured by the producer) and
76
+ * whether a history was built for it (`historyBuilt`). */
77
+ export function producedSlice(value, { bytes = null, historyBuilt = true } = {}) {
78
+ const slice = { value, bytes, historyBuilt };
79
+ producedSlices.add(slice);
80
+ return slice;
81
+ }
82
+
83
+ /** This realm's stamp epoch (a worker composes history stamps with its
84
+ * caller's). */
85
+ export function projectionStampEpoch() {
86
+ return stampEpoch;
87
+ }
88
+
89
+ /** The identity of one display history: its session, record content and
90
+ * sidecar fingerprint, within one process epoch (a restart re-proves held
91
+ * rows by digest). Every slice of the history shares it, whichever thread
92
+ * built it and however often, so held rows stay proven across pages,
93
+ * evictions and worker restarts. */
94
+ export function historyStampOf(sessionId, textHash, textChars, fingerprint, epoch = stampEpoch) {
95
+ const id = createHash('sha256')
96
+ .update(`${sessionId}|${textHash}|${textChars}|${fingerprint}`)
97
+ .digest('base64url')
98
+ .slice(0, 22);
99
+ return `${epoch}:h${id}`;
100
+ }
101
+
102
+ /** The retained entries and their eviction policy: byte/entry budget, paging
103
+ * pins, ghost admission and idle trimming. */
104
+ function createEntryStore({ maxEntries, maxBytes, maxIdleBytes }) {
80
105
  // Retain a content digest, not a second full transcript beside its projection.
81
106
  // The bound is the size of what is actually retained: the projection.
82
107
  /** key -> { textHash, textChars, bytes, group, fingerprint, value, usedAt } (Map order is LRU order). */
83
108
  const entries = new Map();
84
- /** key -> { text, fingerprint, promise } for reads still parsing. */
85
- const inFlight = new Map();
86
- /** key -> { fingerprint, fileStat, promise } for reads not yet answered,
87
- * from before their body is loaded. */
88
- const reading = new Map();
89
109
  /** Keys evicted for space (insertion order = age), bounded. */
90
110
  const ghosts = new Set();
91
111
  let retainedBytes = 0;
@@ -104,8 +124,21 @@ export function createStoredTranscriptCache({
104
124
  };
105
125
  const overBudget = (extraEntries = 0, extraBytes = 0) =>
106
126
  entries.size + extraEntries > maxEntries || retainedBytes + extraBytes > maxBytes;
107
- const prune = () => {
108
- while (entries.size > 0 && overBudget()) evict(entries.keys().next().value);
127
+ // A history a reader is paging through (read with `pin` within
128
+ // ACTIVE_ENTRY_MS) stays cached under pressure: every page would otherwise
129
+ // build it again.
130
+ const paging = (entry, now) => now - entry.pinnedAt <= ACTIVE_ENTRY_MS;
131
+ // The newest entry stays (never larger than the budget: remember refuses
132
+ // those). For an unpinned newcomer, entries being paged are not evicted; a
133
+ // pinned one evicts whatever exceeds the budget, pinned or not.
134
+ const prune = (now, keepPaging) => {
135
+ const listed = [...entries];
136
+ const newest = listed.at(-1)?.[0];
137
+ for (const [key, entry] of listed) {
138
+ if (!overBudget()) return;
139
+ if (key === newest || (keepPaging && paging(entry, now))) continue;
140
+ evict(key);
141
+ }
109
142
  };
110
143
  // A returning ghost may displace only idle entries (oldest first).
111
144
  const makeRoomForGhost = (bytes, now) => {
@@ -123,25 +156,37 @@ export function createStoredTranscriptCache({
123
156
  for (const other of idle) evict(other);
124
157
  return true;
125
158
  };
126
- const remember = (key, group, textChars, textHash, fingerprint, fileStat, value, now) => {
159
+ const remember = (key, group, textChars, textHash, fingerprint, fileStat, value, now, pin, measured) => {
127
160
  drop(key);
128
161
  // One entry per group: a growing history window replaces its smaller
129
162
  // predecessor instead of accumulating beside it.
130
163
  if (group !== null) {
131
164
  for (const [other, entry] of [...entries]) if (entry.group === group) drop(other);
132
165
  }
133
- const bytes = Buffer.byteLength(JSON.stringify(value));
166
+ // Values are slices (a window or page), never a whole history; the
167
+ // producer's own measure is used when it has one.
168
+ const bytes = Number.isSafeInteger(measured) && measured >= 0 ? measured : Buffer.byteLength(JSON.stringify(value));
169
+ // Larger than the whole budget: served uncached, pinned or not.
134
170
  if (bytes > maxBytes) return;
135
- if (ghosts.has(key)) {
136
- if (!makeRoomForGhost(bytes, now)) return;
137
- ghosts.delete(key);
171
+ if (pin) ghosts.delete(key);
172
+ else {
173
+ if (ghosts.has(key)) {
174
+ if (!makeRoomForGhost(bytes, now)) return;
175
+ ghosts.delete(key);
176
+ }
177
+ // Never in place of a history being paged: served uncached instead.
178
+ let pagedBytes = 0;
179
+ for (const entry of entries.values()) if (paging(entry, now)) pagedBytes += entry.bytes;
180
+ if (pagedBytes > 0 && pagedBytes + bytes > maxBytes) return;
138
181
  }
139
- entries.set(key, { textChars, textHash, bytes, group, fingerprint, fileStat, value, usedAt: now });
182
+ const pinnedAt = pin ? now : Number.NEGATIVE_INFINITY;
183
+ entries.set(key, { textChars, textHash, bytes, group, fingerprint, fileStat, value, usedAt: now, pinnedAt });
140
184
  retainedBytes += bytes;
141
- prune();
185
+ prune(now, !pin);
142
186
  };
143
- const touch = (key, entry, now) => {
187
+ const touch = (key, entry, now, pin = false) => {
144
188
  entry.usedAt = now;
189
+ if (pin) entry.pinnedAt = now;
145
190
  entries.delete(key);
146
191
  entries.set(key, entry);
147
192
  };
@@ -168,14 +213,59 @@ export function createStoredTranscriptCache({
168
213
  : null;
169
214
  };
170
215
 
216
+ return {
217
+ get: (key) => entries.get(key),
218
+ remember,
219
+ touch,
220
+ trimIdle,
221
+ entryWithContent,
222
+ release(keyPrefix, now) {
223
+ for (const [key, entry] of entries) {
224
+ if (key.startsWith(keyPrefix)) entry.usedAt = Math.min(entry.usedAt, now - ACTIVE_ENTRY_MS - 1);
225
+ }
226
+ trimIdle(now);
227
+ },
228
+ forget(keyPrefix) {
229
+ for (const key of [...entries.keys()]) {
230
+ if (key.startsWith(keyPrefix)) drop(key);
231
+ }
232
+ for (const key of [...ghosts]) {
233
+ if (key.startsWith(keyPrefix)) ghosts.delete(key);
234
+ }
235
+ },
236
+ clear() {
237
+ entries.clear();
238
+ ghosts.clear();
239
+ retainedBytes = 0;
240
+ },
241
+ stats: () => ({ entries: entries.size, retainedBytes, ghosts: ghosts.size }),
242
+ };
243
+ }
244
+
245
+ export function createStoredTranscriptCache({
246
+ // Bound retained content, not the number of small sessions. An eight-entry
247
+ // LRU reparsed every unchanged record when nine visible sessions refreshed.
248
+ maxEntries = Number.POSITIVE_INFINITY,
249
+ maxBytes = STORED_TRANSCRIPT_CACHE_MAX_BYTES,
250
+ maxIdleBytes = STORED_TRANSCRIPT_IDLE_MAX_BYTES,
251
+ } = {}) {
252
+ const store = createEntryStore({ maxEntries, maxBytes, maxIdleBytes });
253
+ /** key -> { text, fingerprint, promise } for reads still parsing. */
254
+ const inFlight = new Map();
255
+ /** key -> { fingerprint, fileStat, promise } for reads not yet answered,
256
+ * from before their body is loaded. */
257
+ const reading = new Map();
258
+ // Projections produced (here or by `project`), cached or not.
259
+ let builds = 0;
260
+
171
261
  // `project(known)` reads, digests and projects the record elsewhere (a
172
262
  // worker thread) in one step: `{ textChars, textHash, value }`, or
173
263
  // `{ textChars, textHash, same: true }` without a projection when the
174
264
  // content is the `known` digest of the cached entry; null when the record
175
265
  // cannot be read. Undefined when it could not answer at all.
176
- async function readProjected({ key, group, fingerprint, fileStat, project, now }) {
266
+ async function readProjected({ key, group, fingerprint, fileStat, project, now, pin }) {
177
267
  for (let attempt = 0; attempt < 2; attempt += 1) {
178
- const cached = entries.get(key);
268
+ const cached = store.get(key);
179
269
  const known =
180
270
  attempt === 0 && cached?.fingerprint === fingerprint
181
271
  ? { textChars: cached.textChars, textHash: cached.textHash }
@@ -195,38 +285,52 @@ export function createStoredTranscriptCache({
195
285
  if (answer === undefined) return undefined;
196
286
  if (answer === null || typeof answer !== 'object') return { value: null, hit: false, read: true };
197
287
  if (answer.same === true) {
198
- const entry = entryWithContent(key, fingerprint, answer);
288
+ const entry = store.entryWithContent(key, fingerprint, answer);
199
289
  // Evicted meanwhile: project it after all.
200
290
  if (!entry) continue;
201
291
  entry.fileStat = fileStat;
202
- touch(key, entry, now);
292
+ store.touch(key, entry, now, pin);
203
293
  return { value: entry.value, hit: true, read: true };
204
294
  }
205
295
  const value = answer.value ?? null;
296
+ // A worker that served the slice from a history it already held built nothing.
297
+ const built = Boolean(value && typeof value === 'object' && answer.historyBuilt !== false);
298
+ if (built) builds += 1;
206
299
  if (current && value && typeof value === 'object') {
207
- remember(key, group, answer.textChars, answer.textHash, fingerprint, fileStat, value, now);
300
+ store.remember(
301
+ key,
302
+ group,
303
+ answer.textChars,
304
+ answer.textHash,
305
+ fingerprint,
306
+ fileStat,
307
+ value,
308
+ now,
309
+ pin,
310
+ answer.bytes
311
+ );
208
312
  }
209
- return { value, hit: false, read: true };
313
+ return { value, hit: false, read: true, built };
210
314
  }
211
315
  return undefined;
212
316
  }
213
317
 
214
- async function readFresh({ key, group, fingerprint, fileStat, loadText, produce, project, now }) {
318
+ async function readFresh({ key, group, fingerprint, fileStat, loadText, produce, project, now, pin }) {
215
319
  if (typeof project === 'function') {
216
- const answered = await readProjected({ key, group, fingerprint, fileStat, project, now });
320
+ const answered = await readProjected({ key, group, fingerprint, fileStat, project, now, pin });
217
321
  if (answered !== undefined) return answered;
218
322
  // It could not answer (worker unavailable): load and produce here.
219
323
  }
220
- const cached = entries.get(key);
324
+ const cached = store.get(key);
221
325
  // `loadText` may answer asynchronously (a large record is read without
222
326
  // blocking the loop); a plain string is unchanged.
223
327
  let text = loadText();
224
328
  if (typeof text?.then === 'function') text = await text;
225
329
  if (typeof text !== 'string') return { value: null, hit: false, read: true };
226
330
  const textHash = transcriptTextHash(text);
227
- if (cached && entryWithContent(key, fingerprint, { textChars: text.length, textHash }) === cached) {
331
+ if (cached && store.entryWithContent(key, fingerprint, { textChars: text.length, textHash }) === cached) {
228
332
  cached.fileStat = fileStat;
229
- touch(key, cached, now);
333
+ store.touch(key, cached, now, pin);
230
334
  return { value: cached.value, hit: true, read: true };
231
335
  }
232
336
  const pending = inFlight.get(key);
@@ -234,17 +338,23 @@ export function createStoredTranscriptCache({
234
338
  return { value: await pending.promise, hit: true, read: true };
235
339
  }
236
340
  const record = { text, fingerprint, promise: null };
341
+ let built = false;
237
342
  const promise = (async () => {
238
- const value = await produce(text);
343
+ const produced = await produce(text);
344
+ const slice = producedSlices.has(produced) ? produced : null;
345
+ const value = slice ? slice.value : produced;
346
+ built = Boolean(value && typeof value === 'object' && slice?.historyBuilt !== false);
347
+ if (built) builds += 1;
239
348
  if (inFlight.get(key) === record && value && typeof value === 'object') {
240
- remember(key, group, text.length, textHash, fingerprint, fileStat, value, now);
349
+ store.remember(key, group, text.length, textHash, fingerprint, fileStat, value, now, pin, slice?.bytes);
241
350
  }
242
351
  return value;
243
352
  })();
244
353
  record.promise = promise;
245
354
  inFlight.set(key, record);
246
355
  try {
247
- return { value: await promise, hit: false, read: true };
356
+ const value = await promise;
357
+ return { value, hit: false, read: true, built };
248
358
  } finally {
249
359
  if (inFlight.get(key) === record) inFlight.delete(key);
250
360
  }
@@ -256,7 +366,9 @@ export function createStoredTranscriptCache({
256
366
  * `project` run only when stat alone cannot vouch for the entry.
257
367
  * Concurrent callers with the same content share one parse; callers of
258
368
  * one unchanged, settled file share one read before it is even loaded.
259
- * Entries naming the same `group` replace each other. */
369
+ * Entries naming the same `group` replace each other. `pin`: a reader is
370
+ * paging through this entry — it is cached however full the cache is,
371
+ * and for ACTIVE_ENTRY_MS no unpinned newcomer evicts it. */
260
372
  async read({
261
373
  key,
262
374
  group = null,
@@ -266,11 +378,12 @@ export function createStoredTranscriptCache({
266
378
  produce,
267
379
  project = null,
268
380
  now = Date.now(),
381
+ pin = false,
269
382
  }) {
270
- trimIdle(now);
271
- const cached = entries.get(key);
383
+ store.trimIdle(now);
384
+ const cached = store.get(key);
272
385
  if (cached && cached.fingerprint === fingerprint && settledSameFile(cached.fileStat, fileStat, now)) {
273
- touch(key, cached, now);
386
+ store.touch(key, cached, now, pin);
274
387
  return { value: cached.value, hit: true, read: false };
275
388
  }
276
389
  const joined = reading.get(key);
@@ -280,7 +393,7 @@ export function createStoredTranscriptCache({
280
393
  if (value) return { value, hit: true, read: false };
281
394
  }
282
395
  const record = { fingerprint, fileStat, promise: null };
283
- record.promise = readFresh({ key, group, fingerprint, fileStat, loadText, produce, project, now });
396
+ record.promise = readFresh({ key, group, fingerprint, fileStat, loadText, produce, project, now, pin });
284
397
  reading.set(key, record);
285
398
  try {
286
399
  return await record.promise;
@@ -291,10 +404,7 @@ export function createStoredTranscriptCache({
291
404
  /** The last view of these projections left: they turn idle now and stay
292
405
  * only within the idle budget, ready for a revisit. */
293
406
  release(keyPrefix, now = Date.now()) {
294
- for (const [key, entry] of entries) {
295
- if (key.startsWith(keyPrefix)) entry.usedAt = Math.min(entry.usedAt, now - ACTIVE_ENTRY_MS - 1);
296
- }
297
- trimIdle(now);
407
+ store.release(keyPrefix, now);
298
408
  },
299
409
  forget(keyPrefix) {
300
410
  for (const pending of [inFlight, reading]) {
@@ -302,28 +412,17 @@ export function createStoredTranscriptCache({
302
412
  if (key.startsWith(keyPrefix)) pending.delete(key);
303
413
  }
304
414
  }
305
- for (const key of [...entries.keys()]) {
306
- if (key.startsWith(keyPrefix)) drop(key);
307
- }
308
- for (const key of [...ghosts]) {
309
- if (key.startsWith(keyPrefix)) ghosts.delete(key);
310
- }
415
+ store.forget(keyPrefix);
311
416
  },
312
417
  clear() {
313
- entries.clear();
418
+ store.clear();
314
419
  inFlight.clear();
315
420
  reading.clear();
316
- ghosts.clear();
317
- retainedBytes = 0;
421
+ builds = 0;
318
422
  },
319
423
  stats() {
320
- return {
321
- entries: entries.size,
322
- retainedBytes,
323
- inFlight: inFlight.size,
324
- reading: reading.size,
325
- ghosts: ghosts.size,
326
- };
424
+ const { entries, retainedBytes, ghosts } = store.stats();
425
+ return { entries, retainedBytes, inFlight: inFlight.size, reading: reading.size, ghosts, builds };
327
426
  },
328
427
  };
329
428
  }
@@ -15,6 +15,7 @@ import { join } from 'node:path';
15
15
  import { desktopSession, positiveNumber } from './store-summary-fields.mjs';
16
16
  import { compactionArchiveRange, readCompactionArchivePage } from './compaction-archive.mjs';
17
17
  import { dataDir } from './store-summary-locations.mjs';
18
+ import { todoSnapshot } from '../runtime-core/todo-list.mjs';
18
19
 
19
20
  /** The parse/recovery/projection body of a stored transcript read. Runs once
20
21
  * per distinct content; its result is shared read-only through the cache. */
@@ -40,7 +41,9 @@ export async function prepareStoredTranscriptBase(sessionId, doc, options) {
40
41
  // A running turn is never recovered: project its checkpoint read-only.
41
42
  if (isSessionTurnLive(sessionId)) projectCheckpoint();
42
43
  else {
43
- session = recoverSessionAfterProcessRestart(sessionId) || session;
44
+ // `doc` is the record exactly as this read parsed it from disk: the
45
+ // durable evidence recovery decides on.
46
+ session = recoverSessionAfterProcessRestart(sessionId, doc) || session;
44
47
  // A closed session keeps its marker unrecovered.
45
48
  if (session?.activeTurnCheckpoint) projectCheckpoint();
46
49
  }
@@ -78,9 +81,10 @@ export async function prepareStoredTranscriptBase(sessionId, doc, options) {
78
81
  }
79
82
  const messages = Array.isArray(session.messages) ? session.messages : [];
80
83
  const hasConversationActivity = messages.some((message) => message?.role === 'user');
81
- const measuredStats = contextMeasurementStats({
82
- measurement: sessionContextMeasurement(session, hasConversationActivity),
83
- });
84
+ const measuredStats = {
85
+ ...contextMeasurementStats({ measurement: sessionContextMeasurement(session, hasConversationActivity) }),
86
+ usageReadout: session.usageReadout || null,
87
+ };
84
88
  const contextWindow = positiveNumber(session.contextWindow);
85
89
  const rawContextWindow = positiveNumber(session.rawContextWindow, contextWindow);
86
90
  const displayContextWindow = positiveNumber(session.compactBoundaryTokens, contextWindow);
@@ -107,27 +111,186 @@ export async function prepareStoredTranscriptBase(sessionId, doc, options) {
107
111
  };
108
112
  }
109
113
 
110
- /** One transcript window (`options.itemLimit`, default whole) of a base. */
114
+ /** The digest a paged caller proves its held rows with: over their wire form,
115
+ * as the caller serializes them. */
116
+ export async function heldRowsDigester() {
117
+ const [{ sanitizeForWire }, { transcriptItemsDigest }] = await Promise.all([
118
+ import('../../../../standalone/session-wire-values.mjs'),
119
+ import('../../../../standalone/session-state-patch.mjs'),
120
+ ]);
121
+ return (rows) => transcriptItemsDigest(rows.map((row) => sanitizeForWire(row, 2) ?? null));
122
+ }
123
+
124
+ /** The rows a page reveals never go below this many whatever their size, so
125
+ * paging always progresses (the caller's own floor). */
126
+ const PAGE_MIN_ROWS = 8;
127
+
128
+ /** The slice of a whole display history (windowStoredTranscript with
129
+ * `history`) one read receives (`request`):
130
+ * - `held` (`{ firstId, count, digest }`, the newest rows a paged caller
131
+ * holds): when the history's newest `held.count` rows are those rows (same
132
+ * first id and — unless `proven` — the same `digestOf` digest), only the
133
+ * rows above them: at most `maxRows` (and `limit - held.count`) within
134
+ * `byteBudget` (`rowBytes(index)`), never fewer than PAGE_MIN_ROWS, with
135
+ * `heldProven`. Unproven: a tail of at most `maxRows` rows instead
136
+ * (`heldProven: false`).
137
+ * - otherwise its newest `limit` rows but the newest `skip` (with
138
+ * `skippedFirstId`, the oldest skipped row) — or, without a finite limit
139
+ * (the legacy whole read), every restored row and none of the compaction
140
+ * archive.
141
+ * `windowStamp` names the slice within the history (the caller composes the
142
+ * projection stamp). Slicing only: whatever the depth, a slice carries only
143
+ * its own rows, and the history never leaves the thread that built it. */
144
+ export function storedHistorySlice(history, request = {}, { digestOf = null, rowBytes = null } = {}) {
145
+ if (!history || typeof history !== 'object' || !Array.isArray(history.items)) return history;
146
+ const { transcriptArchivedRows: archivedRows = 0, items, projectionStamp: _stamp, ...fields } = history;
147
+ const sizeOf =
148
+ typeof rowBytes === 'function' ? rowBytes : (index) => Buffer.byteLength(JSON.stringify(items[index] ?? null));
149
+ if (request.cursor) return historyCursorSlice(fields, items, request.cursor, history.transcriptHasOlder, sizeOf);
150
+ const itemLimit = Number(request.limit);
151
+ if (!Number.isFinite(itemLimit)) {
152
+ return {
153
+ ...fields,
154
+ windowStamp: 'whole',
155
+ items: archivedRows > 0 ? items.slice(archivedRows) : items.slice(),
156
+ transcriptHasOlder: false,
157
+ };
158
+ }
159
+ const limit = Math.max(0, Math.floor(itemLimit));
160
+ const held = request.held;
161
+ if (held) {
162
+ const maxRows = Math.max(1, Math.floor(Number(request.maxRows) || limit));
163
+ const end = items.length - held.count;
164
+ const holds =
165
+ end >= 0 &&
166
+ items[end]?.id === held.firstId &&
167
+ (request.proven === true || (typeof digestOf === 'function' && digestOf(items.slice(end)) === held.digest));
168
+ if (!holds) {
169
+ // A fresh tail of one answer, within the same byte budget (and floor).
170
+ const start = budgetedEdge(items.length, -1, items.length, Math.min(limit, maxRows), request.byteBudget, sizeOf);
171
+ return {
172
+ ...fields,
173
+ windowStamp: `${items.length - start}`,
174
+ items: items.slice(start),
175
+ transcriptHasOlder: start > 0 || history.transcriptHasOlder === true,
176
+ heldProven: false,
177
+ };
178
+ }
179
+ const rows = Math.max(0, Math.min(maxRows, limit - held.count));
180
+ const start = budgetedEdge(end, -1, items.length, rows, request.byteBudget, sizeOf);
181
+ return {
182
+ ...fields,
183
+ windowStamp: `${items.length - start}@${held.count}`,
184
+ items: items.slice(start, end),
185
+ transcriptHasOlder: start > 0 || history.transcriptHasOlder === true,
186
+ skippedFirstId: held.firstId,
187
+ heldProven: true,
188
+ };
189
+ }
190
+ const skipped = Math.max(0, Math.min(Math.floor(Number(request.skip) || 0), limit, items.length));
191
+ const end = items.length - skipped;
192
+ const start = Math.max(0, items.length - limit);
193
+ return {
194
+ ...fields,
195
+ windowStamp: skipped ? `${limit}@${skipped}` : `${limit}`,
196
+ items: items.slice(start, end),
197
+ transcriptHasOlder: start > 0 || history.transcriptHasOlder === true,
198
+ ...(skipped ? { skippedFirstId: items[end]?.id ?? null } : {}),
199
+ };
200
+ }
201
+
202
+ /** The far edge of a run of at most `rows` rows within `byteBudget`
203
+ * (`sizeOf(index)`), never fewer than PAGE_MIN_ROWS whatever their size:
204
+ * older (`step` -1) ending just before index `from`, or newer (`step` +1)
205
+ * starting at it. */
206
+ function budgetedEdge(from, step, length, rows, byteBudget, sizeOf) {
207
+ const budget = Number(byteBudget) > 0 ? Number(byteBudget) : null;
208
+ const floor = Math.min(rows, PAGE_MIN_ROWS);
209
+ let edge = from;
210
+ let taken = 0;
211
+ let bytes = 0;
212
+ while (taken < rows) {
213
+ const index = step < 0 ? edge - 1 : edge;
214
+ if (index < 0 || index >= length) break;
215
+ const next = budget ? sizeOf(index) : 0;
216
+ if (budget && taken >= floor && bytes + next > budget) break;
217
+ bytes += next;
218
+ taken += 1;
219
+ edge += step;
220
+ }
221
+ return edge;
222
+ }
223
+
224
+ /** The most rows one historical-position read carries, whatever it asks. */
225
+ const CURSOR_PAGE_MAX_ROWS = 512;
226
+
227
+ /** A cursor's page size: 1 to CURSOR_PAGE_MAX_ROWS rows. */
228
+ export function cursorPageRows(maxRows) {
229
+ return Math.min(CURSOR_PAGE_MAX_ROWS, Math.max(1, Math.floor(Number(maxRows) || 1)));
230
+ }
231
+
232
+ /** A historical-position read (`cursor`: `{ before | after, maxRows,
233
+ * byteBudget }`): the rows directly older than row `before`, or newer than
234
+ * row `after`, at most `maxRows` within `byteBudget` (PAGE_MIN_ROWS floor),
235
+ * with whether rows remain past them each way. Rows are located by their
236
+ * stable id, so a page stays valid while the history only grows; a row the
237
+ * history no longer holds (compaction, rewind, clear) answers
238
+ * `cursorMissing`. */
239
+ function historyCursorSlice(fields, items, cursor, olderBeyond, sizeOf) {
240
+ const older = cursor.before != null;
241
+ const id = older ? cursor.before : cursor.after;
242
+ const at = items.findIndex((item) => item?.id === id);
243
+ if (at < 0) return { ...fields, windowStamp: 'cursor', items: [], cursorMissing: true };
244
+ const rows = cursorPageRows(cursor.maxRows);
245
+ if (older) {
246
+ const start = budgetedEdge(at, -1, items.length, rows, cursor.byteBudget, sizeOf);
247
+ return {
248
+ ...fields,
249
+ windowStamp: 'cursor',
250
+ items: items.slice(start, at),
251
+ transcriptHasOlder: start > 0 || olderBeyond === true,
252
+ transcriptHasNewer: true,
253
+ };
254
+ }
255
+ const end = budgetedEdge(at + 1, 1, items.length, rows, cursor.byteBudget, sizeOf);
256
+ return {
257
+ ...fields,
258
+ windowStamp: 'cursor',
259
+ items: items.slice(at + 1, end),
260
+ transcriptHasOlder: true,
261
+ transcriptHasNewer: end < items.length,
262
+ };
263
+ }
264
+
265
+ /** One transcript window (`options.itemLimit`, default whole) of a base.
266
+ * `options.history`: the whole display history instead — every restored row
267
+ * after every row of the visible compaction archive, with
268
+ * `transcriptArchivedRows` naming how many lead it. Every window is a tail
269
+ * of it (storedHistoryWindow). */
111
270
  export async function windowStoredTranscript(sessionId, base, options) {
112
271
  const { session, messages, contextFields } = base;
113
272
  const { restoreTranscriptItems } = await import('./transcript-restore/restore.mjs');
273
+ const history = options.history === true;
114
274
  // Restoring one item past a finite limit proves whether older history exists
115
275
  // without projecting it; restore ids are message-positional, so the kept
116
276
  // tail is identical either way.
117
- const itemLimit = Number.isFinite(options.itemLimit) ? options.itemLimit : Number.POSITIVE_INFINITY;
277
+ const itemLimit = !history && Number.isFinite(options.itemLimit) ? options.itemLimit : Number.POSITIVE_INFINITY;
118
278
  const restored = restoreTranscriptItems(messages, { sessionId, itemLimit: itemLimit + 1 });
119
279
  let transcriptHasOlder = restored.length > itemLimit;
120
280
  let items = transcriptHasOlder ? restored.slice(-itemLimit) : restored;
281
+ let archivedRows = 0;
121
282
  // A paged window continues past the first stored message into the
122
283
  // display-only compaction archive (newest segment first). A legacy whole
123
284
  // read never receives it.
124
- const archiveRange = Number.isFinite(itemLimit) && !transcriptHasOlder ? compactionArchiveRange(session) : null;
285
+ const archiveRange =
286
+ history || (Number.isFinite(itemLimit) && !transcriptHasOlder) ? compactionArchiveRange(session) : null;
125
287
  if (archiveRange) {
126
288
  const archived = await readCompactionArchivePage(join(dataDir(), 'sessions'), sessionId, {
127
289
  ...archiveRange,
128
- limit: itemLimit - restored.length,
290
+ limit: history ? Number.POSITIVE_INFINITY : itemLimit - restored.length,
129
291
  });
130
292
  if (archived.items.length) items = [...archived.items, ...restored];
293
+ archivedRows = archived.items.length;
131
294
  transcriptHasOlder = archived.hasOlder;
132
295
  }
133
296
  return {
@@ -136,6 +299,7 @@ export async function windowStoredTranscript(sessionId, base, options) {
136
299
  ...(options.includeMessages ? { messages } : {}),
137
300
  items,
138
301
  transcriptHasOlder,
302
+ ...(history ? { transcriptArchivedRows: archivedRows } : {}),
139
303
  provider: session.provider || '',
140
304
  model: session.model || '',
141
305
  effort: session.effort || '',
@@ -145,6 +309,11 @@ export async function windowStoredTranscript(sessionId, base, options) {
145
309
  cwd: session.cwd || '',
146
310
  desktopSession: desktopSession(session.desktopSession, session.cwd),
147
311
  workflow: session.workflow || null,
312
+ todo: todoSnapshot(session),
313
+ // Turns whose checkpoints recovery could not apply, kept on disk.
314
+ ...(Array.isArray(session.unrecoveredTurns) && session.unrecoveredTurns.length
315
+ ? { unrecoveredTurns: session.unrecoveredTurns }
316
+ : {}),
148
317
  ...contextFields,
149
318
  };
150
319
  }