mixdog 1.4.1 → 1.4.2

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 (326) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-shipped-history.mjs +115 -33
  3. package/scripts/gate-local.mjs +172 -61
  4. package/scripts/lib/gate-scheduler.mjs +138 -32
  5. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  6. package/scripts/lib/run-node-tests.mjs +54 -29
  7. package/scripts/lib/scoped-temp.mjs +1 -0
  8. package/scripts/lib/test-failure-records.mjs +14 -1
  9. package/scripts/lib/test-failure-summary.mjs +16 -4
  10. package/scripts/lib/test-spawn-ledger.mjs +12 -3
  11. package/scripts/pptx-kit-index.mjs +5 -6
  12. package/scripts/suite-health.mjs +110 -28
  13. package/scripts/test.mjs +9 -14
  14. package/src/agents/advisor/AGENT.md +4 -4
  15. package/src/agents/advisor/agent.json +1 -1
  16. package/src/agents/explore/AGENT.md +22 -0
  17. package/src/agents/explore/agent.json +6 -0
  18. package/src/cli.mjs +7 -0
  19. package/src/defaults/agents.json +7 -0
  20. package/src/defaults/shipped-history.json +18 -2
  21. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  22. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  23. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  24. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  25. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  26. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  27. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  28. package/src/defaults/skills/goal-management/SKILL.md +1 -1
  29. package/src/defaults/skills/setup/references/actions.md +12 -6
  30. package/src/defaults/skills/setup/references/surfaces.md +2 -2
  31. package/src/defaults/skills/setup-guide/SKILL.md +5 -2
  32. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  33. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  34. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  35. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  36. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  37. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  38. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  39. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  40. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  41. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  42. package/src/defaults/skills/visualize/SKILL.md +6 -2
  43. package/src/lib/rules-builder.cjs +6 -30
  44. package/src/rules/lead/LEAD.md +3 -3
  45. package/src/rules/shared/20-research.md +3 -6
  46. package/src/rules/shared/40-editing.md +1 -0
  47. package/src/rules/shared/60-verification.md +10 -9
  48. package/src/rules/shared/70-delivery.md +4 -3
  49. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  50. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
  51. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +130 -21
  52. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
  53. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  54. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  55. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  56. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
  57. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  58. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
  59. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
  60. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
  61. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
  62. package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
  63. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  64. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
  65. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  66. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  67. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  69. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  70. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  71. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  72. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  73. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  74. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  75. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  76. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  77. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  78. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  79. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  80. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  81. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  82. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  83. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  84. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  85. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  86. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  88. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  89. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  90. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  91. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  92. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  93. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  94. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  95. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  96. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
  97. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  98. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +2 -1
  99. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  100. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -0
  101. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
  102. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  103. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  104. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  105. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  106. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +3 -3
  107. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +10 -5
  108. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +5 -5
  109. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  110. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  111. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
  112. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  113. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +21 -2
  114. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
  115. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  116. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  117. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
  118. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
  119. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +3 -4
  120. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  121. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
  122. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  123. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +25 -14
  124. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +17 -14
  125. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  126. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  127. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -3
  128. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +47 -29
  129. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  130. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
  131. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  132. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  133. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  134. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
  135. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  136. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  137. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +36 -26
  138. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +3 -5
  139. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  140. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  141. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
  142. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  143. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  144. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  145. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  146. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
  147. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  148. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  149. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  150. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
  151. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  152. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  153. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
  154. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  155. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  156. package/src/runtime/channels/lib/whisper-server.mjs +10 -1
  157. package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
  158. package/src/runtime/connectors/gmail-app-password.mjs +3 -3
  159. package/src/runtime/explore/explorer.mjs +93 -0
  160. package/src/runtime/explore/tool-defs.mjs +35 -0
  161. package/src/runtime/explore/tool.mjs +123 -0
  162. package/src/runtime/memory/index.mjs +4 -0
  163. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  164. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  165. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  166. package/src/runtime/shared/agent-route-config.mjs +17 -2
  167. package/src/runtime/shared/atomic-file.mjs +103 -2
  168. package/src/runtime/shared/background-tasks.mjs +15 -6
  169. package/src/runtime/shared/connector-accounts.mjs +5 -5
  170. package/src/runtime/shared/connector-catalog.d.mts +11 -4
  171. package/src/runtime/shared/connector-catalog.mjs +60 -52
  172. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  173. package/src/runtime/shared/file-has-data.mjs +26 -2
  174. package/src/runtime/shared/file-lock.mjs +13 -15
  175. package/src/runtime/shared/git-launch.d.mts +9 -0
  176. package/src/runtime/shared/git-launch.mjs +213 -0
  177. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  178. package/src/runtime/shared/llm/cost.mjs +6 -1
  179. package/src/runtime/shared/llm/http-agent.mjs +313 -29
  180. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  181. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  182. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  183. package/src/runtime/shared/llm/system-proxy.mjs +452 -0
  184. package/src/runtime/shared/provider-accounts.mjs +52 -2
  185. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  186. package/src/runtime/shared/staged-update.mjs +47 -2
  187. package/src/runtime/shared/tool-surface.mjs +110 -36
  188. package/src/runtime/shared/tool-work-units.mjs +4 -0
  189. package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
  190. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  191. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  192. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  193. package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
  194. package/src/runtime/shared/worktrees/git.mjs +57 -0
  195. package/src/runtime/shared/worktrees/manager.mjs +205 -137
  196. package/src/runtime/tidy/install.mjs +95 -15
  197. package/src/runtime/tidy/languages.mjs +17 -15
  198. package/src/runtime/tidy/process.mjs +7 -4
  199. package/src/runtime/tidy/resolve.mjs +19 -16
  200. package/src/runtime/tidy/runners/biome.mjs +3 -3
  201. package/src/runtime/tidy/tool.mjs +1 -1
  202. package/src/runtime/tidy/worktree.mjs +10 -6
  203. package/src/runtime/visualize-bridge/client.mjs +4 -1
  204. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  205. package/src/runtime/web-search/index.mjs +1 -1
  206. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  207. package/src/session-runtime/boot/tools.mjs +2 -0
  208. package/src/session-runtime/bot-status.mjs +103 -103
  209. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  210. package/src/session-runtime/conversation-import/discovery.mjs +159 -40
  211. package/src/session-runtime/conversation-import/service.mjs +9 -3
  212. package/src/session-runtime/handoff-attachments.mjs +1 -1
  213. package/src/session-runtime/held-requests.mjs +3 -1
  214. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
  215. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  216. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +143 -116
  217. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
  218. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  219. package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
  220. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  221. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  222. package/src/session-runtime/provider-auth/login.mjs +2 -2
  223. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  224. package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
  225. package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
  226. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  227. package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
  228. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  229. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
  230. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  231. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  232. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  233. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  234. package/src/session-runtime/services/plugin-admin.mjs +10 -6
  235. package/src/session-runtime/services/provider-admin.mjs +281 -10
  236. package/src/session-runtime/session-turn-api.mjs +2 -0
  237. package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
  238. package/src/session-runtime/settings-system-api.mjs +1 -1
  239. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  240. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  241. package/src/session-runtime/setup-tool/executor.mjs +6 -2
  242. package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
  243. package/src/session-runtime/turn/agent-ops.mjs +23 -0
  244. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
  245. package/src/session-runtime/workflow-agents-api/agent-route.mjs +10 -1
  246. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  247. package/src/session-runtime/workspace/session-view.mjs +149 -0
  248. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  249. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  250. package/src/session-runtime/workspace/transitions.mjs +108 -1066
  251. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  252. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  253. package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
  254. package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
  255. package/src/session-runtime/workspace/worktree-tool.mjs +54 -54
  256. package/src/standalone/daemon-desktop-runtime.mjs +2 -0
  257. package/src/standalone/daemon-session-control.mjs +151 -136
  258. package/src/standalone/daemon.mjs +7 -0
  259. package/src/standalone/desktop-service-registry.mjs +9 -0
  260. package/src/standalone/local-session-runtime.mjs +5 -1
  261. package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
  262. package/src/standalone/session-client.mjs +5 -1
  263. package/src/standalone/session-frame-stream.mjs +83 -11
  264. package/src/standalone/session-protocol.mjs +4 -0
  265. package/src/standalone/session-service/agent-tree.mjs +45 -9
  266. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  267. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  268. package/src/standalone/session-service/stored-reader.mjs +127 -40
  269. package/src/tui/App.jsx +154 -164
  270. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  271. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  272. package/src/tui/app/clipboard.mjs +21 -10
  273. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  274. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  275. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  276. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  277. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  278. package/src/tui/app/provider-setup-picker.mjs +20 -13
  279. package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
  280. package/src/tui/app/slash-commands.mjs +1 -0
  281. package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
  282. package/src/tui/app/slash-dispatch.mjs +1 -1
  283. package/src/tui/app/use-btw-panel.mjs +29 -0
  284. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  285. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  286. package/src/tui/app/use-mouse-input.mjs +11 -0
  287. package/src/tui/app/use-onboarding-start.mjs +8 -3
  288. package/src/tui/app/use-panel-transition.mjs +10 -1
  289. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  290. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  291. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  292. package/src/tui/app/use-prompt-queue-history.mjs +3 -2
  293. package/src/tui/app/use-selection-focus.mjs +11 -2
  294. package/src/tui/app/use-selection-geometry.mjs +18 -9
  295. package/src/tui/app/use-selection-paint.mjs +4 -4
  296. package/src/tui/app/use-selection-stitch.mjs +3 -3
  297. package/src/tui/app/use-slash-palette.mjs +62 -0
  298. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  299. package/src/tui/app/use-transcript-activity.mjs +47 -32
  300. package/src/tui/app/use-transcript-follow.mjs +12 -4
  301. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  302. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  303. package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
  304. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  305. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  306. package/src/tui/app/use-transcript-window.mjs +21 -11
  307. package/src/tui/app/use-tui-ready.mjs +18 -0
  308. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  309. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  310. package/src/tui/components/Picker.jsx +27 -3
  311. package/src/tui/components/SignInUrl.jsx +68 -0
  312. package/src/tui/components/TextEntryPanel.jsx +76 -46
  313. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  314. package/src/tui/dist/index.mjs +1896 -1341
  315. package/src/tui/session/goal-turn-state.mjs +6 -2
  316. package/src/tui/session/session-api/controls.mjs +4 -0
  317. package/src/tui/session/session-api/extensions.mjs +8 -0
  318. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  319. package/src/tui/session/session-api/intake.mjs +2 -0
  320. package/src/tui/session/session-api/integrations.mjs +2 -2
  321. package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
  322. package/src/tui/session/session-api/settings.mjs +2 -2
  323. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  324. package/src/tui/session/transcript-spill.mjs +92 -4
  325. package/src/tui/session/transcript-store.mjs +2 -0
  326. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // Weekly opt-out sweep: run every test:*/smoke:* npm script in the repository
