@selesai/code 0.5.28 → 0.5.29

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 (307) hide show
  1. package/dist/cli/args.d.ts.map +1 -1
  2. package/dist/cli/args.js +9 -1
  3. package/dist/cli/args.js.map +1 -1
  4. package/dist/cli/config-selector.d.ts.map +1 -1
  5. package/dist/cli/config-selector.js +1 -1
  6. package/dist/cli/config-selector.js.map +1 -1
  7. package/dist/cli/credential-print.d.ts +23 -0
  8. package/dist/cli/credential-print.d.ts.map +1 -0
  9. package/dist/cli/credential-print.js +117 -0
  10. package/dist/cli/credential-print.js.map +1 -0
  11. package/dist/cli/startup-ui.d.ts.map +1 -1
  12. package/dist/cli/startup-ui.js +1 -1
  13. package/dist/cli/startup-ui.js.map +1 -1
  14. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  15. package/dist/core/agent-session-runtime.js +3 -0
  16. package/dist/core/agent-session-runtime.js.map +1 -1
  17. package/dist/core/agent-session.d.ts +12 -1
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +20 -14
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/compaction/compaction.d.ts.map +1 -1
  22. package/dist/core/compaction/compaction.js +11 -3
  23. package/dist/core/compaction/compaction.js.map +1 -1
  24. package/dist/core/extensions/runner.d.ts +1 -0
  25. package/dist/core/extensions/runner.d.ts.map +1 -1
  26. package/dist/core/extensions/runner.js +11 -0
  27. package/dist/core/extensions/runner.js.map +1 -1
  28. package/dist/core/extensions/types.d.ts +14 -1
  29. package/dist/core/extensions/types.d.ts.map +1 -1
  30. package/dist/core/extensions/types.js.map +1 -1
  31. package/dist/core/footer-data-provider.d.ts +10 -0
  32. package/dist/core/footer-data-provider.d.ts.map +1 -1
  33. package/dist/core/footer-data-provider.js +1 -1
  34. package/dist/core/footer-data-provider.js.map +1 -1
  35. package/dist/core/llama/provider.d.ts.map +1 -1
  36. package/dist/core/llama/provider.js +8 -3
  37. package/dist/core/llama/provider.js.map +1 -1
  38. package/dist/core/model-config.d.ts +30 -0
  39. package/dist/core/model-config.d.ts.map +1 -1
  40. package/dist/core/model-config.js +6 -0
  41. package/dist/core/model-config.js.map +1 -1
  42. package/dist/core/model-registry.d.ts.map +1 -1
  43. package/dist/core/model-registry.js +2 -2
  44. package/dist/core/model-registry.js.map +1 -1
  45. package/dist/core/model-resolver.d.ts +1 -0
  46. package/dist/core/model-resolver.d.ts.map +1 -1
  47. package/dist/core/model-resolver.js +20 -3
  48. package/dist/core/model-resolver.js.map +1 -1
  49. package/dist/core/model-runtime.d.ts +2 -0
  50. package/dist/core/model-runtime.d.ts.map +1 -1
  51. package/dist/core/model-runtime.js +5 -4
  52. package/dist/core/model-runtime.js.map +1 -1
  53. package/dist/core/package-manager.d.ts.map +1 -1
  54. package/dist/core/package-manager.js +13 -6
  55. package/dist/core/package-manager.js.map +1 -1
  56. package/dist/core/remote-catalog-provider.d.ts +1 -1
  57. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  58. package/dist/core/remote-catalog-provider.js +24 -11
  59. package/dist/core/remote-catalog-provider.js.map +1 -1
  60. package/dist/core/resource-loader.d.ts +15 -0
  61. package/dist/core/resource-loader.d.ts.map +1 -1
  62. package/dist/core/resource-loader.js +66 -9
  63. package/dist/core/resource-loader.js.map +1 -1
  64. package/dist/core/settings-manager.d.ts +1 -1
  65. package/dist/core/settings-manager.d.ts.map +1 -1
  66. package/dist/core/settings-manager.js.map +1 -1
  67. package/dist/core/system-prompt.d.ts.map +1 -1
  68. package/dist/core/system-prompt.js +1 -1
  69. package/dist/core/system-prompt.js.map +1 -1
  70. package/dist/core/tools/bash.d.ts +2 -0
  71. package/dist/core/tools/bash.d.ts.map +1 -1
  72. package/dist/core/tools/bash.js +34 -5
  73. package/dist/core/tools/bash.js.map +1 -1
  74. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  75. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  76. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  77. package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
  78. package/dist/extensions/pi-intercom/README.md +102 -39
  79. package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
  80. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
  81. package/dist/extensions/pi-intercom/broker/client.ts +315 -12
  82. package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
  83. package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
  84. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
  85. package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
  86. package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
  87. package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
  88. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
  89. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
  90. package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
  91. package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
  92. package/dist/extensions/pi-intercom/config.test.ts +93 -0
  93. package/dist/extensions/pi-intercom/config.ts +55 -6
  94. package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
  95. package/dist/extensions/pi-intercom/cwd.ts +31 -0
  96. package/dist/extensions/pi-intercom/extension-api.ts +44 -0
  97. package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
  98. package/dist/extensions/pi-intercom/format-context.ts +32 -0
  99. package/dist/extensions/pi-intercom/index.ts +742 -145
  100. package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
  101. package/dist/extensions/pi-intercom/package.json +15 -5
  102. package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
  103. package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
  104. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
  105. package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
  106. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
  107. package/dist/extensions/pi-intercom/types.ts +94 -4
  108. package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
  109. package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
  110. package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
  111. package/dist/extensions/pi-subagents/CHANGELOG.md +85 -0
  112. package/dist/extensions/pi-subagents/LICENSE +21 -0
  113. package/dist/extensions/pi-subagents/README.md +146 -52
  114. package/dist/extensions/pi-subagents/agents/architect.md +1 -0
  115. package/dist/extensions/pi-subagents/agents/builder.md +1 -0
  116. package/dist/extensions/pi-subagents/package-lock.json +2 -2
  117. package/dist/extensions/pi-subagents/package.json +3 -3
  118. package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
  119. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +21 -989
  120. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +256 -0
  121. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +430 -0
  122. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
  123. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +282 -0
  124. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +71 -30
  125. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
  126. package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
  127. package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
  128. package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
  129. package/dist/extensions/pi-subagents/src/api/preflight.ts +16 -12
  130. package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
  131. package/dist/extensions/pi-subagents/src/extension/index.ts +17 -7
  132. package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
  133. package/dist/extensions/pi-subagents/src/extension/schemas.ts +31 -6
  134. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +8 -7
  135. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
  136. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
  137. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +63 -16
  138. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
  139. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
  140. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
  141. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
  142. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
  143. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +29 -4
  144. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +29 -6
  145. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
  146. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +372 -28
  147. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
  148. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
  149. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +143 -43
  150. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +527 -247
  151. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
  152. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +426 -123
  153. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +15 -7
  154. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
  155. package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
  156. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  157. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
  158. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
  159. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
  160. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
  161. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
  162. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
  163. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
  164. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
  165. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
  166. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
  167. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +1 -1
  168. package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
  169. package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
  170. package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
  171. package/dist/extensions/pi-subagents/src/shared/types.ts +155 -10
  172. package/dist/extensions/pi-subagents/src/shared/utils.ts +73 -4
  173. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +5 -0
  174. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
  175. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
  176. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
  177. package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
  178. package/dist/extensions/pi-subagents/src/tui/render.ts +27 -28
  179. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
  180. package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
  181. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
  182. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
  183. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
  184. package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
  185. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  186. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +348 -7
  187. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
  188. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
  189. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
  190. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +26 -1
  191. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
  192. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +3 -3
  193. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +213 -13
  194. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +34 -0
  195. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
  196. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +118 -12
  197. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +850 -7
  198. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
  199. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
  200. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
  201. package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
  202. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
  203. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +128 -0
  204. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
  205. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
  206. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
  207. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +102 -0
  208. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
  209. package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
  210. package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
  211. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
  212. package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
  213. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
  214. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +4 -2
  215. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
  216. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
  217. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
  218. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
  219. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +11 -11
  220. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
  221. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
  222. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
  223. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +10 -2
  224. package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
  225. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
  226. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
  227. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +46 -0
  228. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
  229. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
  230. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
  231. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
  232. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
  233. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +34 -2
  234. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  235. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
  236. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
  237. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
  238. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
  239. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +3 -0
  240. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +1 -1
  241. package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
  242. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
  243. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
  244. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
  245. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
  246. package/dist/main.d.ts.map +1 -1
  247. package/dist/main.js +43 -0
  248. package/dist/main.js.map +1 -1
  249. package/dist/modes/interactive/components/custom-message.d.ts +3 -1
  250. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  251. package/dist/modes/interactive/components/custom-message.js +10 -2
  252. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  253. package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
  254. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  255. package/dist/modes/interactive/components/extension-editor.js +16 -46
  256. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  257. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  258. package/dist/modes/interactive/components/model-selector.js +4 -1
  259. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  260. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  261. package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
  262. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  263. package/dist/modes/interactive/external-editor.d.ts +12 -0
  264. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  265. package/dist/modes/interactive/external-editor.js +37 -0
  266. package/dist/modes/interactive/external-editor.js.map +1 -0
  267. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  268. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  269. package/dist/modes/interactive/interactive-mode.js +72 -64
  270. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  271. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  272. package/dist/modes/rpc/rpc-mode.js +14 -0
  273. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  274. package/dist/utils/clipboard.d.ts.map +1 -1
  275. package/dist/utils/clipboard.js +19 -8
  276. package/dist/utils/clipboard.js.map +1 -1
  277. package/dist/utils/version-check.d.ts.map +1 -1
  278. package/dist/utils/version-check.js +1 -1
  279. package/dist/utils/version-check.js.map +1 -1
  280. package/docs/compaction.md +1 -1
  281. package/docs/custom-provider.md +14 -5
  282. package/docs/environment-variables.md +86 -0
  283. package/docs/extensions.md +15 -5
  284. package/docs/index.md +1 -0
  285. package/docs/models.md +9 -2
  286. package/docs/providers.md +21 -2
  287. package/docs/rpc.md +23 -6
  288. package/docs/session-format.md +2 -0
  289. package/docs/settings.md +1 -1
  290. package/docs/usage.md +0 -13
  291. package/examples/extensions/custom-compaction.ts +5 -2
  292. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  293. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  294. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  295. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  296. package/examples/extensions/gondolin/package-lock.json +2 -2
  297. package/examples/extensions/gondolin/package.json +1 -1
  298. package/examples/extensions/handoff.ts +11 -3
  299. package/examples/extensions/message-renderer.ts +3 -3
  300. package/examples/extensions/sandbox/package-lock.json +2 -2
  301. package/examples/extensions/sandbox/package.json +1 -1
  302. package/examples/extensions/summarize.ts +5 -2
  303. package/examples/extensions/with-deps/package-lock.json +2 -2
  304. package/examples/extensions/with-deps/package.json +1 -1
  305. package/examples/sdk/12-full-control.ts +3 -1
  306. package/package.json +15 -6
  307. package/dist/extensions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
