@zhushanwen/subagent-core 0.4.0 → 0.6.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 (309) hide show
  1. package/dist/{chunk-4KN4TTG7.js → chunk-43ONBFZX.js} +1 -1
  2. package/dist/{chunk-X7SZ5HLQ.js → chunk-V3VHZ2VX.js} +20 -27
  3. package/dist/execution/engine/engines/zcode/constants.cjs +29 -41
  4. package/dist/execution/engine/engines/zcode/constants.d.cts +65 -53
  5. package/dist/execution/engine/engines/zcode/constants.d.ts +65 -53
  6. package/dist/execution/engine/engines/zcode/constants.js +17 -27
  7. package/dist/execution/engine/engines/zcode/reader.d.cts +2 -1
  8. package/dist/execution/engine/engines/zcode/reader.d.ts +2 -1
  9. package/dist/execution/engine/engines/zcode/reader.js +2 -2
  10. package/dist/index.cjs +17100 -14082
  11. package/dist/index.d.cts +5336 -4033
  12. package/dist/index.d.ts +5336 -4033
  13. package/dist/index.js +17020 -14055
  14. package/dist/{types-DpUO16pj.d.cts → types-C3fE3R9x.d.cts} +280 -112
  15. package/dist/{types-DpUO16pj.d.ts → types-C3fE3R9x.d.ts} +280 -112
  16. package/dist.bundle/index.cjs +34933 -0
  17. package/package.json +3 -3
  18. package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +0 -1
  19. package/src/__tests__/append-system-prompt-assembly.test.ts +8 -7
  20. package/src/__tests__/fr4-get-state-handshake.test.ts +2 -2
  21. package/src/__tests__/m2-append-content-probe.test.ts +0 -1
  22. package/src/__tests__/manifest-store.test.ts +10 -9
  23. package/src/__tests__/record-store-cache.test.ts +0 -2
  24. package/src/__tests__/record-store-index.test.ts +1 -2
  25. package/src/__tests__/review-fix-loop-script.test.ts +4 -2
  26. package/src/__tests__/review-fix-loop-utils.test.ts +10 -10
  27. package/src/__tests__/robustness-low-batch1.test.ts +6 -5
  28. package/src/__tests__/robustness-medium-batch1.test.ts +2 -2
  29. package/src/__tests__/robustness-medium-batch2.test.ts +17 -6
  30. package/src/__tests__/robustness-medium-batch4.test.ts +2 -2
  31. package/src/__tests__/session-runner.test.ts +1 -1
  32. package/src/core/__tests__/host-services.test.ts +2 -2
  33. package/src/core/__tests__/logger.test.ts +1 -1
  34. package/src/core/error-message.ts +9 -0
  35. package/src/core/host-services.ts +21 -5
  36. package/src/core/notify-ports.ts +18 -5
  37. package/src/execution/__tests__/agent-profile.test.ts +4 -4
  38. package/src/execution/__tests__/agent-registry.test.ts +370 -0
  39. package/src/execution/__tests__/agent-result-mapper.test.ts +18 -2
  40. package/src/execution/__tests__/agents-assembly.test.ts +2 -2
  41. package/src/execution/__tests__/alive-store.test.ts +1 -1
  42. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +6 -6
  43. package/src/execution/__tests__/chat-engine-routing.test.ts +68 -33
  44. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +4 -4
  45. package/src/execution/__tests__/cold-resurrect.test.ts +283 -0
  46. package/src/execution/__tests__/collect-budget.test.ts +291 -0
  47. package/src/execution/__tests__/collect-coordinator-service.test.ts +327 -0
  48. package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
  49. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +262 -0
  50. package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
  51. package/src/execution/__tests__/config.test.ts +1 -1
  52. package/src/execution/__tests__/delivery-methods.test.ts +75 -62
  53. package/src/execution/__tests__/descendant-sweep-guards.test.ts +220 -0
  54. package/src/execution/__tests__/descendant-sweep.test.ts +6 -6
  55. package/src/execution/__tests__/dialog-queue.test.ts +2 -2
  56. package/src/execution/__tests__/engine-model-validation.test.ts +741 -0
  57. package/src/execution/__tests__/epipe-fallback.test.ts +29 -24
  58. package/src/execution/__tests__/execute-and-await-worktree.test.ts +21 -91
  59. package/src/execution/__tests__/execute-nesting.test.ts +34 -188
  60. package/src/execution/__tests__/execution-record.test.ts +217 -60
  61. package/src/execution/__tests__/execution-runtime-face.test.ts +5 -5
  62. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +4 -4
  63. package/src/execution/__tests__/finalize-record.test.ts +173 -17
  64. package/src/execution/__tests__/finalized-marker.test.ts +1 -1
  65. package/src/execution/__tests__/gc-timer.test.ts +56 -3
  66. package/src/execution/__tests__/get-record-for-action-restart.test.ts +12 -12
  67. package/src/execution/__tests__/get-state-handshake.test.ts +1 -1
  68. package/src/execution/__tests__/helpers/mock-extension-api.ts +1 -1
  69. package/src/execution/__tests__/helpers/session-runner-mocks.ts +113 -0
  70. package/src/execution/__tests__/helpers/spawn-mock.ts +150 -3
  71. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +137 -0
  72. package/src/execution/__tests__/keep-alive-no-progress.test.ts +50 -148
  73. package/src/execution/__tests__/kill-all-escalation.test.ts +2 -2
  74. package/src/execution/__tests__/lifecycle-predicates.test.ts +1 -2
  75. package/src/execution/__tests__/manifest-parentid.test.ts +4 -4
  76. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
  77. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +1 -1
  78. package/src/execution/__tests__/model-resolver.test.ts +2 -2
  79. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +23 -121
  80. package/src/execution/__tests__/nested-visibility.test.ts +2 -0
  81. package/src/execution/__tests__/notify-batch.test.ts +500 -0
  82. package/src/execution/__tests__/notify-ledger.test.ts +1000 -18
  83. package/src/execution/__tests__/output-collector.test.ts +117 -6
  84. package/src/execution/__tests__/pi-invocation.test.ts +36 -4
  85. package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
  86. package/src/execution/__tests__/record-store.test.ts +10 -9
  87. package/src/execution/__tests__/records-cwd-isolation.test.ts +2 -2
  88. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +29 -132
  89. package/src/execution/__tests__/recursive-visibility-env.test.ts +55 -179
  90. package/src/execution/__tests__/relay-env.test.ts +12 -1
  91. package/src/execution/__tests__/rpc-mode.test.ts +2 -2
  92. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +387 -0
  93. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +15 -9
  94. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +4 -4
  95. package/src/execution/__tests__/run-spawn-edges.test.ts +17 -15
  96. package/src/execution/__tests__/run-spawn-integration.test.ts +2 -2
  97. package/src/execution/__tests__/run-spawn-resume.test.ts +2 -2
  98. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +2 -2
  99. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +4 -4
  100. package/src/execution/__tests__/service-kill-escalation.test.ts +7 -5
  101. package/src/execution/__tests__/session-context-resolver.test.ts +0 -2
  102. package/src/execution/__tests__/session-file-gc.test.ts +36 -1
  103. package/src/execution/__tests__/session-pending.test.ts +257 -14
  104. package/src/execution/__tests__/session-reconstructor.test.ts +366 -15
  105. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +1 -1
  106. package/src/execution/__tests__/session-runner-close-prune.test.ts +2 -2
  107. package/src/execution/__tests__/session-runner-dispatch.test.ts +489 -0
  108. package/src/execution/__tests__/session-runner-epipe.test.ts +3 -3
  109. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +5 -4
  110. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +290 -0
  111. package/src/execution/__tests__/session-runner-schema-env.test.ts +7 -5
  112. package/src/execution/__tests__/settled-watchdog.test.ts +282 -47
  113. package/src/execution/__tests__/spawn-args.test.ts +11 -10
  114. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +26 -23
  115. package/src/execution/__tests__/spawn-event-adapter.test.ts +3 -3
  116. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +5 -4
  117. package/src/execution/__tests__/spawned-children.test.ts +2 -1
  118. package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
  119. package/src/execution/__tests__/start-sync-model-guard.test.ts +5 -5
  120. package/src/execution/__tests__/stdin-writer.test.ts +6 -4
  121. package/src/execution/__tests__/stream-sink-retirement.test.ts +6 -6
  122. package/src/execution/__tests__/subagent-actions-core.test.ts +48 -22
  123. package/src/execution/__tests__/subagent-service-message-close.test.ts +29 -26
  124. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +21 -8
  125. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +27 -22
  126. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +30 -29
  127. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +45 -20
  128. package/src/execution/__tests__/subagent-service.test.ts +37 -30
  129. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +88 -12
  130. package/src/execution/__tests__/subprocess-agent-runner-timeout.test.ts +75 -0
  131. package/src/execution/__tests__/subprocess-agent-runner.test.ts +22 -20
  132. package/src/execution/__tests__/sync-collect-recovery.test.ts +1117 -0
  133. package/src/execution/__tests__/temp-prompt.test.ts +1 -1
  134. package/src/execution/__tests__/timeout-integration.test.ts +6 -5
  135. package/src/execution/__tests__/tombstone-store.test.ts +1 -1
  136. package/src/execution/__tests__/turn-limiter-semantics.test.ts +1 -1
  137. package/src/execution/__tests__/turn-limiter.test.ts +1 -1
  138. package/src/execution/__tests__/ui-request-handler-factory.test.ts +12 -6
  139. package/src/execution/__tests__/ui-request-handler.test.ts +4 -3
  140. package/src/execution/__tests__/ui-request-queue.test.ts +142 -2
  141. package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
  142. package/src/execution/__tests__/worktree-manager.test.ts +14 -5
  143. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +4 -3
  144. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
  145. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
  146. package/src/execution/__tests__/worktree-registry.test.ts +1 -1
  147. package/src/execution/agent-registry.ts +74 -30
  148. package/src/execution/agent-result-mapper.ts +3 -0
  149. package/src/execution/cold-resurrect.ts +199 -0
  150. package/src/execution/collect-coordinator.ts +200 -0
  151. package/src/execution/config.ts +77 -5
  152. package/src/execution/engine/__tests__/common/capability-gate.test.ts +91 -0
  153. package/src/execution/engine/__tests__/common/data-dir.test.ts +1 -1
  154. package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
  155. package/src/execution/engine/__tests__/common/journal-wiring.test.ts +84 -0
  156. package/src/execution/engine/__tests__/common/kill-chain.test.ts +34 -7
  157. package/src/execution/engine/__tests__/common/persona-router.test.ts +4 -5
  158. package/src/execution/engine/__tests__/common/pool-manager.test.ts +213 -53
  159. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +149 -0
  160. package/src/execution/engine/__tests__/common/session-view-service.test.ts +499 -0
  161. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +22 -112
  162. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +15 -28
  163. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +1 -1
  164. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +12 -12
  165. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +2 -2
  166. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +21 -82
  167. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +4 -7
  168. package/src/execution/engine/__tests__/engine-discovery.test.ts +15 -3
  169. package/src/execution/engine/__tests__/model-prompt.test.ts +15 -3
  170. package/src/execution/engine/__tests__/registry.test.ts +4 -2
  171. package/src/execution/engine/__tests__/routing.test.ts +115 -6
  172. package/src/execution/engine/common/capability-gate.ts +92 -0
  173. package/src/execution/engine/common/journal-wiring.ts +97 -0
  174. package/src/execution/engine/common/kill-chain.ts +42 -10
  175. package/src/execution/engine/common/nesting-guard.ts +66 -0
  176. package/src/execution/engine/common/persona-router.ts +18 -8
  177. package/src/execution/engine/common/pool-manager.ts +332 -78
  178. package/src/execution/engine/common/session-view-service.ts +506 -0
  179. package/src/execution/engine/common/session-view-types.ts +125 -0
  180. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +174 -28
  181. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +257 -0
  182. package/src/execution/{argv-mirror.ts → engine/engines/pi/argv-mirror.ts} +43 -21
  183. package/src/execution/{get-state-handshake.ts → engine/engines/pi/get-state-handshake.ts} +1 -1
  184. package/src/execution/{output-collector.ts → engine/engines/pi/output-collector.ts} +108 -19
  185. package/src/execution/engine/engines/pi/pi-engine.ts +434 -38
  186. package/src/execution/{pi-invocation.ts → engine/engines/pi/pi-invocation.ts} +2 -2
  187. package/src/execution/engine/engines/pi/reader.ts +11 -0
  188. package/src/execution/engine/engines/pi/registration.ts +4 -2
  189. package/src/execution/{session-runner.ts → engine/engines/pi/session-runner.ts} +617 -412
  190. package/src/execution/{spawn-event-adapter.ts → engine/engines/pi/spawn-event-adapter.ts} +75 -34
  191. package/src/execution/{stdin-writer.ts → engine/engines/pi/stdin-writer.ts} +10 -9
  192. package/src/execution/{temp-prompt.ts → engine/engines/pi/temp-prompt.ts} +2 -2
  193. package/src/execution/{turn-limiter.ts → engine/engines/pi/turn-limiter.ts} +1 -1
  194. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +54 -27
  195. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +321 -0
  196. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +13 -12
  197. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +7 -210
  198. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +6 -110
  199. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +247 -0
  200. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +451 -0
  201. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +20 -8
  202. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +77 -110
  203. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +26 -320
  204. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +210 -0
  205. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +353 -0
  206. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +282 -0
  207. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +372 -0
  208. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +48 -148
  209. package/src/execution/engine/engines/zcode/appserver-launcher.ts +167 -0
  210. package/src/execution/engine/engines/zcode/connection.ts +24 -11
  211. package/src/execution/engine/engines/zcode/constants.ts +75 -71
  212. package/src/execution/engine/engines/zcode/golden-sample.ts +8 -46
  213. package/src/execution/engine/engines/zcode/parser.ts +12 -346
  214. package/src/execution/engine/engines/zcode/preparer.ts +12 -143
  215. package/src/execution/engine/engines/zcode/session-channel.ts +351 -39
  216. package/src/execution/engine/engines/zcode/zcode-engine.ts +665 -760
  217. package/src/execution/engine/host-task-spec.ts +32 -36
  218. package/src/execution/engine/model-validation.ts +177 -0
  219. package/src/execution/engine/port.ts +24 -6
  220. package/src/execution/engine/routing.ts +75 -1
  221. package/src/execution/engine/types.ts +30 -103
  222. package/src/execution/execution-record.ts +229 -144
  223. package/src/execution/finalize-record.ts +141 -99
  224. package/src/execution/idle-gc.ts +28 -0
  225. package/src/execution/lifecycle-predicates.ts +1 -1
  226. package/src/execution/notifier.ts +234 -25
  227. package/src/execution/notify-host.ts +232 -0
  228. package/src/execution/record-entry.ts +16 -0
  229. package/src/execution/record-store.ts +280 -103
  230. package/src/execution/round-settlement.ts +93 -0
  231. package/src/execution/session-file-gc.ts +96 -62
  232. package/src/execution/session-reconstructor.ts +256 -143
  233. package/src/execution/sessions-index.ts +117 -47
  234. package/src/execution/settled-watchdog.ts +264 -52
  235. package/src/execution/subagent-actions-core.ts +84 -28
  236. package/src/execution/subagent-service.ts +1225 -964
  237. package/src/execution/subprocess-agent-runner.ts +144 -97
  238. package/src/execution/sync-rebuild.ts +87 -0
  239. package/src/execution/types.ts +72 -0
  240. package/src/execution/ui-request-handler-factory.ts +102 -74
  241. package/src/execution/ui-request-queue.ts +50 -19
  242. package/src/index.ts +442 -316
  243. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +1 -1
  244. package/src/orchestration/__tests__/agent-call-stream.test.ts +2 -2
  245. package/src/orchestration/__tests__/args-validator.test.ts +14 -0
  246. package/src/orchestration/__tests__/config-loader.test.ts +1 -1
  247. package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +1 -1
  248. package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +11 -9
  249. package/src/orchestration/__tests__/execute-agent-call.test.ts +151 -11
  250. package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
  251. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
  252. package/src/orchestration/__tests__/file-run-store.test.ts +7 -6
  253. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +2 -2
  254. package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +1 -1
  255. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +3 -3
  256. package/src/orchestration/__tests__/lifecycle.test.ts +7 -5
  257. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +1 -1
  258. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
  259. package/src/orchestration/__tests__/run-snapshot.test.ts +8 -5
  260. package/src/orchestration/__tests__/script-generate.test.ts +5 -5
  261. package/src/orchestration/__tests__/script-lint.test.ts +17 -0
  262. package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
  263. package/src/orchestration/__tests__/test-mocks.ts +2 -0
  264. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +7 -6
  265. package/src/orchestration/__tests__/worker-message-pump-finalize-run.test.ts +229 -0
  266. package/src/orchestration/__tests__/{error-recovery-handlers.test.ts → worker-message-pump-handlers.test.ts} +27 -19
  267. package/src/orchestration/__tests__/{error-recovery-postmessage-defense.test.ts → worker-message-pump-postmessage-defense.test.ts} +8 -8
  268. package/src/orchestration/__tests__/{error-recovery-serialize-failed-result.test.ts → worker-message-pump-serialize-failed-result.test.ts} +2 -2
  269. package/src/orchestration/__tests__/{error-recovery-workflow-call.test.ts → worker-message-pump-workflow-call.test.ts} +1 -1
  270. package/src/orchestration/__tests__/worker-pending-timeout-abort.test.ts +1 -1
  271. package/src/orchestration/__tests__/worker-script-builder.test.ts +1 -1
  272. package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
  273. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +1 -1
  274. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
  275. package/src/orchestration/agent-opts-resolver.ts +1 -1
  276. package/src/orchestration/args-validator.ts +53 -31
  277. package/src/orchestration/execute-agent-call.ts +19 -73
  278. package/src/orchestration/launcher.ts +128 -81
  279. package/src/orchestration/lifecycle.ts +43 -45
  280. package/src/orchestration/models/ports.ts +4 -4
  281. package/src/orchestration/models/run-runtime.ts +2 -2
  282. package/src/orchestration/models/trace.ts +1 -1
  283. package/src/orchestration/models/types.ts +111 -22
  284. package/src/orchestration/models/workflow-run.ts +1 -1
  285. package/src/orchestration/script-lint.ts +91 -58
  286. package/src/orchestration/{error-recovery.ts → worker-message-pump.ts} +157 -150
  287. package/src/shared/__tests__/atomic-write.test.ts +1 -1
  288. package/src/shared/__tests__/meta-parser.test.ts +151 -0
  289. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
  290. package/src/shared/__tests__/resource-discovery.test.ts +258 -215
  291. package/src/shared/atomic-write.ts +12 -9
  292. package/src/shared/meta-parser.ts +158 -84
  293. package/src/shared/model-ref.ts +15 -2
  294. package/src/shared/resource-discovery.ts +9 -183
  295. package/src/shared/schema-jsonify.ts +1 -1
  296. package/workflows/review-fix-loop-utils.cjs +151 -89
  297. package/workflows/review-fix-loop-utils.d.cts +287 -0
  298. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  299. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  300. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  301. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  302. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  303. package/src/execution/engine/engines/zcode/__tests__/preparer-appserver.test.ts +0 -387
  304. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -710
  305. package/src/execution/engine/engines/zcode/appserver-home.ts +0 -442
  306. package/src/execution/engine/engines/zcode/appserver-probe.ts +0 -141
  307. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  308. package/src/execution/execute-options-mapper.ts +0 -115
  309. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -288