3
- // so no locally-registered suite can rot silently (docs/testing.md, "A
4
- // contract suite runs in CI or it drifts"). New scripts join automatically;
3
+ // so no locally-registered suite can rot silently (docs/testing.md, "CI coverage"). New scripts join automatically;
5
4
  // exclusions are explicit, reasoned, and fail closed when they go stale.
6
5
  import { readFileSync, writeFileSync } from 'node:fs';
7
6
  import { join } from 'node:path';
@@ -36,13 +35,9 @@ export const WORKSPACES = [
36
35
  'test:daemon:e2e': 'needs the built daemon; the release gate desktop job owns it',
37
36
  'test:spec-advisory': 'advisory by design (MIXDOG_TEST_ADVISORY)',
38
37
  'test:browser-host:integration': 'live desktop integration harness',
39
- 'test:browser-login-persistence:integration':
40
- 'live desktop integration harness; launches real Electron, which needs a display the Linux sweep runner lacks',
41
- 'test:browser-login-popup:integration':
42
- 'live desktop integration harness; launches real Electron, which needs a display the Linux sweep runner lacks',
43
38
  'test:browser-profile-import:integration': 'live desktop integration harness',
44
39
  'test:remote-webrtc-sender:integration':
45
- 'live desktop integration harness; launches real Electron, which needs a display the Linux sweep runner lacks',
40
+ 'live desktop integration harness; launches real Electron and has never run in the sweep, so it stays out until verified under Xvfb',
46
41
  'test:computer-host:integration': 'live desktop integration harness',
47
42
  'test:computer-host:scenarios': 'live desktop scenario harness',
48
43
  'test:computer-host:repeats': 'live desktop scenario harness',
@@ -50,6 +45,32 @@ export const WORKSPACES = [
50
45
  },
51
46
  ];