@@ -9,6 +9,7 @@ import {
9
9
  watchdogWarningFromLspDiagnostics,
10
10
  type WatchdogLspDiagnosticsFunction,
11
11
  } from "./lsp-diagnostics.ts";
12
+ import { WatchdogScopeArtifact, isWatchdogAutoFollowPromptEvent } from "./scope.ts";
12
13
  import { resolveWatchdogConfig } from "./settings.ts";
13
14
  import { formatWatchdogTurnDelta } from "./turn-delta.ts";
14
15
  import {
@@ -34,6 +35,7 @@ export interface WatchdogReviewResult {
34
35
  export interface WatchdogReviewRequest {
35
36
  delta: string;
36
37
  epoch: number;
38
+ hasScope: boolean;
37
39
  reviewId: number;
38
40
  config: ResolvedWatchdogConfig;
39
41
  emitWarning(warning: WatchdogWarning): boolean;
@@ -60,7 +62,9 @@ export interface WatchdogRuntimeSnapshot {
60
62
  staleReviews: number;
61
63
  reviewConnected: boolean;
62
64
  reviewDescription: string;
63
- autoFollowQueued: false;
65
+ autoFollowQueued: boolean;
66
+ autoFollowAttempts: number;
67
+ autoFollowStalemate: boolean;
64
68
  reviewTrigger: "turn-delta" | "repo-edits";
65
69
  changedPaths?: string[];
66
70
  lsp: WatchdogLspRuntimeSnapshot;
@@ -76,7 +80,8 @@ interface MainWatchdogRuntimeOptions {
76
80
  resolveConfig?: (cwd: string, options?: { session?: Record<string, unknown> }) => WatchdogSettingsResult;
77
81
  review?: WatchdogReviewFunction;
78
82
  reviewDescription?: string;
79
- displayWarning?: (warning: WatchdogWarningDetails) => void;
83
+ displayWarning?: (warning: WatchdogWarningDetails, options?: { deliverAs?: "steer" }) => void;
84
+ sendUserMessage?: (message: string) => void | Promise<void>;
80
85
  reviewChangesOnly?: boolean;
81
86
  lspDiagnostics?: WatchdogLspDiagnosticsFunction;
82
87
  repoChangeSignature?: typeof computeWatchdogRepoChangeSignature;
@@ -111,11 +116,13 @@ export class MainWatchdogRuntime {
111
116
  private readonly review: WatchdogReviewFunction;
112
117
  private readonly reviewConnected: boolean;
113
118
  private readonly reviewDescription: string;
114
- private readonly displayWarning: ((warning: WatchdogWarningDetails) => void) | undefined;
119
+ private readonly displayWarning: ((warning: WatchdogWarningDetails, options?: { deliverAs?: "steer" }) => void) | undefined;
120
+ private readonly sendUserMessage: ((message: string) => void | Promise<void>) | undefined;
115
121
  private readonly reviewChangesOnly: boolean;
116
122
  private readonly lspDiagnostics: WatchdogLspDiagnosticsFunction;
117
123
  private readonly repoChangeSignature: typeof computeWatchdogRepoChangeSignature;
118
124
  private readonly lspLedger = new WatchdogLspDiagnosticsLedger();
125
+ private readonly scope = new WatchdogScopeArtifact();
119
126
  private configResult: WatchdogSettingsResult;
120
127
  private sessionOverrideEnabled: boolean | undefined;
121
128
  private sessionModelOverride: Partial<Pick<WatchdogEndpointConfig, "model" | "thinking">> | undefined;
@@ -138,6 +145,7 @@ export class MainWatchdogRuntime {
138
145
  private userPrompt: string | undefined;
139
146
  private waiters: Waiter[] = [];
140
147
  private lastWarning: WatchdogWarningDetails | undefined;
148
+ private displayedWarningSequence = 0;
141
149
  private lastError: string | undefined;
142
150
  private lastReviewInputSignature: string | undefined;
143
151
  private turnStartChangeSignature: WatchdogRepoChangeSignature | undefined;
@@ -145,6 +153,16 @@ export class MainWatchdogRuntime {
145
153
  private currentChangedPaths: string[] | undefined;
146
154
  private lastLspSnapshot: WatchdogLspRuntimeSnapshot | undefined;
147
155
  private observedRepoEditThisTurn = false;
156
+ private toolResultsThisRun = 0;
157
+ private midRunReviewing = false;
158
+ private autoFollowQueued = false;
159
+ private autoFollowAttempts = 0;
160
+ private consecutiveAutoFollowIdentity: string | undefined;
161
+ private consecutiveAutoFollowRepeats = 0;
162
+ private autoFollowStalemate = false;
163
+ private pendingAutoFollowPrompts: string[] = [];
164
+ private midRunGeneration = 0;
165
+ private activeReviewAbortController: AbortController | undefined;
148
166
  private failedReviews = 0;
149
167
  private staleReviews = 0;
150
168
 
@@ -155,6 +173,7 @@ export class MainWatchdogRuntime {
155
173
  this.reviewConnected = Boolean(options.review);
156
174
  this.reviewDescription = options.reviewDescription ?? (options.review ? "injected seam" : "not wired");
157
175
  this.displayWarning = options.displayWarning;
176
+ this.sendUserMessage = options.sendUserMessage;
158
177
  this.reviewChangesOnly = options.reviewChangesOnly === true;
159
178
  this.lspDiagnostics = options.lspDiagnostics ?? collectWatchdogLspDiagnostics;
160
179
  this.repoChangeSignature = options.repoChangeSignature ?? computeWatchdogRepoChangeSignature;
@@ -170,7 +189,7 @@ export class MainWatchdogRuntime {
170
189
  this.sessionOverrideEnabled = undefined;
171
190
  this.sessionModelOverride = undefined;
172
191
  this.refreshConfig(ctx.cwd);
173
- this.reset("session_start", { clearReviewInputSignature: true, resetChangeSignature: true, clearLspLedger: true });
192
+ this.reset("session_start", { clearReviewInputSignature: true, resetChangeSignature: true, clearLspLedger: true, clearScope: true, resetAutoFollow: true });
174
193
  }
175
194
 
176
195
  refreshConfig(cwd = this.cwd): WatchdogSettingsResult {
@@ -228,7 +247,7 @@ export class MainWatchdogRuntime {
228
247
  return this.getSnapshot();
229
248
  }
230
249
 
231
- reset(_reason = "reset", options: { clearReviewInputSignature?: boolean; resetChangeSignature?: boolean; clearLspLedger?: boolean } = {}): void {
250
+ reset(_reason = "reset", options: { clearReviewInputSignature?: boolean; resetChangeSignature?: boolean; clearLspLedger?: boolean; clearScope?: boolean; resetAutoFollow?: boolean } = {}): void {
232
251
  this.abortActiveAgentEnd();
233
252
  this.epoch++;
234
253
  this.status = "idle";
@@ -242,10 +261,18 @@ export class MainWatchdogRuntime {
242
261
  this.lastError = undefined;
243
262
  this.currentChangedPaths = undefined;
244
263
  this.observedRepoEditThisTurn = false;
264
+ this.toolResultsThisRun = 0;
265
+ this.midRunReviewing = false;
266
+ this.autoFollowQueued = false;
245
267
  if (options.clearLspLedger) {
246
268
  this.lspLedger.reset();
247
269
  this.lastLspSnapshot = undefined;
248
270
  }
271
+ if (options.clearScope) {
272
+ this.scope.reset();
273
+ this.pendingAutoFollowPrompts = [];
274
+ }
275
+ if (options.resetAutoFollow) this.resetAutoFollowState();
249
276
  if (options.clearReviewInputSignature) this.lastReviewInputSignature = undefined;
250
277
  if (options.resetChangeSignature) this.resetRepoChangeBaseline({ reviewed: true });
251
278
  this.guard.reset();
@@ -266,16 +293,31 @@ export class MainWatchdogRuntime {
266
293
  this.currentChangedPaths = undefined;
267
294
  this.lastLspSnapshot = undefined;
268
295
  this.lspLedger.reset();
296
+ this.scope.reset();
269
297
  this.observedRepoEditThisTurn = false;
298
+ this.toolResultsThisRun = 0;
299
+ this.midRunReviewing = false;
300
+ this.autoFollowQueued = false;
270
301
  this.resolveWaiters(false);
271
302
  }
272
303
 
273
304
  handleBeforeAgentStart(event: unknown, ctx: ContextLike): void {
274
305
  if (this.disposed) return;
275
- this.reset("before_agent_start");
306
+ const incomingPrompt = promptFromBeforeAgentStart(event);
307
+ // Only exact queued auto-follow text is treated as an auto-follow turn; a real user
308
+ // prompt racing in ahead of one stays real and the pending matches survive for later.
309
+ const pendingIndex = incomingPrompt === undefined ? -1 : this.pendingAutoFollowPrompts.indexOf(incomingPrompt);
310
+ const autoFollowPrompt = pendingIndex >= 0 || isWatchdogAutoFollowPromptEvent(event);
311
+ if (pendingIndex >= 0) this.pendingAutoFollowPrompts.splice(pendingIndex, 1);
312
+ this.reset("before_agent_start", { resetAutoFollow: !autoFollowPrompt });
276
313
  this.refreshConfig(ctx.cwd);
277
- this.userPrompt = promptFromBeforeAgentStart(event);
278
- this.includeUserPromptInNextDelta = Boolean(this.userPrompt?.trim());
314
+ this.userPrompt = incomingPrompt;
315
+ if (!autoFollowPrompt && this.userPrompt?.trim()) {
316
+ this.includeUserPromptInNextDelta = true;
317
+ this.scope.addPrompt(this.userPrompt);
318
+ } else {
319
+ this.includeUserPromptInNextDelta = false;
320
+ }
279
321
  this.resetRepoChangeBaseline();
280
322
  }
281
323
 
@@ -300,7 +342,21 @@ export class MainWatchdogRuntime {
300
342
  enqueueDelta(delta: string): void {
301
343
  if (this.disposed || !delta.trim() || !this.isEnabled()) return;
302
344
  this.appendBoundedDelta(delta);
303
- if (!this.reviewing && !this.waitingAtAgentEnd) this.status = "queued";
345
+ if (!this.reviewing && !this.waitingAtAgentEnd && !this.midRunReviewing) this.status = "queued";
346
+ }
347
+
348
+ handleToolResult(ctx: ContextLike): void {
349
+ if (this.disposed) return;
350
+ this.refreshConfig(ctx.cwd);
351
+ if (!this.isEnabled()) return;
352
+ const everyNTools = this.configResult.config.cadence.everyNTools;
353
+ if (everyNTools === null) return;
354
+ this.toolResultsThisRun++;
355
+ if (this.toolResultsThisRun % everyNTools !== 0) return;
356
+ if (this.reviewing || this.waitingAtAgentEnd || this.midRunReviewing) return;
357
+ const delta = this.buildReviewInput(undefined, "");
358
+ if (!delta.trim()) return;
359
+ void this.reviewMidRunDelta(delta);
304
360
  }
305
361
 
306
362
  async handleAgentEnd(_event: unknown, ctx: ContextLike): Promise<void> {
@@ -320,12 +376,15 @@ export class MainWatchdogRuntime {
320
376
  this.resolveWaiters(true);
321
377
  return;
322
378
  }
379
+ this.cancelMidRunReview();
323
380
  this.waitingAtAgentEnd = true;
324
381
  const agentEndEpoch = this.epoch;
325
382
  const agentEndId = ++this.agentEndIdCounter;
326
383
  const lspAbortController = new AbortController();
327
384
  this.activeAgentEndId = agentEndId;
328
385
  this.activeAgentEndAbortController = lspAbortController;
386
+ let displayedDuringAgentEnd: WatchdogWarningDetails | undefined;
387
+ const previousDisplayedSequence = this.displayedWarningSequence;
329
388
  try {
330
389
  this.guard.startModelUpdate();
331
390
  const lspBlock = await this.collectLspDiagnostics(changeSignature, {
@@ -366,6 +425,8 @@ export class MainWatchdogRuntime {
366
425
  this.currentChangedPaths = changeSignature?.changedPaths;
367
426
  this.status = "idle";
368
427
  }
428
+ displayedDuringAgentEnd = this.displayedWarningSequence !== previousDisplayedSequence ? this.lastWarning : undefined;
429
+ this.queueAutoFollowIfNeeded(displayedDuringAgentEnd);
369
430
  this.resolveWaiters(true);
370
431
  } finally {
371
432
  if (this.activeAgentEndAbortController === lspAbortController) this.activeAgentEndAbortController = undefined;
@@ -399,7 +460,9 @@ export class MainWatchdogRuntime {
399
460
  staleReviews: this.staleReviews,
400
461
  reviewConnected: this.reviewConnected,
401
462
  reviewDescription: this.reviewDescription,
402
- autoFollowQueued: false,
463
+ autoFollowQueued: this.autoFollowQueued,
464
+ autoFollowAttempts: this.autoFollowAttempts,
465
+ autoFollowStalemate: this.autoFollowStalemate,
403
466
  reviewTrigger: this.reviewChangesOnly ? "repo-edits" : "turn-delta",
404
467
  ...(this.currentChangedPaths?.length ? { changedPaths: [...this.currentChangedPaths] } : {}),
405
468
  lsp: this.lspSnapshot(),
@@ -428,8 +491,12 @@ export class MainWatchdogRuntime {
428
491
  return !this.disposed && this.epoch === epoch && this.activeReviewId === reviewId;
429
492
  }
430
493
 
494
+ private warningMeetsThreshold(warning: WatchdogWarning): boolean {
495
+ return this.configResult.config.severityThreshold === "concern" || warning.severity === "blocker";
496
+ }
497
+
431
498
  private acceptWarning(epoch: number, reviewId: number, warning: WatchdogWarning): boolean {
432
- if (!this.isCurrent(epoch, reviewId) || !this.isEnabled()) return false;
499
+ if (!this.isCurrent(epoch, reviewId) || !this.isEnabled() || !this.warningMeetsThreshold(warning)) return false;
433
500
  const decision = this.guard.evaluate(warning);
434
501
  if (!decision.accepted) return false;
435
502
  const details = normalizeWatchdogWarningDetails(warning, {
@@ -443,7 +510,7 @@ export class MainWatchdogRuntime {
443
510
  }
444
511
 
445
512
  private displayBoundaryWarning(warning: WatchdogWarning): boolean {
446
- if (!this.isEnabled()) return false;
513
+ if (!this.isEnabled() || !this.warningMeetsThreshold(warning)) return false;
447
514
  const decision = this.guard.evaluate(warning);
448
515
  if (!decision.accepted) return false;
449
516
  const details = normalizeWatchdogWarningDetails(warning, {
@@ -453,6 +520,7 @@ export class MainWatchdogRuntime {
453
520
  displayedAt: new Date().toISOString(),
454
521
  });
455
522
  this.lastWarning = details;
523
+ this.displayedWarningSequence++;
456
524
  this.displayWarning?.(details);
457
525
  return true;
458
526
  }
@@ -468,7 +536,41 @@ export class MainWatchdogRuntime {
468
536
  this.activeReviewWarning = undefined;
469
537
  }
470
538
 
471
- private async reviewDelta(delta: string, timeoutMs: number): Promise<ReviewDeltaOutcome> {
539
+ private async reviewMidRunDelta(delta: string): Promise<void> {
540
+ if (this.midRunReviewing || this.reviewing || this.waitingAtAgentEnd || this.disposed) return;
541
+ this.midRunReviewing = true;
542
+ const generation = this.midRunGeneration;
543
+ try {
544
+ const outcome = await this.reviewDelta(delta, this.configResult.config.agentEndTimeoutMs, { correction: true });
545
+ if (generation !== this.midRunGeneration) return;
546
+ if (outcome === "timeout") {
547
+ this.staleReviews++;
548
+ this.status = "stale";
549
+ this.markLastWarningStale();
550
+ }
551
+ } finally {
552
+ if (generation === this.midRunGeneration) {
553
+ this.midRunReviewing = false;
554
+ if (this.status === "reviewing") this.status = this.pendingDeltas.length ? "queued" : "idle";
555
+ this.resolveWaiters(this.isSettled());
556
+ }
557
+ }
558
+ }
559
+
560
+ // The agent-end boundary review is authoritative; an in-flight cadence review is superseded.
561
+ private cancelMidRunReview(): void {
562
+ if (!this.midRunReviewing) return;
563
+ this.midRunGeneration++;
564
+ this.activeReviewAbortController?.abort();
565
+ this.activeReviewAbortController = undefined;
566
+ this.staleReviews++;
567
+ this.reviewing = false;
568
+ this.midRunReviewing = false;
569
+ this.activeReviewId = undefined;
570
+ this.activeReviewWarning = undefined;
571
+ }
572
+
573
+ private async reviewDelta(delta: string, timeoutMs: number, options: { correction?: boolean } = {}): Promise<ReviewDeltaOutcome> {
472
574
  if (this.reviewing || this.disposed) return "stale";
473
575
  this.reviewing = true;
474
576
  const reviewEpoch = this.epoch;
@@ -478,11 +580,13 @@ export class MainWatchdogRuntime {
478
580
  this.status = "reviewing";
479
581
  let timeout: ReturnType<typeof setTimeout> | undefined;
480
582
  const abortController = new AbortController();
583
+ this.activeReviewAbortController = abortController;
481
584
  const reviewPromise = Promise.resolve().then(() => this.review({
482
585
  delta,
483
586
  epoch: reviewEpoch,
484
587
  reviewId,
485
588
  config: this.configResult.config,
589
+ hasScope: this.scopeBlock().trim().length > 0,
486
590
  signal: abortController.signal,
487
591
  emitWarning: (warning) => this.acceptWarning(reviewEpoch, reviewId, warning),
488
592
  }));
@@ -503,7 +607,7 @@ export class MainWatchdogRuntime {
503
607
  this.fail(`Watchdog review ended with stop reason '${result.stopReason}'.`);
504
608
  return "completed";
505
609
  }
506
- this.displayAcceptedReviewWarning();
610
+ this.displayAcceptedReviewWarning(options.correction);
507
611
  return "completed";
508
612
  } catch (error) {
509
613
  if (this.isCurrent(reviewEpoch, reviewId)) {
@@ -513,6 +617,7 @@ export class MainWatchdogRuntime {
513
617
  return "stale";
514
618
  } finally {
515
619
  if (timeout) clearTimeout(timeout);
620
+ if (this.activeReviewAbortController === abortController) this.activeReviewAbortController = undefined;
516
621
  if (this.epoch === reviewEpoch && this.activeReviewId === reviewId) {
517
622
  this.reviewing = false;
518
623
  this.activeReviewId = undefined;
@@ -522,7 +627,7 @@ export class MainWatchdogRuntime {
522
627
  }
523
628
  }
524
629
 
525
- private displayAcceptedReviewWarning(): void {
630
+ private displayAcceptedReviewWarning(correction = false): void {
526
631
  if (!this.activeReviewWarning) return;
527
632
  const details: WatchdogWarningDetails = {
528
633
  ...this.activeReviewWarning,
@@ -530,7 +635,50 @@ export class MainWatchdogRuntime {
530
635
  displayedAt: new Date().toISOString(),
531
636
  };
532
637
  this.lastWarning = details;
533
- this.displayWarning?.(details);
638
+ this.displayedWarningSequence++;
639
+ this.displayWarning?.(details, correction ? { deliverAs: "steer" } : undefined);
640
+ }
641
+
642
+ private resetAutoFollowState(): void {
643
+ this.autoFollowQueued = false;
644
+ this.autoFollowAttempts = 0;
645
+ this.consecutiveAutoFollowIdentity = undefined;
646
+ this.consecutiveAutoFollowRepeats = 0;
647
+ this.autoFollowStalemate = false;
648
+ }
649
+
650
+ private queueAutoFollowIfNeeded(warning: WatchdogWarningDetails | undefined): void {
651
+ if (!warning || warning.severity !== "blocker" || warning.stale || !this.configResult.config.autoFollow.blockers || !this.isEnabled()) return;
652
+ const identity = warning.identity ?? reviewInputSignature([warning.severity, warning.summary, warning.evidence].join("\n"));
653
+ if (this.consecutiveAutoFollowIdentity === identity) this.consecutiveAutoFollowRepeats++;
654
+ else {
655
+ this.consecutiveAutoFollowIdentity = identity;
656
+ this.consecutiveAutoFollowRepeats = 1;
657
+ }
658
+ if (this.consecutiveAutoFollowRepeats >= this.configResult.config.autoFollow.stalemateRepeats) {
659
+ this.autoFollowStalemate = true;
660
+ this.lastWarning = { ...warning, state: "stalemate", stalemateRepeats: this.consecutiveAutoFollowRepeats };
661
+ return;
662
+ }
663
+ const maxAttempts = this.configResult.config.autoFollow.maxAttempts;
664
+ if (maxAttempts !== null && this.autoFollowAttempts >= maxAttempts) return;
665
+ if (!this.sendUserMessage) return;
666
+ this.autoFollowAttempts++;
667
+ this.autoFollowQueued = true;
668
+ const prompt = [
669
+ "Watchdog auto-follow: address this blocker before continuing.",
670
+ `Summary: ${warning.summary}`,
671
+ `Evidence: ${warning.evidence}`,
672
+ `Recommended action: ${warning.recommendedAction}`,
673
+ ].join("\n");
674
+ this.pendingAutoFollowPrompts.push(prompt);
675
+ if (this.pendingAutoFollowPrompts.length > 8) this.pendingAutoFollowPrompts.shift();
676
+ void Promise.resolve(this.sendUserMessage(prompt)).catch((error) => {
677
+ this.autoFollowQueued = false;
678
+ const index = this.pendingAutoFollowPrompts.indexOf(prompt);
679
+ if (index >= 0) this.pendingAutoFollowPrompts.splice(index, 1);
680
+ this.lastError = `Watchdog auto-follow failed: ${errorMessage(error)}`;
681
+ });
534
682
  }
535
683
 
536
684
  private currentRepoChangeSignature(cwd = this.cwd): WatchdogRepoChangeSignature | undefined {
@@ -645,10 +793,11 @@ export class MainWatchdogRuntime {
645
793
 
646
794
  private buildReviewInput(changeSignature?: WatchdogRepoChangeSignature, lspBlock = ""): string {
647
795
  const input = this.pendingDeltas.join(REVIEW_DELTA_SEPARATOR);
796
+ const scopeBlock = this.scopeBlock();
648
797
  const changes = changeSignature?.changedPaths.length
649
798
  ? ["Changed repo paths:", ...changeSignature.changedPaths.slice(0, 200).map((file) => `- ${file}`)].join("\n")
650
799
  : "";
651
- const contextPieces = [changes, lspBlock].filter(Boolean);
800
+ const contextPieces = [scopeBlock, changes, lspBlock].filter(Boolean);
652
801
  if (!contextPieces.length) return input.length > MAX_REVIEW_INPUT_CHARS ? input.slice(-MAX_REVIEW_INPUT_CHARS) : input;
653
802
 
654
803
  const maxContextLength = Math.floor(MAX_REVIEW_INPUT_CHARS / 2);
@@ -666,6 +815,10 @@ export class MainWatchdogRuntime {
666
815
  return [boundedContext, boundedInput].filter(Boolean).join(REVIEW_DELTA_SEPARATOR);
667
816
  }
668
817
 
818
+ private scopeBlock(): string {
819
+ return this.configResult.config.scope.enabled ? this.scope.render() : "";
820
+ }
821
+
669
822
  private clearPendingDeltas(): void {
670
823
  this.pendingDeltas = [];
671
824
  this.pendingDeltaChars = 0;
@@ -0,0 +1,62 @@
1
+ export const WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER = Symbol("subagent-watchdog-auto-follow-prompt");
2
+
3
+ const MAX_SCOPE_ENTRIES = 8;
4
+ const MAX_SCOPE_ENTRY_CHARS = 2_000;
5
+ const MAX_SCOPE_TOTAL_CHARS = 16_000;
6
+
7
+ export interface WatchdogScopeEntry {
8
+ prompt: string;
9
+ createdAt: string;
10
+ }
11
+
12
+ export class WatchdogScopeArtifact {
13
+ private entries: WatchdogScopeEntry[] = [];
14
+
15
+ addPrompt(prompt: string, options: { createdAt?: string } = {}): void {
16
+ const normalized = prompt.trim();
17
+ if (!normalized) return;
18
+ this.entries.push({
19
+ prompt: normalized.length > MAX_SCOPE_ENTRY_CHARS ? normalized.slice(0, MAX_SCOPE_ENTRY_CHARS) : normalized,
20
+ createdAt: options.createdAt ?? new Date().toISOString(),
21
+ });
22
+ this.trim();
23
+ }
24
+
25
+ reset(): void {
26
+ this.entries = [];
27
+ }
28
+
29
+ snapshot(): WatchdogScopeEntry[] {
30
+ return this.entries.map((entry) => ({ ...entry }));
31
+ }
32
+
33
+ render(): string {
34
+ if (!this.entries.length) return "";
35
+ return [
36
+ "Current scope:",
37
+ "The following real user prompts are the current scope record, newest last. Newer prompts supersede and mutate older prompts: they may add, modify, or remove requirements. Flag work that serves no current scope item as category 'scope-drift'.",
38
+ ...this.entries.map((entry, index) => [
39
+ `Scope prompt ${index + 1} (${entry.createdAt}):`,
40
+ entry.prompt,
41
+ ].join("\n")),
42
+ ].join("\n\n");
43
+ }
44
+
45
+ private trim(): void {
46
+ while (this.entries.length > MAX_SCOPE_ENTRIES) this.entries.shift();
47
+ let total = this.entries.reduce((sum, entry) => sum + entry.prompt.length, 0);
48
+ while (this.entries.length > 1 && total > MAX_SCOPE_TOTAL_CHARS) {
49
+ const removed = this.entries.shift();
50
+ if (removed) total -= removed.prompt.length;
51
+ }
52
+ }
53
+ }
54
+
55
+ export function isWatchdogAutoFollowPromptEvent(event: unknown): boolean {
56
+ return Boolean(event && typeof event === "object" && (event as { [WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER]?: unknown })[WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER]);
57
+ }
58
+
59
+ export function markWatchdogAutoFollowPromptEvent<T extends object>(event: T): T {
60
+ Object.defineProperty(event, WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER, { value: true });
61
+ return event;
62
+ }
@@ -13,8 +13,10 @@ import {
13
13
  type WatchdogChildrenConfig,
14
14
  type WatchdogDeliveryMode,
15
15
  type WatchdogEndpointConfig,
16
+ type WatchdogCadenceConfig,
16
17
  type WatchdogGuidanceConfig,
17
18
  type WatchdogLateWarningPolicy,
19
+ type WatchdogScopeConfig,
18
20
  type WatchdogLspConfig,
19
21
  type WatchdogSettingsError,
20
22
  type WatchdogSettingsResult,
@@ -25,6 +27,8 @@ import {
25
27
 
26
28
  type WatchdogAutoFollowPatch = Partial<WatchdogAutoFollowConfig>;
27
29
  type WatchdogGuidancePatch = Partial<WatchdogGuidanceConfig>;
30
+ type WatchdogScopePatch = Partial<WatchdogScopeConfig>;
31
+ type WatchdogCadencePatch = Partial<WatchdogCadenceConfig>;
28
32
  type WatchdogEndpointPatch = Partial<WatchdogEndpointConfig>;
29
33
  type WatchdogChildOverridePatch = Partial<WatchdogChildOverrideConfig>;
30
34
  type WatchdogChildrenPatch = Partial<Omit<WatchdogChildrenConfig, "autoFollow" | "overrides">> & {
@@ -48,9 +52,11 @@ export interface WatchdogModelSettingsWrite {
48
52
  thinking?: ThinkingLevel | false | null;
49
53
  }
50
54
 
51
- type WatchdogConfigPatch = Partial<Omit<ResolvedWatchdogConfig, "guidance" | "autoFollow" | "main" | "children" | "asyncCompletion" | "lsp">> & {
55
+ type WatchdogConfigPatch = Partial<Omit<ResolvedWatchdogConfig, "guidance" | "autoFollow" | "scope" | "cadence" | "main" | "children" | "asyncCompletion" | "lsp">> & {
52
56
  guidance?: WatchdogGuidancePatch;
53
57
  autoFollow?: WatchdogAutoFollowPatch;
58
+ scope?: WatchdogScopePatch;
59
+ cadence?: WatchdogCadencePatch;
54
60
  main?: WatchdogEndpointPatch;
55
61
  children?: WatchdogChildrenPatch;
56
62
  asyncCompletion?: WatchdogAsyncCompletionPatch;
@@ -80,6 +86,12 @@ export const DEFAULT_WATCHDOG_CONFIG: ResolvedWatchdogConfig = {
80
86
  maxAttempts: 3,
81
87
  stalemateRepeats: 3,
82
88
  },
89
+ scope: {
90
+ enabled: true,
91
+ },
92
+ cadence: {
93
+ everyNTools: null,
94
+ },
83
95
  main: {
84
96
  enabled: false,
85
97
  },
@@ -119,6 +131,8 @@ const WATCHDOG_FIELDS = new Set([
119
131
  "maxWarnings",
120
132
  "guidance",
121
133
  "autoFollow",
134
+ "scope",
135
+ "cadence",
122
136
  "main",
123
137
  "children",
124
138
  "asyncCompletion",
@@ -129,6 +143,8 @@ const WATCHDOG_FIELDS = new Set([
129
143
  ]);
130
144
  const GUIDANCE_FIELDS = new Set(["watchdogMd", "systemPromptPath"]);
131
145
  const AUTO_FOLLOW_FIELDS = new Set(["blockers", "maxAttempts", "stalemateRepeats"]);
146
+ const SCOPE_FIELDS = new Set(["enabled"]);
147
+ const CADENCE_FIELDS = new Set(["everyNTools"]);
132
148
  const ENDPOINT_FIELDS = new Set(["enabled", "model", "thinking"]);
133
149
  const CHILDREN_FIELDS = new Set(["enabled", "model", "thinking", "watchdogTailTimeoutMs", "autoFollow", "overrides"]);
134
150
  const CHILD_OVERRIDE_FIELDS = new Set(["enabled", "model", "thinking"]);
@@ -140,6 +156,8 @@ function cloneDefaultConfig(): ResolvedWatchdogConfig {
140
156
  ...DEFAULT_WATCHDOG_CONFIG,
141
157
  guidance: { ...DEFAULT_WATCHDOG_CONFIG.guidance },
142
158
  autoFollow: { ...DEFAULT_WATCHDOG_CONFIG.autoFollow },
159
+ scope: { ...DEFAULT_WATCHDOG_CONFIG.scope },
160
+ cadence: { ...DEFAULT_WATCHDOG_CONFIG.cadence },
143
161
  main: { ...DEFAULT_WATCHDOG_CONFIG.main },
144
162
  children: {
145
163
  ...DEFAULT_WATCHDOG_CONFIG.children,
@@ -241,6 +259,26 @@ function parseAutoFollowPatch(value: unknown, field: string, meta: ParseMeta): W
241
259
  return patch;
242
260
  }
243
261
 
262
+ function parseScopePatch(value: unknown, field: string, meta: ParseMeta): WatchdogScopePatch {
263
+ const input = parseObject(value, field, meta);
264
+ assertKnownFields(input, SCOPE_FIELDS, field, meta);
265
+ const patch: WatchdogScopePatch = {};
266
+ if ("enabled" in input) patch.enabled = parseBoolean(input.enabled, `${field}.enabled`, meta);
267
+ return patch;
268
+ }
269
+
270
+ function parseCadencePatch(value: unknown, field: string, meta: ParseMeta): WatchdogCadencePatch {
271
+ const input = parseObject(value, field, meta);
272
+ assertKnownFields(input, CADENCE_FIELDS, field, meta);
273
+ const patch: WatchdogCadencePatch = {};
274
+ if ("everyNTools" in input) {
275
+ patch.everyNTools = input.everyNTools === null
276
+ ? null
277
+ : parseInteger(input.everyNTools, `${field}.everyNTools`, meta, "null or an integer >= 5", (candidate) => candidate >= 5);
278
+ }
279
+ return patch;
280
+ }
281
+
244
282
  function parseEndpointPatch(value: unknown, field: string, meta: ParseMeta): WatchdogEndpointPatch {
245
283
  const input = parseObject(value, field, meta);
246
284
  assertKnownFields(input, ENDPOINT_FIELDS, field, meta);
@@ -325,6 +363,8 @@ function parseWatchdogPatch(value: unknown, field: string, meta: ParseMeta): Wat
325
363
  }
326
364
  if ("guidance" in input) patch.guidance = parseGuidancePatch(input.guidance, `${field}.guidance`, meta);
327
365
  if ("autoFollow" in input) patch.autoFollow = parseAutoFollowPatch(input.autoFollow, `${field}.autoFollow`, meta);
366
+ if ("scope" in input) patch.scope = parseScopePatch(input.scope, `${field}.scope`, meta);
367
+ if ("cadence" in input) patch.cadence = parseCadencePatch(input.cadence, `${field}.cadence`, meta);
328
368
  if ("main" in input) patch.main = parseEndpointPatch(input.main, `${field}.main`, meta);
329
369
  if ("children" in input) patch.children = parseChildrenPatch(input.children, `${field}.children`, meta);
330
370
  if ("asyncCompletion" in input) patch.asyncCompletion = parseAsyncCompletionPatch(input.asyncCompletion, `${field}.asyncCompletion`, meta);
@@ -92,6 +92,14 @@ export interface WatchdogGuidanceConfig {
92
92
  systemPromptPath: string | null;
93
93
  }
94
94
 
95
+ export interface WatchdogScopeConfig {
96
+ enabled: boolean;
97
+ }
98
+
99
+ export interface WatchdogCadenceConfig {
100
+ everyNTools: number | null;
101
+ }
102
+
95
103
  export interface WatchdogEndpointConfig {
96
104
  enabled: boolean;
97
105
  model?: string;
@@ -159,6 +167,8 @@ export interface ResolvedWatchdogConfig {
159
167
  maxWarnings: number | null;
160
168
  guidance: WatchdogGuidanceConfig;
161
169
  autoFollow: WatchdogAutoFollowConfig;
170
+ scope: WatchdogScopeConfig;
171
+ cadence: WatchdogCadenceConfig;
162
172
  main: WatchdogEndpointConfig;
163
173
  children: WatchdogChildrenConfig;
164
174
  asyncCompletion: WatchdogAsyncCompletionConfig;
@@ -191,12 +191,12 @@ Report active tools.`;
191
191
 
192
192
  try {
193
193
  run = await runRealSubagentSession({
194
- prompt: "Delegate to a worker and report its exact result.",
194
+ prompt: "Delegate to a builder and report its exact result.",
195
195
  childText: CHILD_MARKER,
196
196
  respond: routeParentThroughSubagent({
197
197
  childMarker: CHILD_MARKER,
198
198
  subagentArgs: {
199
- agent: "worker",
199
+ agent: "builder",
200
200
  task: "Return the marker from the faux child provider.",
201
201
  context: "fresh",
202
202
  agentScope: "project",