@zhushanwen/subagent-core 0.5.1 → 0.7.0

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 (318) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-KXVBIVOU.js +16 -0
  3. package/dist/chunk-T2SYBW3I.js +24 -0
  4. package/dist/chunk-VURUAGMM.js +2305 -0
  5. package/dist/{types-Dv4QhSJ_.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +835 -668
  6. package/dist/{types-Dv4QhSJ_.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +835 -668
  7. package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
  8. package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
  9. package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
  10. package/dist/execution/engine/engine-discovery-scan.js +20 -0
  11. package/dist/execution/engine/paths.cjs +6 -23
  12. package/dist/execution/engine/paths.d.cts +1 -8
  13. package/dist/execution/engine/paths.d.ts +1 -8
  14. package/dist/execution/engine/paths.js +1 -1
  15. package/dist/execution/relay-env.cjs +12 -28
  16. package/dist/execution/relay-env.d.cts +1 -33
  17. package/dist/execution/relay-env.d.ts +1 -33
  18. package/dist/execution/relay-env.js +5 -3
  19. package/dist/index.cjs +14123 -15467
  20. package/dist/index.d.cts +1179 -1540
  21. package/dist/index.d.ts +1179 -1540
  22. package/dist/index.js +7694 -10986
  23. package/dist.bundle/index.cjs +33485 -0
  24. package/package.json +20 -26
  25. package/src/__tests__/record-store-last-line.test.ts +16 -7
  26. package/src/core/error-message.ts +7 -6
  27. package/src/core/host-services.ts +8 -2
  28. package/src/core/notify-ports.ts +17 -2
  29. package/src/execution/__tests__/agent-registry.test.ts +1 -1
  30. package/src/execution/__tests__/alive-store.test.ts +1 -1
  31. package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
  32. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
  33. package/src/execution/__tests__/collect-budget.test.ts +291 -0
  34. package/src/execution/__tests__/collect-coordinator-service.test.ts +316 -0
  35. package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
  36. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +229 -0
  37. package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
  38. package/src/execution/__tests__/config.test.ts +1 -1
  39. package/src/execution/__tests__/delivery-methods.test.ts +179 -237
  40. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
  41. package/src/execution/__tests__/execute-nesting.test.ts +20 -13
  42. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +21 -34
  43. package/src/execution/__tests__/finalized-marker.test.ts +1 -1
  44. package/src/execution/__tests__/gc-timer.test.ts +8 -23
  45. package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
  46. package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
  47. package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
  48. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
  49. package/src/execution/__tests__/idle-gc.test.ts +200 -0
  50. package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
  51. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
  52. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
  53. package/src/execution/__tests__/notify-batch.test.ts +500 -0
  54. package/src/execution/__tests__/notify-ledger.test.ts +27 -0
  55. package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
  56. package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
  57. package/src/execution/__tests__/record-store.test.ts +60 -6
  58. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
  59. package/src/execution/__tests__/relay-env.test.ts +12 -1
  60. package/src/execution/__tests__/round-supervisor.test.ts +293 -0
  61. package/src/execution/__tests__/session-file-gc.test.ts +1 -1
  62. package/src/execution/__tests__/session-pending.test.ts +119 -17
  63. package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
  64. package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
  65. package/src/execution/__tests__/subagent-actions-core.test.ts +6 -0
  66. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +14 -11
  67. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
  68. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
  69. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
  70. package/src/execution/__tests__/subagent-service.test.ts +2 -2
  71. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
  72. package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
  73. package/src/execution/__tests__/sync-collect-recovery.test.ts +1102 -0
  74. package/src/execution/__tests__/tombstone-store.test.ts +1 -1
  75. package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
  76. package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
  77. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
  78. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
  79. package/src/execution/__tests__/worktree-registry.test.ts +1 -1
  80. package/src/execution/agent-registry.ts +6 -2
  81. package/src/execution/collect-coordinator.ts +200 -0
  82. package/src/execution/config.ts +77 -5
  83. package/src/execution/dialog-queue.ts +6 -73
  84. package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
  85. package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
  86. package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
  87. package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
  88. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
  89. package/src/execution/engine/__tests__/common/pool-manager.test.ts +2 -2
  90. package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
  91. package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
  92. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
  93. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
  94. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
  95. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
  96. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
  97. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
  98. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
  99. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +82 -55
  100. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
  101. package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
  102. package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
  103. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +8 -3
  104. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
  105. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
  106. package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
  107. package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
  108. package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
  109. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
  110. package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
  111. package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
  112. package/src/execution/engine/__tests__/registry.test.ts +206 -1
  113. package/src/execution/engine/__tests__/routing.test.ts +97 -0
  114. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
  115. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
  116. package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
  117. package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
  118. package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
  119. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
  120. package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
  121. package/src/execution/engine/client/client-options.ts +103 -0
  122. package/src/execution/engine/client/engine-client.ts +687 -0
  123. package/src/execution/engine/client/mirror.ts +167 -0
  124. package/src/execution/engine/client/pid-file.ts +392 -0
  125. package/src/execution/engine/client/reaper.ts +95 -0
  126. package/src/execution/engine/client/remote-engine.ts +441 -0
  127. package/src/execution/engine/client/reverse-router.ts +255 -0
  128. package/src/execution/engine/common/capability-gate.ts +109 -22
  129. package/src/execution/engine/common/errors.ts +9 -25
  130. package/src/execution/engine/common/event-journal.ts +4 -50
  131. package/src/execution/engine/common/journal-replay.ts +3 -1
  132. package/src/execution/engine/common/kill-chain.ts +18 -251
  133. package/src/execution/engine/common/nesting-guard.ts +18 -114
  134. package/src/execution/engine/common/pool-manager.ts +4 -0
  135. package/src/execution/engine/common/session-view-service.ts +56 -84
  136. package/src/execution/engine/config.ts +151 -0
  137. package/src/execution/engine/d8-compat.ts +346 -0
  138. package/src/execution/engine/engine-discovery-roots.ts +107 -0
  139. package/src/execution/engine/engine-discovery-scan.ts +269 -0
  140. package/src/execution/engine/engine-discovery.ts +30 -7
  141. package/src/execution/engine/engine-inspect-package.ts +282 -0
  142. package/src/execution/engine/engine-manifest.ts +244 -0
  143. package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
  144. package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
  145. package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
  146. package/src/execution/engine/host/host-bridge.ts +150 -0
  147. package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
  148. package/src/execution/engine/host/pi-host-binding.ts +91 -0
  149. package/src/execution/engine/host/spawned-children.ts +139 -0
  150. package/src/execution/engine/host-task-spec.ts +29 -2
  151. package/src/execution/engine/model-validation.ts +55 -2
  152. package/src/execution/engine/paths.ts +16 -41
  153. package/src/execution/engine/port.ts +48 -2
  154. package/src/execution/engine/registry.ts +153 -34
  155. package/src/execution/engine/routing.ts +225 -52
  156. package/src/execution/engine/types.ts +25 -200
  157. package/src/execution/execution-record.ts +7 -0
  158. package/src/execution/finalize-record.ts +40 -11
  159. package/src/execution/idle-gc.ts +89 -14
  160. package/src/execution/lifecycle-manager.ts +10 -7
  161. package/src/execution/lifecycle-predicates.ts +10 -8
  162. package/src/execution/notifier.ts +234 -25
  163. package/src/execution/notify-host.ts +21 -1
  164. package/src/execution/record-entry.ts +16 -0
  165. package/src/execution/record-store.ts +189 -31
  166. package/src/execution/relay-env.ts +19 -36
  167. package/src/execution/round-supervisor/domain.ts +89 -0
  168. package/src/execution/round-supervisor/index.ts +33 -0
  169. package/src/execution/round-supervisor/notify-accounting.ts +87 -0
  170. package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
  171. package/src/execution/round-supervisor/service-binding.test.ts +661 -0
  172. package/src/execution/round-supervisor/service-binding.ts +273 -0
  173. package/src/execution/round-supervisor/supervisor.ts +426 -0
  174. package/src/execution/session-pending.ts +68 -74
  175. package/src/execution/settled-watchdog.ts +39 -0
  176. package/src/execution/subagent-actions-core.ts +62 -6
  177. package/src/execution/subagent-service.ts +1161 -406
  178. package/src/execution/subprocess-agent-runner.ts +16 -8
  179. package/src/execution/sync-rebuild.ts +87 -0
  180. package/src/execution/types.ts +104 -117
  181. package/src/execution/ui-channels.ts +13 -214
  182. package/src/execution/ui-request-handler-factory.ts +7 -4
  183. package/src/execution/ui-request-observability.ts +2 -2
  184. package/src/execution/workflow-state-root.ts +67 -0
  185. package/src/execution/worktree-git-ops.ts +5 -0
  186. package/src/execution/worktree-manager.ts +11 -1
  187. package/src/index.ts +55 -26
  188. package/src/orchestration/__tests__/config-loader.test.ts +1 -1
  189. package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
  190. package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
  191. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
  192. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
  193. package/src/orchestration/__tests__/script-generate.test.ts +5 -5
  194. package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
  195. package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
  196. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
  197. package/src/orchestration/execute-agent-call.ts +1 -1
  198. package/src/orchestration/file-run-store.ts +144 -59
  199. package/src/orchestration/models/types.ts +43 -42
  200. package/src/shared/__tests__/atomic-write.test.ts +1 -1
  201. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
  202. package/src/shared/zcode-model-ref.ts +31 -0
  203. package/dist/chunk-43ONBFZX.js +0 -240
  204. package/dist/chunk-A4IVZWVX.js +0 -31
  205. package/dist/chunk-APZY4IME.js +0 -27
  206. package/dist/chunk-V3VHZ2VX.js +0 -59
  207. package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
  208. package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
  209. package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
  210. package/dist/execution/engine/engines/zcode/constants.js +0 -54
  211. package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
  212. package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
  213. package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
  214. package/dist/execution/engine/engines/zcode/reader.js +0 -9
  215. package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
  216. package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
  217. package/src/__tests__/session-runner.test.ts +0 -69
  218. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  219. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
  220. package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
  221. package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
  222. package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
  223. package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
  224. package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
  225. package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
  226. package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
  227. package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
  228. package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
  229. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
  230. package/src/execution/__tests__/output-collector.test.ts +0 -469
  231. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  232. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
  233. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  234. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
  235. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
  236. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
  237. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
  238. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  239. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  240. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  241. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
  242. package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
  243. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
  244. package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
  245. package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
  246. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
  247. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
  248. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
  249. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
  250. package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
  251. package/src/execution/__tests__/spawn-args.test.ts +0 -446
  252. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
  253. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  254. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
  255. package/src/execution/__tests__/spawned-children.test.ts +0 -236
  256. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  257. package/src/execution/__tests__/stdin-writer.test.ts +0 -464
  258. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
  259. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  260. package/src/execution/__tests__/timeout-integration.test.ts +0 -616
  261. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  262. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  263. package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
  264. package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
  265. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
  266. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  267. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
  268. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  269. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
  270. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  271. package/src/execution/engine/common/schema-emulation.ts +0 -189
  272. package/src/execution/engine/common/session-view-projection.ts +0 -51
  273. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
  274. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  275. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
  276. package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
  277. package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
  278. package/src/execution/engine/engines/pi/output-collector.ts +0 -317
  279. package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
  280. package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
  281. package/src/execution/engine/engines/pi/reader.ts +0 -59
  282. package/src/execution/engine/engines/pi/registration.ts +0 -37
  283. package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
  284. package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
  285. package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
  286. package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
  287. package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
  288. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
  289. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
  290. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
  291. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
  292. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
  293. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
  294. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  295. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
  296. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
  297. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
  298. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
  299. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
  300. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
  301. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
  302. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
  303. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
  304. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
  305. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
  306. package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
  307. package/src/execution/engine/engines/zcode/connection.ts +0 -598
  308. package/src/execution/engine/engines/zcode/constants.ts +0 -176
  309. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
  310. package/src/execution/engine/engines/zcode/parser.ts +0 -102
  311. package/src/execution/engine/engines/zcode/preparer.ts +0 -235
  312. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  313. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  314. package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
  315. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
  316. package/src/execution/round-settlement.ts +0 -93
  317. package/src/execution/ui-request-queue.ts +0 -215
  318. package/src/shared/schema-env.ts +0 -44
@@ -0,0 +1,255 @@
1
+ // src/execution/__tests__/start-collect-guard.test.ts
2
+ //
3
+ // startHandler 的 collect 语义(subagent-sync-collect U1 foundation):
4
+ // 1. E4 校验(设计 §3.1.5):conversation:true + collect:"sync" → immediate throw,
5
+ // 不产生半启动 record(execute 零调用);文案指引「sync 仅支持 one-shot,
6
+ // 去掉 conversation 或 collect」;
7
+ // 2. 合法组合放行:collect 透传 service.execute(ExecuteOptions.collect);
8
+ // 3. start 响应 collect 段(设计 §3.1.1):仅 resolved=sync 附段(async 响应字节
9
+ // 零变化,G3);pendingSyncCount = 未闭合批 sync 成员数(collectMode=sync 且无
10
+ // batchFinalized;U2 偏差#4 接线后 record 落 collectMode,枚举天然含本条,无 +1)。
11
+ //
12
+ // stub SubagentService 仅实现 handler 触达的方法子集(subagent-actions-core.test.ts
13
+ // 同款形态);真实 service 行为归属 subagent-service 各自测试。
14
+
15
+ import { describe, expect, it, vi, type Mock } from "vitest";
16
+
17
+ import { startHandler } from "../subagent-actions-core.ts";
18
+ // SubagentService 的权威源是 subagent-service.ts(types.ts 只有 record/tool 契约)
19
+ import type { SubagentService } from "../subagent-service.ts";
20
+ import type { StatusFilter } from "../record-store.ts";
21
+ import type {
22
+ ExecutionHandle,
23
+ SubagentRecord,
24
+ SubagentToolDetails,
25
+ } from "../types.ts";
26
+
27
+ function makeDetails(): SubagentToolDetails {
28
+ return {
29
+ status: "running",
30
+ mode: "background",
31
+ agent: "/home/u/agents/worker.md",
32
+ model: "prov/m1",
33
+ thinkingLevel: undefined,
34
+ slug: "src-slug",
35
+ turns: 0,
36
+ totalTokens: 0,
37
+ elapsedSeconds: 0,
38
+ eventLog: [],
39
+ displayItems: [],
40
+ result: undefined,
41
+ error: undefined,
42
+ } as SubagentToolDetails;
43
+ }
44
+
45
+ function makeHandle(): ExecutionHandle {
46
+ return { mode: "background", subagentId: "sa-new", sessionFile: undefined, details: makeDetails() };
47
+ }
48
+
49
+ /** collectRecords stub 数据行(只含 pendingSyncCount 口径判读所需字段)。 */
50
+ function makeRec(over: Partial<SubagentRecord> = {}): SubagentRecord {
51
+ return {
52
+ id: "sa-1",
53
+ agent: "/home/u/agents/worker.md",
54
+ task: "t",
55
+ slug: "worker",
56
+ status: "running",
57
+ mode: "background",
58
+ startedAt: 1000,
59
+ rootSessionId: "root-A",
60
+ parentRecordId: undefined,
61
+ depth: 0,
62
+ endedAt: undefined,
63
+ turns: 1,
64
+ totalTokens: 42,
65
+ model: "prov/m1",
66
+ thinkingLevel: undefined,
67
+ eventLog: [],
68
+ displayItems: [],
69
+ ...over,
70
+ } as SubagentRecord;
71
+ }
72
+
73
+ // Mock<T> 具名签名 + Omit 类原生同名成员:ReturnType<typeof vi.fn>
74
+ // (= Mock<Procedure | Constructable>)与类方法签名交叉会收窄 never
75
+ type ServiceStub = Omit<SubagentService, "execute" | "collectRecords" | "getCollectSyncDefault"> & {
76
+ // 带首参形态:断言消费 execute.mock.calls[0][0](ExecuteOptions),零参签名为空元组取不到
77
+ execute: Mock<(opts: Record<string, unknown>) => Promise<SubagentRecord>>;
78
+ collectRecords: Mock<(limit: number, statusFilter?: StatusFilter) => SubagentRecord[]>;
79
+ getCollectSyncDefault: Mock<() => "async" | "sync">;
80
+ };
81
+
82
+ /** startHandler 的测试包装:stub → SubagentService 断言收口一处(类私有成员不可结构模拟)。 */
83
+ function sh(svc: ServiceStub, input: Record<string, unknown>, signal?: AbortSignal) {
84
+ return startHandler(
85
+ svc as unknown as SubagentService,
86
+ input as Parameters<typeof startHandler>[1],
87
+ signal ?? undefined,
88
+ );
89
+ }
90
+
91
+ function makeService(
92
+ collectRecordsReturn: SubagentRecord[] = [],
93
+ collectSyncDefault: "async" | "sync" = "async",
94
+ ): ServiceStub {
95
+ const execute = vi.fn(async (_opts: Record<string, unknown>) => makeHandle());
96
+ const collectRecords = vi.fn(() => collectRecordsReturn);
97
+ const getCollectSyncDefault = vi.fn(() => collectSyncDefault);
98
+ // [D4-① 适配] countPendingSyncRecords 经查询面聚合读 collectRecords(dev 重构后
99
+ // service.collectRecords 收窄 private,public 出口 = service.queries.collectRecords)。
100
+ return {
101
+ execute,
102
+ queries: { collectRecords },
103
+ collectRecords,
104
+ getCollectSyncDefault,
105
+ } as unknown as ServiceStub;
106
+ }
107
+
108
+ const BASE_INPUT = { task: "do things", slug: "do-things" };
109
+
110
+ // ============================================================
111
+ // E4:conversation + collect:"sync" 即拒
112
+ // ============================================================
113
+
114
+ describe("startHandler E4 guard (conversation + collect:sync)", () => {
115
+ it("throws immediately and never calls execute (不产生半启动 record)", async () => {
116
+ const service = makeService();
117
+ await expect(
118
+ sh(service, { ...BASE_INPUT, conversation: true, collect: "sync" }, undefined),
119
+ ).rejects.toThrow();
120
+ expect(service.execute).not.toHaveBeenCalled();
121
+ });
122
+
123
+ it("error copy carries the design guidance verbatim (文案锚定)", async () => {
124
+ const service = makeService();
125
+ const err = await sh(service,
126
+ { ...BASE_INPUT, conversation: true, collect: "sync" },
127
+ undefined,
128
+ ).catch((e: unknown) => e as Error);
129
+ expect(err).toBeInstanceOf(Error);
130
+ expect((err as Error).message).toBe(
131
+ 'collect:"sync" only supports one-shot subagents — it cannot be combined with conversation:true. ' +
132
+ 'Remove either conversation or collect (use collect:"async", or omit it, for conversational subagents).',
133
+ );
134
+ });
135
+
136
+ it("allows conversation:true + collect:async (async 语义与 conversation 正交)", async () => {
137
+ const service = makeService();
138
+ const result = await sh(service,
139
+ { ...BASE_INPUT, conversation: true, collect: "async" },
140
+ undefined,
141
+ );
142
+ expect(result.subagentId).toBe("sa-new");
143
+ expect(service.execute).toHaveBeenCalledTimes(1);
144
+ });
145
+
146
+ it("allows collect:sync alone (one-shot sync 是合法主场景)", async () => {
147
+ const service = makeService();
148
+ const result = await sh(service, { ...BASE_INPUT, collect: "sync" }, undefined);
149
+ expect(result.subagentId).toBe("sa-new");
150
+ expect(service.execute).toHaveBeenCalledTimes(1);
151
+ });
152
+
153
+ it("E4 also blocks conversation when config default is sync (偏差#3 接线:resolved 含 config 默认)", async () => {
154
+ const service = makeService([], "sync");
155
+ await expect(
156
+ sh(service, { ...BASE_INPUT, conversation: true }, undefined),
157
+ ).rejects.toThrow('collect:"sync" only supports one-shot subagents');
158
+ expect(service.execute).not.toHaveBeenCalled();
159
+ });
160
+
161
+ it("config default=sync applies when collect omitted (缺省读真实 config,U2 偏差#3)", async () => {
162
+ const service = makeService([], "sync");
163
+ const result = await sh(service, { ...BASE_INPUT }, undefined);
164
+ expect(result.response.collect).toBeDefined();
165
+ expect(service.getCollectSyncDefault).toHaveBeenCalledTimes(1);
166
+ });
167
+
168
+ it("reads config default via service accessor when collect omitted (async 默认零附段)", async () => {
169
+ const service = makeService([], "async");
170
+ const result = await sh(service, { ...BASE_INPUT }, undefined);
171
+ expect(result.response.collect).toBeUndefined();
172
+ expect(service.getCollectSyncDefault).toHaveBeenCalledTimes(1);
173
+ });
174
+ });
175
+
176
+ // ============================================================
177
+ // collect 透传 + 响应 collect 段
178
+ // ============================================================
179
+
180
+ describe("startHandler collect forwarding + response collect segment", () => {
181
+ it("forwards collect to service.execute via ExecuteOptions.collect", async () => {
182
+ const service = makeService();
183
+ await sh(service, { ...BASE_INPUT, collect: "sync" }, undefined);
184
+ const opts = service.execute.mock.calls[0]?.[0] as { collect?: string };
185
+ expect(opts.collect).toBe("sync");
186
+ });
187
+
188
+ it("omits collect in ExecuteOptions when not provided (resolved≠sync 时保持 undefined,async 缺省语义)", async () => {
189
+ const service = makeService();
190
+ await sh(service, { ...BASE_INPUT }, undefined);
191
+ const opts = service.execute.mock.calls[0]?.[0] as { collect?: string };
192
+ expect(opts.collect).toBeUndefined();
193
+ });
194
+
195
+ it("B1:config default=sync + 省略 collect → execute 收 collect:\"sync\"(缺省解析作用于 record 本体)", async () => {
196
+ // 修复前:execute 收原始 input.collect=undefined → createRecordForMode 只认
197
+ // ==="sync" → record 走 async 逐条通知而响应声称已入批(设计 §3.1.3/types.ts:689
198
+ // 承诺「缺省 = config 默认」作用于 record)。修复后 resolved=sync 落值。
199
+ const service = makeService([], "sync");
200
+ await sh(service, { ...BASE_INPUT }, undefined);
201
+ const opts = service.execute.mock.calls[0]?.[0] as { collect?: string };
202
+ expect(opts.collect).toBe("sync");
203
+ });
204
+
205
+ it("B1:config default=sync 时显式 collect:\"async\" 优先(execute 收 \"async\")", async () => {
206
+ const service = makeService([], "sync");
207
+ await sh(service, { ...BASE_INPUT, collect: "async" }, undefined);
208
+ const opts = service.execute.mock.calls[0]?.[0] as { collect?: string };
209
+ expect(opts.collect).toBe("async");
210
+ });
211
+
212
+ it("attaches collect segment counting this very record from the enumeration (U2 偏差#4:无 +1 补偿)", async () => {
213
+ // 本条 record(id=sa-new)已由 createRecordForMode 落 collectMode 入枚举:
214
+ // stub 枚举返回本条 + 另一未闭合 sync → count=2(无 +1 补偿即含本条)
215
+ const service = makeService([
216
+ makeRec({ id: "sa-new", collectMode: "sync" }),
217
+ makeRec({ id: "sa-other", collectMode: "sync", status: "running" }),
218
+ makeRec({ id: "sa-gone", collectMode: "sync", batchFinalized: true }),
219
+ ]);
220
+ const result = await sh(service, { ...BASE_INPUT, collect: "sync" }, undefined);
221
+ expect(result.response.collect).toEqual({ mode: "sync", pendingSyncCount: 2 });
222
+ });
223
+
224
+ it("reports the enumeration verbatim when no sync records exist yet (如实反映,无补偿)", async () => {
225
+ const service = makeService([]);
226
+ const result = await sh(service, { ...BASE_INPUT, collect: "sync" }, undefined);
227
+ expect(result.response.collect).toEqual({ mode: "sync", pendingSyncCount: 0 });
228
+ });
229
+
230
+ it("counts pending unmarked sync members from the enumeration (跨轮续累口径)", async () => {
231
+ const service = makeService([
232
+ makeRec({ id: "sa-1", collectMode: "sync" }), // 未闭合(无 batchFinalized)→ 计入
233
+ makeRec({ id: "sa-2", collectMode: "sync", batchFinalized: true }), // 已离场 → 排除
234
+ makeRec({ id: "sa-3" }), // async → 排除
235
+ makeRec({ id: "sa-4", collectMode: "sync", batchFinalized: false }), // 显式 false → 计入
236
+ ]);
237
+ const result = await sh(service, { ...BASE_INPUT, collect: "sync" }, undefined);
238
+ expect(result.response.collect).toEqual({ mode: "sync", pendingSyncCount: 2 });
239
+ });
240
+
241
+ it("omits the collect segment for async starts (G3: async 响应字节零变化)", async () => {
242
+ for (const input of [{ ...BASE_INPUT }, { ...BASE_INPUT, collect: "async" as const }]) {
243
+ const service = makeService();
244
+ const result = await sh(service, input, undefined);
245
+ expect(result.response.collect).toBeUndefined();
246
+ // G3 字节锚:response 其余字段与既有形态全等
247
+ expect(result.response).toEqual({
248
+ status: "running",
249
+ mode: "background",
250
+ message: result.response.message,
251
+ notifyContract: "ledger+at-least-once",
252
+ });
253
+ }
254
+ });
255
+ });
@@ -103,14 +103,6 @@ vi.mock("../manifest-store.ts", () => {
103
103
  return { ManifestStore: vi.fn(function (_recordsDir: string) { return new FakeManifestStore(); }) };
104
104
  });
105
105
 
106
- vi.mock("../engine/engines/pi/temp-prompt.ts", () => ({
107
- writePromptToTempFile: vi.fn(async (agent: string) => {
108
- const safeName = agent.replace(/[^\w.-]+/g, "_");
109
- return { dir: `/tmp/fake-${safeName}`, filePath: `/tmp/fake-${safeName}/prompt-${safeName}.md` };
110
- }),
111
- cleanupTempPrompt: vi.fn(async () => {}),
112
- }));
113
-
114
106
  import { spawn } from "node:child_process";
115
107
 
116
108
  import { ModelConfigService } from "../model-config-service.ts";
@@ -233,6 +225,11 @@ describe("退役步骤 2 判定层:createBackgroundStream", () => {
233
225
  });
234
226
 
235
227
  // ── 接线层:service → 工厂的参数透传(mode 传错 = 判定失效)──
228
+ // [W3 改写] 驱动方式从 inproc spawn(FakeChild close)改为协议 seam
229
+ //(registerFakePiEngine 替身)——kickOffChatRound 的 stream 创建先于 pool acquire,
230
+ // 替身 run 挂起即可观察工厂入参。
231
+ import { registerFakePiEngine } from "./helpers/fake-engine-port.ts";
232
+ import { clearEngines } from "../engine/registry.ts";
236
233
 
237
234
  describe("退役步骤 2 接线层:kickOffChatRound 透传 mode/sink 给工厂", () => {
238
235
  beforeEach(() => {
@@ -242,6 +239,7 @@ describe("退役步骤 2 接线层:kickOffChatRound 透传 mode/sink 给工厂
242
239
 
243
240
  afterEach(() => {
244
241
  for (const key of RELAY_ENV_KEYS) delete process.env[key];
242
+ clearEngines();
245
243
  vi.restoreAllMocks();
246
244
  });
247
245
 
@@ -250,9 +248,11 @@ describe("退役步骤 2 接线层:kickOffChatRound 透传 mode/sink 给工厂
250
248
  ["tui", "tui"],
251
249
  ["undefined(headless)", undefined],
252
250
  ])("mode=%s:工厂收到 initSession 注入的 mode 与 streamSink", async (_label, mode) => {
251
+ clearEngines();
252
+ registerFakePiEngine();
253
253
  const service = setupService(mode);
254
- await executeBackground(service);
255
- expect(mockCreateStream).toHaveBeenCalledTimes(1);
254
+ await service.execute({ task: "retire test", slug: "test", ctxModel, conversation: true });
255
+ await vi.waitFor(() => expect(mockCreateStream).toHaveBeenCalledTimes(1));
256
256
  const [recordId, sinkArg, modeArg] = mockCreateStream.mock.calls[0]!;
257
257
  expect(typeof recordId).toBe("string");
258
258
  expect(sinkArg).toHaveProperty("setWidget");
@@ -144,11 +144,17 @@ function makeService(over: Record<string, unknown> = {}): SubagentService {
144
144
  getRecordForAction: vi.fn(),
145
145
  closeSubagent: vi.fn(),
146
146
  deliverChatMessage: vi.fn(),
147
+ // [U2] startHandler 缺省 collect 解析读真实 config(偏差#3 接线):stub 缺省 async
148
+ //(本文件不测 collect 语义,专项见 start-collect-guard.test.ts)。
149
+ getCollectSyncDefault: vi.fn(() => "async" as const),
147
150
  ...over,
148
151
  };
149
152
  return {
150
153
  execute: m.execute,
151
154
  cancel: m.cancel,
155
+ // [U2 偏差#3 接线] startHandler 经平铺访问器读 config 缺省 collect(真实 service
156
+ // 为平铺方法 subagent-service.ts:1786,非 queries 聚合面成员),stub 须同构挂载。
157
+ getCollectSyncDefault: m.getCollectSyncDefault,
152
158
  queries: {
153
159
  findRecord: m.findRecord,
154
160
  lookupRecordAnyState: m.lookupRecordAnyState,
@@ -21,8 +21,7 @@ const { loggerMock } = vi.hoisted(() => ({
21
21
  }));
22
22
  vi.mock("../../core/logger.ts", () => ({ getLogger: () => loggerMock }));
23
23
 
24
- const { killChildSpy, foreignLiveSpy } = vi.hoisted(() => ({
25
- killChildSpy: vi.fn(),
24
+ const { foreignLiveSpy } = vi.hoisted(() => ({
26
25
  foreignLiveSpy: vi.fn<() => { pid: number; id: string; startedAt: number } | undefined>(),
27
26
  }));
28
27
  vi.mock("../alive-store.ts", () => ({
@@ -34,15 +33,6 @@ vi.mock("../alive-store.ts", () => ({
34
33
  findForeignLiveInstance: foreignLiveSpy,
35
34
  }));
36
35
 
37
- vi.mock("../engine/engines/pi/session-runner.ts", () => ({
38
- runSpawn: vi.fn(),
39
- killAllSpawnedChildren: vi.fn(),
40
- getChildByRecord: vi.fn(() => undefined),
41
- registerSpawnedChildForRecord: vi.fn(),
42
- spawnedChildren: new Map(),
43
- killRecordChildWithEscalation: killChildSpy,
44
- }));
45
-
46
36
  import { ModelConfigService } from "../model-config-service.ts";
47
37
  import type { RecordStore } from "../record-store.ts";
48
38
  import { SubagentService } from "../subagent-service.ts";
@@ -120,6 +110,19 @@ describe("T5③ cold-lookup running candidate foreign-instance guard", () => {
120
110
  let store: RecordStore;
121
111
 
122
112
  beforeEach(() => {
113
+ // 身份 env 剥离:initSession 会把 PI_SUBAGENT_ROOT_SESSION_ID 读作 sessionRootId 基线
114
+ //(env 优先于入参 sessionId)——宿主进程(xyz-agent 子 agent 环境)泄漏的身份 env
115
+ // 会让「root-session」桩记录归属校验恒不匹配 → 冷查用例误红(与 collect-coordinator-
116
+ // service.test.ts 同款剥离纪律)。
117
+ for (const k of [
118
+ "PI_SUBAGENT_ROOT_SESSION_ID",
119
+ "PI_SUBAGENT_SELF_RECORD_ID",
120
+ "PI_SUBAGENT_DEPTH",
121
+ "PI_SUBAGENT_ROOT_CWD",
122
+ "PI_SUBAGENT_FORK_DEPTH",
123
+ ] as const) {
124
+ delete process.env[k];
125
+ }
123
126
  foreignLiveSpy.mockReset();
124
127
  foreignLiveSpy.mockReturnValue(undefined);
125
128
  ({ agentDir, service, store } = setup());
@@ -22,16 +22,10 @@ const { loggerMock } = vi.hoisted(() => ({
22
22
  }));
23
23
  vi.mock("../../core/logger.ts", () => ({ getLogger: () => loggerMock }));
24
24
 
25
- const { killChildSpy } = vi.hoisted(() => ({ killChildSpy: vi.fn() }));
26
- vi.mock("../engine/engines/pi/session-runner.ts", () => ({
27
- runSpawn: vi.fn(),
28
- killAllSpawnedChildren: vi.fn(),
29
- getChildByRecord: vi.fn(() => undefined),
30
- registerSpawnedChildForRecord: vi.fn(),
31
- spawnedChildren: new Map(),
32
- killRecordChildWithEscalation: killChildSpy,
33
- }));
34
-
25
+ // [W3 改写] vi.mock(inproc pi 引擎目录/session-runner) 随删件消亡——chat 轮次走协议 seam
26
+ //(registerFakePiEngine 替身,kickOffChatRound 的 notify 门经 engine.run 应答驱动)。
27
+ import { registerFakePiEngine } from "./helpers/fake-engine-port.ts";
28
+ import { clearEngines } from "../engine/registry.ts";
35
29
  import { bindNotifyLedgerHost, NOTIFY_LEDGER_CUSTOM_TYPE, _resetNotifyLedgerForTest } from "../notify-ledger.ts";
36
30
  import { createRecord } from "../execution-record.ts";
37
31
  import { ModelConfigService } from "../model-config-service.ts";
@@ -95,8 +89,10 @@ describe("T4① notify gate closedReason whitelist", () => {
95
89
  expect(notifyGateAllowsDelivery(undefined)).toBe(true);
96
90
  });
97
91
 
98
- it("kickOffChatRound.then does not inject parent-new closed records into the session", async () => {
92
+ it("kickOffChatRound 应答回注不注入 parent-new closed records(notify 门白名单)", async () => {
99
93
  const { agentDir, service, pi } = setup();
94
+ clearEngines();
95
+ const fake = registerFakePiEngine();
100
96
  const record = createRecord("sa-gate-new", {
101
97
  agent: "general-purpose",
102
98
  model: "test/model",
@@ -107,34 +103,33 @@ describe("T4① notify gate closedReason whitelist", () => {
107
103
  rootSessionId: "root-session",
108
104
  controller: new AbortController(),
109
105
  });
110
- // 模拟 disposeAllRecords 先行编排性关闭后,迟到的 kickOffChatRound.then 回注
106
+ // 模拟 disposeAllRecords 先行编排性关闭后,迟到的 kickOffChatRound 应答回注
111
107
  record.closedReason = "parent-new";
112
- const stub = vi.fn().mockResolvedValue({
113
- text: "",
114
- turns: 0,
115
- durationMs: 1,
116
- success: false,
117
- error: "closed due to parent-new",
118
- sessionId: record.id,
119
- toolCalls: [],
120
- });
121
- (service as unknown as Record<string, unknown>).runAndFinalize = stub;
122
- // [D4 后形态] 轮次编排入口 kickOffChatRound(私有,bracket 调用先例见
123
- // subagent-service-recovery-bounds.test.ts privateFn);opts 形参仍是 ExecuteOptions
124
- //(task/slug),chat 分支由 ticket lossless 携带——task 声明形参不参与校验。
108
+ // [W3] 轮次编排入口 kickOffChatRound(私有,bracket 调用先例)——协议 run 发起后
109
+ // 挂起,编排性关闭先行,再模拟引擎应答(迟到回注被门拦)。
125
110
  const kickOffChatRound = (
126
111
  service as unknown as Record<string, (...args: unknown[]) => void>
127
112
  )["kickOffChatRound"];
128
- kickOffChatRound.call(service, record, { task: "t", slug: "gate" }, {}, {}, undefined, 1000, undefined);
129
- await vi.waitFor(() => expect(stub).toHaveBeenCalled());
113
+ const identity = {
114
+ agent: "general-purpose",
115
+ agentConfig: undefined,
116
+ resolved: { model: { id: "model", name: "Model", provider: "test", reasoning: false }, thinkingLevel: undefined },
117
+ };
118
+ kickOffChatRound.call(service, record, { task: "t", slug: "gate" }, identity, undefined, 1000);
119
+ await vi.waitFor(() => expect(fake.runs.length).toBe(1));
120
+ fake.runs[0]!.settle({ content: "late round text" });
130
121
  await Promise.resolve();
131
122
  await Promise.resolve();
132
123
  expect(pi.sendMessage).not.toHaveBeenCalled();
124
+ service.dispose();
125
+ clearEngines();
133
126
  fs.rmSync(agentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
134
127
  });
135
128
 
136
- it("kickOffChatRound.then still notifies for real failure closures (gc)", async () => {
129
+ it("kickOffChatRound 应答回注对真实失败关闭(gc)仍通知", async () => {
137
130
  const { agentDir, service, pi } = setup();
131
+ clearEngines();
132
+ const fake = registerFakePiEngine();
138
133
  const record = createRecord("sa-gate-gc", {
139
134
  agent: "general-purpose",
140
135
  model: "test/model",
@@ -146,12 +141,20 @@ describe("T4① notify gate closedReason whitelist", () => {
146
141
  controller: new AbortController(),
147
142
  });
148
143
  record.closedReason = "gc";
149
- (service as unknown as Record<string, unknown>).runAndFinalize = vi.fn().mockResolvedValue({});
150
144
  const kickOffChatRound = (
151
145
  service as unknown as Record<string, (...args: unknown[]) => void>
152
146
  )["kickOffChatRound"];
153
- kickOffChatRound.call(service, record, { task: "t", slug: "gate" }, {}, {}, undefined, 1000, undefined);
147
+ const identity = {
148
+ agent: "general-purpose",
149
+ agentConfig: undefined,
150
+ resolved: { model: { id: "model", name: "Model", provider: "test", reasoning: false }, thinkingLevel: undefined },
151
+ };
152
+ kickOffChatRound.call(service, record, { task: "t", slug: "gate" }, identity, undefined, 1000);
153
+ await vi.waitFor(() => expect(fake.runs.length).toBe(1));
154
+ fake.runs[0]!.settle({ content: "round" });
154
155
  await vi.waitFor(() => expect(pi.sendMessage).toHaveBeenCalled());
156
+ service.dispose();
157
+ clearEngines();
155
158
  fs.rmSync(agentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
156
159
  });
157
160
  });
@@ -25,15 +25,8 @@ const { loggerMock } = vi.hoisted(() => ({
25
25
  }));
26
26
  vi.mock("../../core/logger.ts", () => ({ getLogger: () => loggerMock }));
27
27
 
28
- // mock session-runner(import 链需要 runSpawn/killAllSpawnedChildren/getChildByRecord 存在)
29
- vi.mock("../engine/engines/pi/session-runner.ts", () => ({
30
- runSpawn: vi.fn(),
31
- killAllSpawnedChildren: vi.fn(),
32
- getChildByRecord: vi.fn(() => undefined),
33
- registerSpawnedChildForRecord: vi.fn(),
34
- killRecordChildWithEscalation: vi.fn(),
35
- spawnedChildren: new Map(),
36
- }));
28
+ // [W3 改写] 原 vi.mock(inproc pi 引擎目录/session-runner) 随删件消亡——本文件只测
29
+ // getRecordForAction 守卫(纯内存判定,不触引擎链路),现存 import 无需再 mock 引擎替身。
37
30
 
38
31
  import { createRecord } from "../execution-record.ts";
39
32
  import { ModelConfigService } from "../model-config-service.ts";