52
47
 
48
+ // Swept scripts that launch a real Electron window. The headless Linux runner
49
+ // has no X server, so they run inside a virtual one (xvfb-run, as
50
+ // linux-desktop-verify.yml does). The runner also has no usable keyring (a
51
+ // keyring daemon there prompts for an unlock on a display it cannot open and
52
+ // stalls the entry), and these entries check Mixdog's own persistence and
53
+ // sign-out logic, not the OS keychain. So on Linux the sweep sets
54
+ // TEST_PLAINTEXT_SAFE_STORAGE_ENV and the test harness alone (never the app)
55
+ // switches Electron's safeStorage to its in-memory-password fallback.
56
+ export const DISPLAY_SUITES = ['test:browser-login-persistence:integration', 'test:browser-login-popup:integration'];
57
+ export const TEST_PLAINTEXT_SAFE_STORAGE_ENV = 'MIXDOG_TEST_PLAINTEXT_SAFE_STORAGE';
58
+
59
+ const runsUnderDisplay = (ws, name, platform) =>
60
+ platform === 'linux' && ws.dir !== '.' && DISPLAY_SUITES.includes(name);
61
+
62
+ export function sweepCommand(ws, name, platform = process.platform) {
63
+ const args = ['run', name, ...(ws.dir === '.' ? [] : ['--prefix', ws.dir])];
64
+ if (runsUnderDisplay(ws, name, platform)) {
65
+ return ['xvfb-run', ['-a', '--server-args=-screen 0 1440x900x24', 'npm', ...args]];
66
+ }
67
+ return [platform === 'win32' ? 'npm.cmd' : 'npm', args];
68
+ }
69
+
70
+ export function sweepEnv(ws, name, platform = process.platform, base = process.env) {
71
+ return runsUnderDisplay(ws, name, platform) ? { ...base, [TEST_PLAINTEXT_SAFE_STORAGE_ENV]: '1' } : base;
72
+ }
73
+
53
74
  export function selectSuiteScripts(scripts, exclusions) {
54
75
  const names = Object.keys(scripts).filter((name) => /^(test|smoke)(:|$)/.test(name));
55
76
  const stale = Object.keys(exclusions).filter((name) => !names.includes(name));
@@ -59,12 +80,80 @@ export function selectSuiteScripts(scripts, exclusions) {
59
80
  return names.filter((name) => !(name in exclusions));
60
81
  }
61
82
 
62
- const lastLines = (text) =>
63
- String(text || '')
83
+ const TAIL_LINES = 25;
84
+ const lastLines = (text, name) => {
85
+ const lines = String(text || '')
64
86
  .trim()
87
+ .split('\n');
88
+ if (lines.length <= TAIL_LINES) return lines.join('\n');
89
+ return [`[${name} truncated: last ${TAIL_LINES} of ${lines.length} lines]`, ...lines.slice(-TAIL_LINES)].join('\n');
90
+ };
91
+
92
+ // What a failed entry shows in the report: how it ended, every failure-summary
93
+ // and failed-test line from either stream (a long stderr must not hide them),
94
+ // then each stream's tail.
95
+ export function failureParts({ stdout, stderr, status, signal, error }) {
96
+ const failedLines = `${stdout || ''}\n${stderr || ''}`
65
97
  .split('\n')
66
- .slice(-25)
67
- .join('\n');
98
+ .filter((line) => /^\[failure-summary\]|^\s*✖ /.test(line));
99
+ const ended = error
100
+ ? `spawn error: ${error.message}`
101
+ : `exit ${status ?? 'none'}${signal ? `, signal ${signal}` : ''}`;
102
+ const tails = [lastLines(stdout, 'stdout'), lastLines(stderr, 'stderr')].filter(Boolean).join('\n');
103
+ return { ended, failedLines, tails };
104
+ }
105
+
106
+ const failureText = ({ ended, failedLines, tails }) =>
107
+ [ended, failedLines.join('\n'), tails].filter(Boolean).join('\n').trim();
108
+
109
+ export const failureTail = (child) => failureText(failureParts(child));
110
+
111
+ // GitHub rejects an issue body over 65,536 characters (HTTP 422). Past the
112
+ // limit the tails go first, then failure lines from the end; the omission is
113
+ // always stated, and the full diagnostics stay in the workflow log.
114
+ const ISSUE_BODY_LIMIT = 60_000;
115
+
116
+ export function buildReport({ checked, runUrl, reportLines, failures, limit = ISSUE_BODY_LIMIT }) {
117
+ const render = (withTails, keep) => {
118
+ let left = keep;
119
+ let omitted = 0;
120
+ const blocks = failures.map(({ title, parts }) => {
121
+ const shown = parts.failedLines.slice(0, left);
122
+ left -= shown.length;
123
+ omitted += parts.failedLines.length - shown.length;
124
+ const text = failureText({ ...parts, failedLines: shown, tails: withTails ? parts.tails : '' });
125
+ return `${title}\n\n\`\`\`\n${text}\n\`\`\``;
126
+ });
127
+ const notes = [];
128
+ if (!withTails) notes.push('Stdout/stderr tails omitted to fit the issue size limit; see the workflow log.');
129
+ if (omitted) notes.push(`${omitted} more failure lines omitted — see the workflow log: ${runUrl}`);
130
+ return [
131
+ '# Weekly suite health sweep failed',
132
+ '',
133
+ `Checked: ${checked}`,
134
+ `Workflow run: ${runUrl}`,
135
+ '',
136
+ ...reportLines,
137
+ '',
138
+ ...blocks,
139
+ '',
140
+ ...notes,
141
+ ]
142
+ .join('\n')
143
+ .trimEnd()
144
+ .concat('\n');
145
+ };
146
+ const total = failures.reduce((sum, { parts }) => sum + parts.failedLines.length, 0);
147
+ if (render(true, total).length <= limit) return render(true, total);
148
+ let low = 0;
149
+ let high = total;
150
+ while (low < high) {
151
+ const mid = Math.ceil((low + high) / 2);
152
+ if (render(false, mid).length <= limit) low = mid;
153
+ else high = mid - 1;
154
+ }
155
+ return render(false, low);
156
+ }
68
157
 
69
158
  function runSweep() {
70
159
  const failures = [];
@@ -75,8 +164,9 @@ function runSweep() {
75
164
  for (const name of names) {
76
165
  const label = ws.dir === '.' ? name : `${ws.dir} ${name}`;
77
166
  const started = Date.now();
78
- const args = ['run', name, ...(ws.dir === '.' ? [] : ['--prefix', ws.dir])];
79
- const child = spawnSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, {
167
+ const [command, args] = sweepCommand(ws, name);
168
+ const child = spawnSync(command, args, {
169
+ env: sweepEnv(ws, name),
80
170
  encoding: 'utf8',
81
171
  shell: process.platform === 'win32',
82
172
  maxBuffer: 64 * 1024 * 1024,
@@ -88,10 +178,10 @@ function runSweep() {
88
178
  } else {
89
179
  // Tail each stream on its own: a long stderr (cargo build chatter) must
90
180
  // not push the test failure summary on stdout out of the report.
91
- const tail = `${lastLines(child.stdout)}\n${lastLines(child.stderr)}`.trim();
92
- failures.push(`- ${label}: FAILED (${seconds}s)\n\n\`\`\`\n${tail}\n\`\`\``);
181
+ const parts = failureParts(child);
182
+ failures.push({ title: `- ${label}: FAILED (${seconds}s)`, parts });
93
183
  reportLines.push(`- ${label}: FAILED (${seconds}s)`);
94
- console.error(`${label}: FAILED (${seconds}s)\n${tail}`);
184
+ console.error(`${label}: FAILED (${seconds}s)\n${failureText(parts)}`);
95
185
  }
96
186
  }
97
187
  }
@@ -100,18 +190,10 @@ function runSweep() {
100
190
  const runUrl = process.env.GITHUB_RUN_ID
101
191
  ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
102
192
  : '(local run)';
103
- const report = [
104
- '# Weekly suite health sweep failed',
105
- '',
106
- `Checked: ${new Date().toISOString()}`,
107
- `Workflow run: ${runUrl}`,
108
- '',
109
- ...reportLines,
110
- '',
111
- ...failures,
112
- '',
113
- ].join('\n');
114
- writeFileSync('suite-health-report.md', report);
193
+ writeFileSync(
194
+ 'suite-health-report.md',
195
+ buildReport({ checked: new Date().toISOString(), runUrl, reportLines, failures })
196
+ );
115
197
  process.exitCode = 1;
116
198
  }
117
199
  }
package/scripts/test.mjs CHANGED
@@ -40,12 +40,11 @@ export const USAGE = `Usage: node scripts/test.mjs [--lane ${LANES.join('|')}] [
40
40
  --exclude-lane drop one lane from the selection, repeatable. Electron and
41
41
  window-capture tests cannot run twice at once, so a second
42
42
  concurrent --lane all run uses --exclude-lane electron.
43
- --rerun-failed <n> re-run the failed files up to n times. Default: 1 for a
44
- local run, 0 (off) when CI is set; MIXDOG_TEST_RERUN_FAILED
45
- overrides the default. A test that passes on a re-run is
46
- reported as flaky and does NOT fail the run; a test that
47
- fails every re-run still exits 1. With 0 every failure fails
48
- the run.
43
+ --rerun-failed <n> re-run the failed files up to n times to classify flaky
44
+ tests. Default 0: every failure fails the run;
45
+ MIXDOG_TEST_RERUN_FAILED overrides the default. A test that
46
+ passes on a re-run is reported as flaky and does NOT fail the
47
+ run; a test that fails every re-run still exits 1.
49
48
  Per-file timeout: --test-timeout (default 120000 ms for the fast lane, 600000
50
49
  ms otherwise); MIXDOG_TEST_TIMEOUT_MS overrides, 0 disables.
51
50
  --import forwarded to node (desktop passes its test-env and tsx loaders).
@@ -88,15 +87,11 @@ function rerunCount(value) {
88
87
  return Number(value);
89
88
  }
90
89
 
91
- // Files run in parallel on every core, which exposes timing-sensitive tests
92
- // that pass alone. A local run therefore re-runs failed files once and reports
93
- // a pass on the re-run as flaky (named in the failure summary). CI keeps the
94
- // strict policy unless it opts in with --rerun-failed or MIXDOG_TEST_RERUN_FAILED;
95
- // MIXDOG_TEST_RERUN_FAILED=0 turns the local default off.
90
+ // Every failure fails the run, locally and in CI: a test that passes only on a
91
+ // re-run is a defect to fix, not a pass. Re-runs happen only on an explicit
92
+ // --rerun-failed or MIXDOG_TEST_RERUN_FAILED, to classify a failure as flaky.
96
93
  export function defaultRerunFailed(env = process.env) {
97
- if (/^\d+$/.test(String(env.MIXDOG_TEST_RERUN_FAILED ?? ''))) return Number(env.MIXDOG_TEST_RERUN_FAILED);
98
- const ci = String(env.CI ?? '').toLowerCase();
99
- return ci && ci !== '0' && ci !== 'false' ? 0 : 1;
94
+ return /^\d+$/.test(String(env.MIXDOG_TEST_RERUN_FAILED ?? '')) ? Number(env.MIXDOG_TEST_RERUN_FAILED) : 0;
100
95
  }
101
96
 
102
97
  export function parseArgs(argv) {
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: Advisor
3
- description: "Use when the approach is genuinely unclear, when errors recur or results stop converging, before changing approach, or when the user asks for a second opinion. Never for final verification."
3
+ description: "Use as a second mind on hard work: consulting before a risky or complex change is built, hunting a bug whose cause is unclear, errors that recur or results that stop converging, or when the user asks. Never for final verification."
4
4
  ---
5
5
 
6
6
  Independent technical advisor.
7
7
 
8
- You are consulted at decision points: when the approach is genuinely
9
- unclear, when errors recur or results stop converging, before a
10
- change of approach, and when the user asks for a second opinion or
8
+ You are a second mind on hard work: consulted before a risky or complex
9
+ change is built, to hunt a bug whose cause is unclear, when errors recur or
10
+ results stop converging, and when the user asks for a second opinion or
11
11
  cross-validation. You do not see the Lead's conversation; work from the brief
12
12
  and verify its evidence against the source yourself.
13
13
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "advisor",
3
3
  "name": "Advisor",
4
- "description": "Use when the approach is genuinely unclear, when errors recur or results stop converging, before changing approach, or when the user asks for a second opinion. Never for final verification.",
4
+ "description": "Use as a second mind on hard work: consulting before a risky or complex change is built, hunting a bug whose cause is unclear, errors that recur or results that stop converging, or when the user asks. Never for final verification.",
5
5
  "entry": "AGENT.md"
6
6
  }
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: Explore
3
+ description: Use when Mixdog runs the explore tool. The tool stays off until a model is picked.
4
+ permission: read
5
+ ---
6
+
7
+ Read-only explorer for one query of the explore tool. Search and read the
8
+ working directory; never edit, run commands or delegate.
9
+
10
+ Answer the query in the message, then stop:
11
+
12
+ - First a short direct answer.
13
+ - Then the evidence: one `path:line` per finding, copied from tool output,
14
+ with a few words on what is there.
15
+ - Only what you found. If nothing answers the query, say so in one line and
16
+ name what you searched.
17
+ - Nothing else: no locations the query did not ask about, no notes on what
18
+ you did not read.
19
+
20
+ Batch independent patterns and paths in one call. A location a tool returned
21
+ is final: do not re-read or reconfirm it. Stop as soon as the answer is
22
+ supported.
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "explore",
3
+ "name": "Explore",
4
+ "description": "Use when Mixdog runs the explore tool. The tool stays off until a model is picked.",
5
+ "entry": "AGENT.md"
6
+ }
package/src/cli.mjs CHANGED
@@ -24,6 +24,13 @@ try {
24
24
  // 2026-07-20). Default to production; an explicit NODE_ENV still wins.
25
25
  process.env.NODE_ENV ||= 'production';
26
26
 
27
+ // HTTPS_PROXY/HTTP_PROXY work without NODE_USE_ENV_PROXY: honoured in this
28
+ // process and in every child (the daemon included). On Windows without any
29
+ // proxy variable, the static system proxy routes this process's own fetch and
30
+ // is handed to the daemon this CLI starts, never exported as environment.
31
+ (await import('./runtime/shared/llm/system-proxy.mjs')).adoptSystemProxy();
32
+ (await import('./runtime/shared/llm/http-agent.mjs')).adoptEnvProxy();
33
+
27
34
  let swapped = false;
28
35
  const invocation = classifyCliInvocation(argv);
29
36
  const skipHostPrelude = invocation.kind === 'exec' || invocation.skipHostPrelude === true;
@@ -1,5 +1,12 @@
1
1
  {
2
2
  "agents": [
3
+ {
4
+ "agent": "explore-agent",
5
+ "slot": "explore",
6
+ "description": "One-off read-only explorer, one per query of the explore tool",
7
+ "invokedBy": "explore",
8
+ "maintKey": "explore"
9
+ },
3
10
  {
4
11
  "agent": "cycle1-agent",
5
12
  "slot": "cycle1",
@@ -3,12 +3,14 @@
3
3
  "advisor": [
4
4
  "6bd0318995f70547c162efda92795e79",
5
5
  "895c5f4311dcbebc0c8756c9ec61a02a",
6
- "d3b4a7926c9484833fe8ddba70260f9d"
6
+ "d3b4a7926c9484833fe8ddba70260f9d",
7
+ "fa56b363b9eeb07cb194dcd66dc4159b"
7
8
  ],
8
9
  "debugger": [
9
10
  "88c946270760ecbae86df65b9ce262f1"
10
11
  ],
11
12
  "explore": [
13
+ "baf26f0b3bd3abb0fb5a276febc8c4bc",
12
14
  "d4fa3ff93ace1dfac0b92792f42b9cbf"
13
15
  ],
14
16
  "front-worker": [
@@ -186,6 +188,7 @@
186
188
  "43eeb0b9c5792f08f2223c76846926cb",
187
189
  "4ab5316454013712cedb25d9b75f4e43",
188
190
  "4f042de090d853ed38aaa82b88d301ac",
191
+ "5d909abd96e4aa8636f27cf652301c5e",
189
192
  "646365a3f7041a3da3d7d7d896a0c3b6",
190
193
  "662f730d603b1e583dc777a1984b9134",
191
194
  "814b0820a05119a049cf4262dc35301b",
@@ -216,6 +219,7 @@
216
219
  "8a5a68ec13a7414b35e7f3b0089e2208",
217
220
  "9728f28dc5b23eb1bb1924213d3ffddd",
218
221
  "9a8789b3b4f5f6b3ba02f407cdfb92f7",
222
+ "ab5cce4a2fccad63e006cf22aa6cc6b0",
219
223
  "b50e9c0ba5e8228583eab4f0e0573838",
220
224
  "c03f4d0e008467497c0152639953b166",
221
225
  "cd1a47197762135462037ea6555ea721",
@@ -246,6 +250,7 @@
246
250
  "e10367dd4291a0b3d8ee8e8dd60eae36",
247
251
  "e1f2526aaf123fb77072aa8975f890de",
248
252
  "e67f30ec5bbdd36d7feaabd35b7504b3",
253
+ "edc3519cf07e37702a5793bb23e0643c",
249
254
  "f0798c546c172a742e3384d82322ede4"
250
255
  ],
251
256
  "docx": [
@@ -268,6 +273,7 @@
268
273
  "07604666cb32a7df8b1d4f0d1e137890",
269
274
  "189bca949decd5bccbbdeb49a18426b2",
270
275
  "1db9f3e81c714e7e4aa8db8c8004cca0",
276
+ "290d7620499a4134fdf511aa4902043d",
271
277
  "6d922fc351d6519c3d92cc5807fe0615",
272
278
  "95c83d23f3625c35cc346477a470c769",
273
279
  "a47d07ea3402854dc03e655afd5a3a6d",
@@ -388,7 +394,9 @@
388
394
  "81e979463e0066e7a45cf511a31c5d68",
389
395
  "8476c811b2f02da3a434bcb23a1c3d12",
390
396
  "8af2b614e2a07b58dad6c0f1318d22e2",
397
+ "8b829db6b0675b62a71a1432dbd25490",
391
398
  "99d76213e70c6900d6af48ffa4045886",
399
+ "9a2188ce201e4394bc18182131b7a3e1",
392
400
  "9f90d3872b1ecd312977ce661b770b31",
393
401
  "ade615dd0f6ae6ed1601023e5b9cb692",
394
402
  "b21681ecfeb523c0d7dd89a299ec05a9",
@@ -412,18 +420,24 @@
412
420
  "633e15b84dbe22f2b578b67cc35853d4",
413
421
  "72e474711ecd18cfcae6c8365e08286e",
414
422
  "920d5b29ccfe6c88f623cf0892b29285",
415
- "ec88a82ab5e511c0afb1738162150648"
423
+ "ec88a82ab5e511c0afb1738162150648",
424
+ "fa355d4ea5f1823e4b75219ab842c34a"
416
425
  ],
417
426
  "skill-creator": [
418
427
  "020817866da73a69544ba35086bdcd5f",
419
428
  "2f3f44805618783fbcca9a56652a5e91",
420
429
  "50e365910692a803732f68f82fc1ed1f",
421
430
  "77a4ca1c08f684780eeeebec50a3f1e6",
431
+ "92b2ed0b18a9c14470e434ec946a843f",
422
432
  "bd9bf738a5b3f443450c86230f3299fd",
423
433
  "bec7e5abbcae88a6781d23bcdd35e259",
424
434
  "d65265972caa7cbefc39baacc9e78157",
425
435
  "f450e6d58a7f1f06c71aa2dd557ce09c"
426
436
  ],
437
+ "test-suite": [
438
+ "df60ba4a182ee289f3550e79f1731cd4",
439
+ "f5c8ee5331a9b8279f997f609b10c380"
440
+ ],
427
441
  "video": [
428
442
  "6aad64b16521d324e355d125692a0cec",
429
443
  "82f61245cc67ce5380ab9ccf4c697c29",
@@ -436,6 +450,8 @@
436
450
  "8320fedd9dd745a332621c325a8bf355",
437
451
  "9c9fba19647b67d75a600137e38c02b8",
438
452
  "aa3531bfc4fd6ec3820493d0c190cc75",
453
+ "d9ba9f5f998bf42990eed838a3d1b774",
454
+ "df699ca05260ce37813a7fe6666927da",
439
455
  "f24ff77670e5aa43ce901dec1e0055ac",
440
456
  "f65924f0691284ad31000469a9855b62"
441
457
  ],
@@ -320,7 +320,10 @@ file-reading tool instead of clicking around the page.
320
320
  **Multi-page task** — keep one snapshot per page; `list_tabs` when targets or
321
321
  ownership are unknown, then act on the intended tab. Use `back` instead of
322
322
  re-navigating when history suffices; forward is a `navigate` to the URL the
323
- earlier snapshot showed.
323
+ earlier snapshot showed. A popup the page opens (`window.open`, an OAuth or
324
+ sign-in window) becomes a background page the reply names ("Opened
325
+ "popup-N" as a new page"), and the visible page does not switch: act on it
326
+ by that name, and check `list_tabs` before concluding no popup opened.
324
327
 
325
328
  **Downloads / uploads** — `downloads` lists and can `wait` for and `attach`
326
329
  the newest file (≤ 8 MiB). A wait pins the newest download, or the next one to