@@ -9,7 +9,7 @@ import {
9
9
  deriveSessionFilePath,
10
10
  findSessionFileByHeaderId,
11
11
  parseSpawnLine,
12
- } from "../spawn-event-adapter.ts";
12
+ } from "../engine/engines/pi/spawn-event-adapter.ts";
13
13
 
14
14
  describe("parseSpawnLine", () => {
15
15
  describe("空白行", () => {
@@ -150,14 +150,14 @@ describe("findSessionFileByHeaderId", () => {
150
150
  fs.writeFileSync(expectedFile, "{}");
151
151
  const result = findSessionFileByHeaderId(tmpDir, "sid-456");
152
152
  expect(result).toBe(expectedFile);
153
- fs.rmSync(tmpDir, { recursive: true });
153
+ fs.rmSync(tmpDir, { recursive: true, maxRetries: 5, retryDelay: 20 });
154
154
  });
155
155
 
156
156
  it("无匹配返回 undefined", () => {
157
157
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "spawn-adapter-test-"));
158
158
  const result = findSessionFileByHeaderId(tmpDir, "nonexistent");
159
159
  expect(result).toBeUndefined();
160
- fs.rmSync(tmpDir, { recursive: true });
160
+ fs.rmSync(tmpDir, { recursive: true, maxRetries: 5, retryDelay: 20 });
161
161
  });
162
162
 
163
163
  it("目录不存在返回 undefined(不抛错)", () => {
@@ -71,7 +71,7 @@ vi.mock("../alive-store.ts", () => ({
71
71
  writeAliveMarker: vi.fn(),
72
72
  }));
73
73
 
74
- vi.mock("../temp-prompt.ts", () => ({
74
+ vi.mock("../engine/engines/pi/temp-prompt.ts", () => ({
75
75
  writePromptToTempFile: vi.fn(async (agent: string, content: string) => {
76
76
  captured.content = content;
77
77
  const safeName = agent.replace(/[^\w.-]+/g, "_");
@@ -83,7 +83,7 @@ vi.mock("../temp-prompt.ts", () => ({
83
83
  import { spawn } from "node:child_process";
84
84
 
85
85
  import { createRecord } from "../execution-record.ts";
86
- import { runSpawn, type RunOptions, type SessionRunnerContext } from "../session-runner.ts";
86
+ import { runSpawn, type RunOptions, type SessionRunnerContext } from "../engine/engines/pi/session-runner.ts";
87
87
 
88
88
  const mockSpawn = vi.mocked(spawn);
89
89
 
@@ -117,8 +117,9 @@ function makeRecord() {
117
117
  return createRecord("wt-guidance-1", {
118
118
  agent: "general-purpose",
119
119
  model: "test/model",
120
- mode: "sync",
120
+ mode: "background",
121
121
  task: "test task",
122
+ slug: "test",
122
123
  startedAt: Date.now(),
123
124
  rootSessionId: "s1",
124
125
  parentRecordId: undefined,
@@ -128,7 +129,7 @@ function makeRecord() {
128
129
 
129
130
  function makeRunOpts(overrides: Partial<RunOptions> = {}): RunOptions {
130
131
  return {
131
- resolved: { model: { provider: "test", id: "model" }, thinkingLevel: undefined },
132
+ resolved: { model: { provider: "test", id: "model", name: "Model", reasoning: false }, thinkingLevel: undefined },
132
133
  agentConfig: undefined,
133
134
  appendSystemPrompt: undefined,
134
135
  skillPath: undefined,
@@ -29,7 +29,7 @@ vi.mock("../../core/logger.ts", () => ({ getLogger: () => loggerMock }));
29
29
 
30
30
  import type { EnginePort } from "../engine/port.ts";
31
31
  import { clearEngines, getEngine, registerEngine } from "../engine/registry.ts";
32
- import { getChildByRecord, killAllSpawnedChildren, spawnedChildren } from "../session-runner.ts";
32
+ import { getChildByRecord, killAllSpawnedChildren, spawnedChildren } from "../engine/engines/pi/session-runner.ts";
33
33
 
34
34
  /**
35
35
  * 假 child:只关心 killed 标记 + kill 调用(killAllSpawnedChildren 遍历用)。
@@ -63,6 +63,7 @@ function makeDisposingEngine(
63
63
  resume: "unsupported",
64
64
  interrupt: "kill-only",
65
65
  permissionMode: "fixed",
66
+ maxTurns: false,
66
67
  }),
67
68
  probe: () =>
68
69
  Promise.resolve({ ok: true, engineVersion: "0.0.0-test", checks: [{ name: "stub", ok: true }] }),
@@ -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
+ });
@@ -30,14 +30,14 @@ vi.mock("node:child_process", async () => {
30
30
  });
31
31
 
32
32
  // buildSpawnArgs 包装为 spy(保留真实实现)——「非全等拒单不触达 spawn 参数组装」的承重断言。
33
- vi.mock("../session-runner.ts", async (importOriginal) => {
34
- const actual = await importOriginal<typeof import("../session-runner.ts")>();
33
+ vi.mock("../engine/engines/pi/session-runner.ts", async (importOriginal) => {
34
+ const actual = await importOriginal<typeof import("../engine/engines/pi/session-runner.ts")>();
35
35
  return { ...actual, buildSpawnArgs: vi.fn(actual.buildSpawnArgs) };
36
36
  });
37
37
 
38
38
  import { ModelConfigService } from "../model-config-service.ts";
39
39
  import type { ModelInfo, ModelRegistryLike } from "../model-resolver.ts";
40
- import { buildSpawnArgs } from "../session-runner.ts";
40
+ import { buildSpawnArgs } from "../engine/engines/pi/session-runner.ts";
41
41
  import type { PiLike } from "../subagent-service.ts";
42
42
  import { SubagentService } from "../subagent-service.ts";
43
43
 
@@ -93,7 +93,7 @@ describe("start 同步期裁决(U1 验收 3:非全等 → isError 且无 spa
93
93
 
94
94
  afterEach(() => {
95
95
  vi.restoreAllMocks();
96
- fs.rmSync(tmpDir, { recursive: true, force: true });
96
+ fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
97
97
  });
98
98
 
99
99
  it("小写变体入参 → execute 同步 reject(问句式报错),buildSpawnArgs/spawn/appendEntry 均未被调", async () => {
@@ -128,7 +128,7 @@ describe("start 同步期裁决(U1 验收 3:非全等 → isError 且无 spa
128
128
  });
129
129
 
130
130
  it("全等入参通过裁决(reject 不发生,放行链路触达 spawn 参数组装)——守卫零误伤对照", async () => {
131
- // 放行路径会进入 kickOffBackground(detached);execute resolve 即视为裁决放行。
131
+ // 放行路径会进入轮次 kick-off(detached);execute resolve 即视为裁决放行。
132
132
  // spawn 本身由 FakeChild 缺失抛错收口——本断言只关心「越过了同步裁决」:
133
133
  // execute 不 reject,且 buildSpawnArgs 已被调(或即将被调的 record 已创建)。
134
134
  const promise = service.execute({
@@ -33,7 +33,7 @@ vi.mock("../../core/logger.ts", () => ({
33
33
  getLogger: () => loggerMock,
34
34
  }));
35
35
 
36
- import { respond, sendGetStateCommand, sendPromptCommand } from "../stdin-writer.ts";
36
+ import { respond, sendGetStateCommand, sendPromptCommand } from "../engine/engines/pi/stdin-writer.ts";
37
37
 
38
38
  // ── helpers ──
39
39
 
@@ -362,8 +362,10 @@ describe("sendGetStateCommand", () => {
362
362
  describe("writeStdinLine 背压 — write 返回 false 时 warn 不 throw", () => {
363
363
  it("child.stdin.write 返回 false → warn 一次,函数正常返回(不 throw)", () => {
364
364
  // 构造 write 永远返回 false 的假 stream(模拟内核缓冲满/HWM 到达)
365
+ // 保留 vi.fn 引用(经 PassThrough 视图后 write 的 mock 面不可达)
366
+ const fakeWrite = vi.fn((_chunk: unknown) => false);
365
367
  const fakeStdin = {
366
- write: vi.fn(() => false),
368
+ write: fakeWrite,
367
369
  destroyed: false,
368
370
  } as unknown as PassThrough;
369
371
  const child = { stdin: fakeStdin } as unknown as ChildProcess;
@@ -371,8 +373,8 @@ describe("writeStdinLine 背压 — write 返回 false 时 warn 不 throw", () =
371
373
  expect(() => respond(child, "req-backpressure", { value: "x" })).not.toThrow();
372
374
 
373
375
  // write 被调一次(写入 command 行)
374
- expect(fakeStdin.write).toHaveBeenCalledTimes(1);
375
- const writtenArg = fakeStdin.write.mock.calls[0]?.[0] as string;
376
+ expect(fakeWrite).toHaveBeenCalledTimes(1);
377
+ const writtenArg = fakeWrite.mock.calls[0]![0] as string;
376
378
  expect(writtenArg).toContain("extension_ui_response");
377
379
  expect(writtenArg).toContain("req-backpressure");
378
380
  expect(writtenArg.endsWith("\n")).toBe(true);
@@ -3,7 +3,7 @@
3
3
  // widget 私货通道退役步骤 2(E 方案 §6.3)测试,两层:
4
4
  // 判定层:createBackgroundStream 真实函数(vi.importActual 绕过文件级 mock)——
5
5
  // gui+relay 激活不创建;tui / relay 未激活 / headless 原样创建;sink=null 恒降级。
6
- // 接线层:SubagentService.execute(background → kickOffBackground 同步段)透传
6
+ // 接线层:SubagentService.execute(background → kickOffChatRound 同步段)透传
7
7
  // mode/streamSink 给工厂——mode 传错 = 判定失效,故接线面必须锁定。
8
8
  //
9
9
  // spawn 层 mock(FakeChild),与 nested-visibility-env-propagation.test.ts 同模式。
@@ -103,7 +103,7 @@ vi.mock("../manifest-store.ts", () => {
103
103
  return { ManifestStore: vi.fn(function (_recordsDir: string) { return new FakeManifestStore(); }) };
104
104
  });
105
105
 
106
- vi.mock("../temp-prompt.ts", () => ({
106
+ vi.mock("../engine/engines/pi/temp-prompt.ts", () => ({
107
107
  writePromptToTempFile: vi.fn(async (agent: string) => {
108
108
  const safeName = agent.replace(/[^\w.-]+/g, "_");
109
109
  return { dir: `/tmp/fake-${safeName}`, filePath: `/tmp/fake-${safeName}/prompt-${safeName}.md` };
@@ -156,7 +156,7 @@ const ctxModel: ModelInfo = { id: "m", name: "M", provider: "p", reasoning: fals
156
156
 
157
157
  function setupService(mode: ExtensionMode | undefined, sessionId = "retire-it"): SubagentService {
158
158
  const agentDir = "/tmp/stream-retire-it";
159
- const modelService = new ModelConfigService({ agentDir });
159
+ const modelService = new ModelConfigService({ agentDir, cwd: agentDir });
160
160
  modelService.initModel({
161
161
  modelRegistry: makeEmptyRegistry(),
162
162
  sessionId,
@@ -176,7 +176,7 @@ function setupService(mode: ExtensionMode | undefined, sessionId = "retire-it"):
176
176
  return service;
177
177
  }
178
178
 
179
- /** 等 kickOffBackground 的 detached runAndFinalize 走到 spawn(stream 创建先于此)。 */
179
+ /** 等 kickOffChatRound 的 detached 轮次执行走到 spawn(stream 创建先于此)。 */
180
180
  async function waitForSpawnCall(): Promise<void> {
181
181
  const baseline = mockSpawn.mock.calls.length;
182
182
  const deadline = Date.now() + 2000;
@@ -187,7 +187,7 @@ async function waitForSpawnCall(): Promise<void> {
187
187
  }
188
188
 
189
189
  async function executeBackground(service: SubagentService): Promise<void> {
190
- await service.execute({ task: "retire test", ctxModel });
190
+ await service.execute({ task: "retire test", slug: "test", ctxModel });
191
191
  await waitForSpawnCall();
192
192
  // 推进 detached runSpawn 收尾(FakeChild close),防句柄悬挂干扰后续用例
193
193
  lastSpawnedChild().emit("close", 0);
@@ -234,7 +234,7 @@ describe("退役步骤 2 判定层:createBackgroundStream", () => {
234
234
 
235
235
  // ── 接线层:service → 工厂的参数透传(mode 传错 = 判定失效)──
236
236
 
237
- describe("退役步骤 2 接线层:kickOffBackground 透传 mode/sink 给工厂", () => {
237
+ describe("退役步骤 2 接线层:kickOffChatRound 透传 mode/sink 给工厂", () => {
238
238
  beforeEach(() => {
239
239
  vi.clearAllMocks();
240
240
  for (const key of RELAY_ENV_KEYS) delete process.env[key];
@@ -42,9 +42,9 @@ import type {
42
42
  ExecutionHandle,
43
43
  ExecutionRecord,
44
44
  SubagentRecord,
45
- SubagentService,
46
45
  SubagentToolDetails,
47
46
  } from "../types.ts";
47
+ import type { SubagentService } from "../subagent-service.ts";
48
48
 
49
49
  // ── 时钟固定(duration 快照确定性,见文件头)──
50
50
  const FROZEN_NOW = 1788189209000;
@@ -132,17 +132,41 @@ function makeRec(over: Partial<SubagentRecord> = {}): SubagentRecord {
132
132
  }
133
133
 
134
134
  function makeService(over: Record<string, unknown> = {}): SubagentService {
135
- return {
135
+ // 聚合面形态对齐 subagent-service.ts D4:queries(读模型)与 chatActions(对话
136
+ // action 面)分组挂载,mock 按同构 key 装配(over 仍传平铺 key,最小化快照用例改动)。
137
+ const m = {
136
138
  execute: vi.fn(),
137
- findRecord: vi.fn(() => undefined),
138
139
  cancel: vi.fn(() => false),
140
+ findRecord: vi.fn(() => undefined),
139
141
  collectRecords: vi.fn(() => [] as SubagentRecord[]),
140
142
  getFullRecord: vi.fn(() => undefined as SubagentRecord | undefined),
141
143
  lookupRecordAnyState: vi.fn(() => undefined as SubagentRecord | undefined),
142
144
  getRecordForAction: vi.fn(),
143
145
  closeSubagent: vi.fn(),
144
- deliverMessage: vi.fn(),
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),
145
150
  ...over,
151
+ };
152
+ return {
153
+ execute: m.execute,
154
+ cancel: m.cancel,
155
+ // [U2 偏差#3 接线] startHandler 经平铺访问器读 config 缺省 collect(真实 service
156
+ // 为平铺方法 subagent-service.ts:1786,非 queries 聚合面成员),stub 须同构挂载。
157
+ getCollectSyncDefault: m.getCollectSyncDefault,
158
+ queries: {
159
+ findRecord: m.findRecord,
160
+ lookupRecordAnyState: m.lookupRecordAnyState,
161
+ collectRecords: m.collectRecords,
162
+ getFullRecord: m.getFullRecord,
163
+ onChange: vi.fn(() => () => {}),
164
+ },
165
+ chatActions: {
166
+ getRecordForAction: m.getRecordForAction,
167
+ closeSubagent: m.closeSubagent,
168
+ deliverChatMessage: m.deliverChatMessage,
169
+ },
146
170
  } as unknown as SubagentService;
147
171
  }
148
172
 
@@ -290,7 +314,7 @@ describe("⛔4 startHandler(校验 + 启动,快照 = pi-sw 实测)", () =>
290
314
  });
291
315
 
292
316
  it("正常启动 → 领域对象全字段 + execute 参数(task/slug trim、拍平透传、ctxModel/signal)", async () => {
293
- const execute = vi.fn(async (): Promise<ExecutionHandle> => ({
317
+ const execute = vi.fn(async (_opts: { task: string; slug?: string; agent?: string }): Promise<ExecutionHandle> => ({
294
318
  mode: "background",
295
319
  subagentId: "bg-9-abc",
296
320
  sessionFile: "sess-9.jsonl",
@@ -334,7 +358,7 @@ describe("⛔4 startHandler(校验 + 启动,快照 = pi-sw 实测)", () =>
334
358
  },
335
359
  });
336
360
  expect(execute).toHaveBeenCalledTimes(1);
337
- expect(execute.mock.calls[0][0]).toEqual({
361
+ expect(execute.mock.calls[0]![0]).toEqual({
338
362
  task: "long task", // trim 生效
339
363
  slug: "long-running",
340
364
  agent: "/x/agent.md",
@@ -489,6 +513,8 @@ describe("⛔4 cancelHandler(守卫 + 归属判定 + CAS 失败映射,快照
489
513
  expect(
490
514
  await errOf(() =>
491
515
  cancelHandler(
516
+ // "sync" 是历史已裁撤值(ExecutionMode 现仅 "background")——经 as never
517
+ // 注入非法值专测守卫分支,运行时守卫按 !== "background" 拦截
492
518
  makeService({ findRecord: vi.fn(() => makeRec({ id: "bg-1", mode: "sync" as never })) }),
493
519
  { subagentId: "bg-1" },
494
520
  ),
@@ -587,11 +613,11 @@ describe("⛔4 messageHandler(守卫 + upgrade + 投递,快照 = pi-sw 实
587
613
  });
588
614
  });
589
615
 
590
- it("chatMode record → deliverMessage(text trim + interrupt) + 领域对象", async () => {
591
- const deliverMessage = vi.fn(async () => {});
616
+ it("chatMode record → deliverChatMessage(text trim + interrupt) + 领域对象", async () => {
617
+ const deliverChatMessage = vi.fn(async () => {});
592
618
  const chatRecord = makeExecRecord({ id: "bg-1", chatMode: true, slug: "src-slug" });
593
619
  const r = await messageHandler(
594
- makeService({ getRecordForAction: vi.fn(() => chatRecord), deliverMessage }),
620
+ makeService({ getRecordForAction: vi.fn(() => chatRecord), deliverChatMessage }),
595
621
  { subagentId: "bg-1", text: " go on ", interrupt: true },
596
622
  );
597
623
  expect(r).toEqual({
@@ -600,18 +626,18 @@ describe("⛔4 messageHandler(守卫 + upgrade + 投递,快照 = pi-sw 实
600
626
  slug: "src-slug",
601
627
  response: { delivered: true },
602
628
  });
603
- expect(deliverMessage).toHaveBeenCalledWith(chatRecord, "go on", true);
629
+ expect(deliverChatMessage).toHaveBeenCalledWith(chatRecord, "go on", true);
604
630
  });
605
631
 
606
632
  it("one-shot upgrade:非 chatMode running record 收 message → 置位 chatMode 后投递", async () => {
607
- const deliverMessage = vi.fn(async () => {});
633
+ const deliverChatMessage = vi.fn(async () => {});
608
634
  const upgradeRec = makeExecRecord({ id: "bg-1", chatMode: false, status: "running" });
609
635
  await messageHandler(
610
- makeService({ getRecordForAction: vi.fn(() => upgradeRec), deliverMessage }),
636
+ makeService({ getRecordForAction: vi.fn(() => upgradeRec), deliverChatMessage }),
611
637
  { subagentId: "bg-1", text: "hi" },
612
638
  );
613
639
  expect(upgradeRec.chatMode).toBe(true);
614
- expect(deliverMessage).toHaveBeenCalledWith(upgradeRec, "hi", false);
640
+ expect(deliverChatMessage).toHaveBeenCalledWith(upgradeRec, "hi", false);
615
641
  });
616
642
 
617
643
  it("getRecordForAction 拒绝 + 无终态快照 → 原错误透传(文案最准原则)", async () => {
@@ -774,7 +800,7 @@ describe("⛔4 closeHandler(force 语义透传,快照 = pi-sw 实测)", ()
774
800
  // forkFromHandler(守卫链 1–6)
775
801
  // ============================================================
776
802
  describe("⛔4 forkFromHandler(守卫链 + slug 派生 + prompt 包装,快照 = pi-sw 实测)", () => {
777
- function makeForkService(source: SubagentRecord | undefined, execute = vi.fn(async (): Promise<ExecutionHandle> => ({
803
+ function makeForkService(source: SubagentRecord | undefined, execute = vi.fn(async (_opts: { task: string; slug?: string; agent?: string }): Promise<ExecutionHandle> => ({
778
804
  mode: "background",
779
805
  subagentId: "bg-new-1",
780
806
  sessionFile: "sess-new.jsonl",
@@ -899,7 +925,7 @@ describe("⛔4 forkFromHandler(守卫链 + slug 派生 + prompt 包装,快
899
925
  });
900
926
 
901
927
  it("正常:显式 prompt → wrapForkFromPrompt 包装 + slug 派生 'src-slug-resumed' + execute 参数", async () => {
902
- const execute = vi.fn(async (): Promise<ExecutionHandle> => ({
928
+ const execute = vi.fn(async (_opts: { task: string; slug?: string; agent?: string }): Promise<ExecutionHandle> => ({
903
929
  mode: "background",
904
930
  subagentId: "bg-new-1",
905
931
  sessionFile: "sess-new.jsonl",
@@ -928,7 +954,7 @@ describe("⛔4 forkFromHandler(守卫链 + slug 派生 + prompt 包装,快
928
954
  });
929
955
 
930
956
  it("无 prompt → FORK_FROM_DEFAULT_PROMPT 逐字", async () => {
931
- const execute = vi.fn(async (): Promise<ExecutionHandle> => ({
957
+ const execute = vi.fn(async (_opts: { task: string; slug?: string; agent?: string }): Promise<ExecutionHandle> => ({
932
958
  mode: "background",
933
959
  subagentId: "bg-new-2",
934
960
  sessionFile: "sess-new-2.jsonl",
@@ -955,7 +981,7 @@ describe("⛔4 forkFromHandler(守卫链 + slug 派生 + prompt 包装,快
955
981
  });
956
982
 
957
983
  it("slug 派生:34 字符源 slug 截 27 + '-resumed';fallback 链 slug||agent||'resumed'", async () => {
958
- const execute34 = vi.fn(async (): Promise<ExecutionHandle> => ({
984
+ const execute34 = vi.fn(async (_opts: { task: string; slug?: string; agent?: string }): Promise<ExecutionHandle> => ({
959
985
  mode: "background",
960
986
  subagentId: "bg-new-3",
961
987
  sessionFile: undefined,
@@ -965,9 +991,9 @@ describe("⛔4 forkFromHandler(守卫链 + slug 派生 + prompt 包装,快
965
991
  makeForkService(makeRec({ id: "bg-1", slug: "s".repeat(34), sessionFile: "sess-1.jsonl" }), execute34),
966
992
  { sourceSubagentId: "bg-1", prompt: "p" },
967
993
  );
968
- expect(execute34.mock.calls[0][0].slug).toBe(`${"s".repeat(27)}-resumed`);
994
+ expect(execute34.mock.calls[0]![0].slug).toBe(`${"s".repeat(27)}-resumed`);
969
995
 
970
- const executeAgent = vi.fn(async (): Promise<ExecutionHandle> => ({
996
+ const executeAgent = vi.fn(async (_opts: { task: string; slug?: string; agent?: string }): Promise<ExecutionHandle> => ({
971
997
  mode: "background",
972
998
  subagentId: "bg-new-4",
973
999
  sessionFile: undefined,
@@ -980,9 +1006,9 @@ describe("⛔4 forkFromHandler(守卫链 + slug 派生 + prompt 包装,快
980
1006
  ),
981
1007
  { sourceSubagentId: "bg-1", prompt: "p" },
982
1008
  );
983
- expect(executeAgent.mock.calls[0][0].slug).toBe("/home/u/agents/helper.md-resumed");
1009
+ expect(executeAgent.mock.calls[0]![0].slug).toBe("/home/u/agents/helper.md-resumed");
984
1010
 
985
- const executeResumed = vi.fn(async (): Promise<ExecutionHandle> => ({
1011
+ const executeResumed = vi.fn(async (_opts: { task: string; slug?: string; agent?: string }): Promise<ExecutionHandle> => ({
986
1012
  mode: "background",
987
1013
  subagentId: "bg-new-5",
988
1014
  sessionFile: undefined,
@@ -992,6 +1018,6 @@ describe("⛔4 forkFromHandler(守卫链 + slug 派生 + prompt 包装,快
992
1018
  makeForkService(makeRec({ id: "bg-1", slug: "", agent: "", sessionFile: "sess-1.jsonl" }), executeResumed),
993
1019
  { sourceSubagentId: "bg-1", prompt: "p" },
994
1020
  );
995
- expect(executeResumed.mock.calls[0][0].slug).toBe("resumed-resumed");
1021
+ expect(executeResumed.mock.calls[0]![0].slug).toBe("resumed-resumed");
996
1022
  });
997
1023
  });