@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhushanwen/subagent-core",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Cross-host shared subagent execution layer and workflow orchestration core (dual-form npm package: TS source for workspace, dist ESM+CJS for npm)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -72,7 +72,7 @@
72
72
  "default": "./workflows/*"
73
73
  }
74
74
  },
75
- "$comment": "D5 公共 API 面定稿(docs/design/subagent-core-package-extraction.md §3.3 D5):公共面 = 主入口 barrel + 4 条语义子入口(./engines/zcode/reader、./engines/zcode/constants、./engine/paths、./relay-env)+ ./workflows/* 资产子入口。exports 面 = semver 契约,收窄不放宽。双形态(D4):workspace TS 消费走 import 条件 -> src(与 extension-protocol 先例同型);npm 消费走 publishConfig 发布面(npm publish 时整体替换 exports):import -> dist ESM、require -> dist CJS。require 条件指向 dist CJS 是本仓首例,D4 依据:zsw 宿主为纯 CJS(node>=20),而 core 依赖的 @xyz-agent/extension-protocol npm dist 仅 ESM(.mjs),node 20 下 require() 加载 ESM 不可靠——因此对 extension-protocol 设 noExternal 防御性 bundle 边界(当前 entry 闭包无其运行时引用、dist 实测零常量命中;未来 entry 一旦引入运行时引用即 bundle),绝不让外部 ESM 依赖出现在 require 链上;require 分支的 types 用 .d.cts 对应。开发态 require 条件即指向 dist:dist 是 require 语义的真实载体,未 build 时 require 失败属预期(build 前置)。语义子入口精确条目优先于 `./*` 通配(Node 规范:exact match beats pattern),`./*` -> src 通配仅为仓内壳侧深路径消费保留(壳侧 `<pkg>/<域>/<路径>.ts` 形态 import,量级百处、以 grep 实测为准,不在此固化易过期数字),发布面刻意不带该通配——npm 消费面收窄到上列受控入口。workflows/ 资产 .cjs/.js 不编译(D1:src=dist 同字节直发),require/import 条件同径。tsup 多入口保形输出见 tsup.config.ts(dist/<entry> 与 src 同构,d.ts/d.cts 全覆盖)。",
75
+ "$comment": "D5 公共 API 面定稿(docs/design/subagent-core-package-extraction.md §3.3 D5):公共面 = 主入口 barrel + 4 条语义子入口(./engines/zcode/reader、./engines/zcode/constants、./engine/paths、./relay-env)+ ./workflows/* 资产子入口。exports 面 = semver 契约,收窄不放宽。双形态(D4):workspace TS 消费走 import 条件 -> src(与 extension-protocol 先例同型);npm 消费走 publishConfig 发布面(npm publish 时整体替换 exports):import -> dist ESM、require -> dist CJS。require 条件指向 dist CJS 是本仓首例,D4 依据:zsw 宿主为纯 CJS(node>=20),而 core 依赖的 @xyz-agent/extension-protocol npm dist 仅 ESM(.mjs),node 20 下 require() 加载 ESM 不可靠——因此对 extension-protocol 设 noExternal 防御性 bundle 边界(当前 entry 闭包无其运行时引用、dist 实测零常量命中;未来 entry 一旦引入运行时引用即 bundle),绝不让外部 ESM 依赖出现在 require 链上;require 分支的 types 用 .d.cts 对应。开发态 require 条件即指向 dist:dist 是 require 语义的真实载体,未 build 时 require 失败属预期(build 前置)。D5 豁免终止(post-convergence 设计 §3.2 B-2 / D5-补注,2026-09):曾为此保留的 `./*` -> src 开发态通配已删除——壳侧深路径豁免终止,生产消费收口到主入口 barrel(137 符号,逐名可审)与上列受控子入口,删通配后壳再写深路径 = tsc 编译错误(不再是风格问题);壳测试侧带 .ts 后缀的深路径(from/vi.mock/动态 import)经壳 vitest.config.ts 正则 alias 物理解析到 core src(生产 barrel import 无路径段、子入口 specifier 无 .ts 后缀,均不命中该 alias),不经 exports——生产走 exports / 测试走 alias 的双轨解析对通配删除免疫。发布面从不带该通配,npm 消费面维持上列受控入口不变。workflows/ 资产 .cjs/.js 不编译(D1:src=dist 同字节直发),require/import 条件同径。tsup 多入口保形输出见 tsup.config.ts(dist/<entry> 与 src 同构,d.ts/d.cts 全覆盖)。",
76
76
  "files": [
77
77
  "src/",
78
78
  "workflows/",
@@ -84,7 +84,7 @@
84
84
  "ajv": "^8.20.0",
85
85
  "proper-lockfile": "^4.1.2",
86
86
  "yaml": "^2.9.0",
87
- "@xyz-agent/extension-protocol": "0.8.0"
87
+ "@xyz-agent/extension-protocol": "0.8.2"
88
88
  },
89
89
  "devDependencies": {
90
90
  "@types/node": "^24.0.0",
@@ -44,7 +44,6 @@ describe("resolveAgentOpts schema prompt wording + M2 content passthrough", () =
44
44
  prompt: "x",
45
45
  agent: "/abs/path/worker.md",
46
46
  description: "test",
47
- slug: "test",
48
47
  };
49
48
  const result = resolveAgentOpts(opts);
50
49
 
@@ -66,7 +66,7 @@ vi.mock("../execution/alive-store.ts", () => ({
66
66
  writeAliveMarker: vi.fn(),
67
67
  }));
68
68
 
69
- vi.mock("../execution/temp-prompt.ts", () => ({
69
+ vi.mock("../execution/engine/engines/pi/temp-prompt.ts", () => ({
70
70
  writePromptToTempFile: vi.fn(async (agent: string, content: string) => {
71
71
  captured.calls++;
72
72
  captured.content = content;
@@ -79,7 +79,7 @@ vi.mock("../execution/temp-prompt.ts", () => ({
79
79
  import { spawn } from "node:child_process";
80
80
 
81
81
  import { createRecord } from "../execution/execution-record.ts";
82
- import { runSpawn, type RunOptions, type SessionRunnerContext } from "../execution/session-runner.ts";
82
+ import { runSpawn, type RunOptions, type SessionRunnerContext } from "../execution/engine/engines/pi/session-runner.ts";
83
83
 
84
84
  const mockSpawn = vi.mocked(spawn);
85
85
 
@@ -116,8 +116,9 @@ function makeRecord() {
116
116
  return createRecord(`append-asm-${seq}`, {
117
117
  agent: "general-purpose",
118
118
  model: "test/model",
119
- mode: "sync",
119
+ mode: "background",
120
120
  task: "test task",
121
+ slug: "append-asm",
121
122
  startedAt: Date.now(),
122
123
  rootSessionId: "s1",
123
124
  parentRecordId: undefined,
@@ -127,7 +128,7 @@ function makeRecord() {
127
128
 
128
129
  function makeRunOpts(overrides: Partial<RunOptions> = {}): RunOptions {
129
130
  return {
130
- resolved: { model: { provider: "test", id: "model" }, thinkingLevel: undefined },
131
+ resolved: { model: { provider: "test", id: "model", name: "Model", reasoning: false }, thinkingLevel: undefined },
131
132
  agentConfig: undefined,
132
133
  appendSystemPrompt: undefined,
133
134
  skillPath: undefined,
@@ -178,7 +179,7 @@ describe("writeAppendSystemPromptFile 组装(经 runSpawn 驱动)", () => {
178
179
  it("全片段组装:env block → agent body → 调用方片段 → wrap-up hint,顺序稳定", async () => {
179
180
  const content = await captureAppendContent(
180
181
  makeRunOpts({
181
- agentConfig: { systemPrompt: "AGENT-BODY-MARKER" },
182
+ agentConfig: { name: "worker", systemPrompt: "AGENT-BODY-MARKER" },
182
183
  appendSystemPrompt: ["FRAG-ONE", "FRAG-TWO"],
183
184
  maxTurns: 5,
184
185
  }),
@@ -207,7 +208,7 @@ describe("writeAppendSystemPromptFile 组装(经 runSpawn 驱动)", () => {
207
208
  });
208
209
 
209
210
  it("ask_user RPC 提示 mode 门控:rpc(gui 响应)注入,json(headless)不注入", async () => {
210
- const opts = makeRunOpts({ agentConfig: { tools: ["ask_user"] } });
211
+ const opts = makeRunOpts({ agentConfig: { name: "worker", systemPrompt: "", tools: ["ask_user"] } });
211
212
  const rpcContent = await captureAppendContent(opts, makeCtx({ mode: "rpc" }));
212
213
  expect(rpcContent).toContain("ask_user Tool Availability");
213
214
  const jsonContent = await captureAppendContent(opts, makeCtx({ mode: "json" }));
@@ -217,7 +218,7 @@ describe("writeAppendSystemPromptFile 组装(经 runSpawn 驱动)", () => {
217
218
 
218
219
  it("mode 响应但 tools 不含 ask_user → 不注入", async () => {
219
220
  const content = await captureAppendContent(
220
- makeRunOpts({ agentConfig: { tools: ["read", "bash"] } }),
221
+ makeRunOpts({ agentConfig: { name: "worker", systemPrompt: "", tools: ["read", "bash"] } }),
221
222
  makeCtx({ mode: "rpc" }),
222
223
  );
223
224
  expect(content).not.toContain("ask_user Tool Availability");
@@ -1,7 +1,7 @@
1
1
  import { describe, expect,it } from "vitest";
2
2
 
3
- import { parseSpawnLine } from "../execution/spawn-event-adapter";
4
- import { sendGetStateCommand } from "../execution/stdin-writer";
3
+ import { parseSpawnLine } from "../execution/engine/engines/pi/spawn-event-adapter";
4
+ import { sendGetStateCommand } from "../execution/engine/engines/pi/stdin-writer";
5
5
 
6
6
  describe("FR-4: get_state RPC handshake", () => {
7
7
  describe("sendGetStateCommand", () => {
@@ -19,7 +19,6 @@ describe("M2 append-content probe (design.json TC1)", () => {
19
19
  schema: { type: "object", properties: { ok: { type: "boolean" } } },
20
20
  agent: "/fake/agents/worker.md",
21
21
  description: "m2-probe",
22
- slug: "m2-probe",
23
22
  };
24
23
 
25
24
  const result = resolveAgentOpts(opts);
@@ -58,7 +58,7 @@ describe("ManifestStore", () => {
58
58
  });
59
59
 
60
60
  afterEach(() => {
61
- fs.rmSync(tmpDir, { recursive: true, force: true });
61
+ fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
62
62
  });
63
63
 
64
64
  describe("writeManifest", () => {
@@ -108,7 +108,7 @@ describe("ManifestStore", () => {
108
108
  };
109
109
 
110
110
  // Delete the directory to cause write failure
111
- fs.rmSync(tmpDir, { recursive: true, force: true });
111
+ fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
112
112
 
113
113
  await expect(store.writeManifest(record)).rejects.toThrow();
114
114
  });
@@ -205,7 +205,7 @@ describe("ManifestStore", () => {
205
205
  describe("listAllSync (A3)", () => {
206
206
  it("正常读:返回目录下所有合法 manifest", async () => {
207
207
  await store.writeManifest({ id: "a-1", rootSessionId: "s", agentName: "w", status: "running" as const, createdAt: 1 });
208
- await store.writeManifest({ id: "a-2", rootSessionId: "s", agentName: "w", status: "completed" as const, createdAt: 2 });
208
+ await store.writeManifest({ id: "a-2", rootSessionId: "s", agentName: "w", status: "closed" as const, createdAt: 2 });
209
209
  const all = store.listAllSync();
210
210
  expect(all.length).toBe(2);
211
211
  expect(all.map((r) => r.id).sort()).toEqual(["a-1", "a-2"]);
@@ -240,8 +240,9 @@ describe("ManifestStore", () => {
240
240
  });
241
241
  });
242
242
 
243
- // ── M3: 4 status 枚举(running/completed/failed/cancelledcrashed 不进 manifest)──
244
- describe("4 status 枚举 (M3)", () => {
243
+ // ── M3: status 枚举(SP-1 running/closed/cancelled 三态;crashed 不进 manifest
244
+ // 历史 completed/failed 由读侧 mapManifestStatus 映射为 closed)──
245
+ describe("status 枚举 (M3)", () => {
245
246
  it("cancelled 能写入 + 读回(不再归并 failed)", async () => {
246
247
  const record = {
247
248
  id: "test-cancelled-4state",
@@ -257,14 +258,14 @@ describe("ManifestStore", () => {
257
258
  expect(result?.status).toBe("cancelled");
258
259
  });
259
260
 
260
- it("listAllSync 接受 4 态(含 cancelled)", async () => {
261
+ it("listAllSync 接受全部合法态(含 cancelled)", async () => {
261
262
  await store.writeManifest({ id: "s-running", rootSessionId: "s", agentName: "w", status: "running" as const, createdAt: 1 });
262
- await store.writeManifest({ id: "s-completed", rootSessionId: "s", agentName: "w", status: "completed" as const, createdAt: 2 });
263
- await store.writeManifest({ id: "s-failed", rootSessionId: "s", agentName: "w", status: "failed" as const, createdAt: 3 });
263
+ await store.writeManifest({ id: "s-completed", rootSessionId: "s", agentName: "w", status: "closed" as const, createdAt: 2 });
264
+ await store.writeManifest({ id: "s-failed", rootSessionId: "s", agentName: "w", status: "closed" as const, createdAt: 3 });
264
265
  await store.writeManifest({ id: "s-cancelled", rootSessionId: "s", agentName: "w", status: "cancelled" as const, createdAt: 4 });
265
266
  const all = store.listAllSync();
266
267
  expect(all.length).toBe(4);
267
- expect(all.map((r) => r.status).sort()).toEqual(["cancelled", "completed", "failed", "running"]);
268
+ expect(all.map((r) => r.status).sort()).toEqual(["cancelled", "closed", "closed", "running"]);
268
269
  });
269
270
 
270
271
  it("isValidManifest 拒绝 crashed(crashed 不进 manifest)", async () => {
@@ -66,7 +66,6 @@ describe("RecordStore per-file cache + light scan [perf]", () => {
66
66
  agent: opts.agent ?? "worker",
67
67
  mode: "background",
68
68
  task: "test task",
69
- slug: "test",
70
69
  startedAt: opts.startedAt ?? 1000,
71
70
  rootSessionId: opts.rootSessionId ?? "root-1",
72
71
  depth: 0,
@@ -266,7 +265,6 @@ describe("RecordStore per-file cache + light scan [perf]", () => {
266
265
  const mem = {
267
266
  id: "sa-1",
268
267
  agent: "worker",
269
- slug: "test",
270
268
  status: "running",
271
269
  mode: "background",
272
270
  startedAt: 1000,
@@ -78,11 +78,11 @@ describe("sessions-index 模块(S1TC10-12)", () => {
78
78
  return {
79
79
  mtimeMs: 111,
80
80
  size: 222,
81
+ slug: "t",
81
82
  id: "sa-1",
82
83
  agent: "worker",
83
84
  mode: "background",
84
85
  task: "test task",
85
- slug: "test",
86
86
  startedAt: 1000,
87
87
  rootSessionId: "root-1",
88
88
  parentRecordId: undefined,
@@ -208,7 +208,6 @@ describe("RecordStore 索引接入 [perf L-1](S1TC1-9/13)", () => {
208
208
  agent: opts.agent ?? "worker",
209
209
  mode: "background",
210
210
  task: "test task",
211
- slug: "test",
212
211
  startedAt: opts.startedAt ?? 1000,
213
212
  rootSessionId: opts.rootSessionId ?? "root-1",
214
213
  depth: 0,
@@ -286,7 +286,9 @@ describe("review-fix-loop.js 模块形态约束", () => {
286
286
  // 本 import 语句同时是静态依赖边:让依赖分析把该 workflow 文件纳入测试可达域
287
287
  // (CRAP 覆盖估算)。顶层 return / require 决定了 import 必然 reject——这是
288
288
  // workflow 脚本的固有形态,抽取测试法(本文件)因此是唯一可行的直测途径。
289
- await expect(import("../../workflows/review-fix-loop.js")).rejects.toThrow();
289
+ // `as string` 使 import() 参数脱离字面量模块解析(该文件顶层 return,非合法模块,
290
+ // 本就无类型可锚);esbuild 转译剥除断言后运行时与字面量形态完全一致
291
+ await expect(import("../../workflows/review-fix-loop.js" as string)).rejects.toThrow();
290
292
  });
291
293
  });
292
294
 
@@ -320,7 +322,7 @@ describe("review-fix-loop.js fixAgent=fallow-scan 显式拒收(RX2-F2)", ()
320
322
  });
321
323
 
322
324
  afterEach(() => {
323
- rmSync(sandboxDir, { recursive: true, force: true });
325
+ rmSync(sandboxDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
324
326
  });
325
327
 
326
328
  /** -e 探针体:AsyncFunction 复刻 worker 模板宿主形态(workerData/$ARGS/log 注入)。 */
@@ -450,7 +450,7 @@ describe("reconcileIssues", () => {
450
450
  const r = reconcileIssues(prev, { seenIds: new Set(), escalateIds: new Set(), round: 2, stuckThreshold: 3 });
451
451
  expect(r.issues["MF-1"].status).toBe("fixed");
452
452
  expect(r.issues["MF-2"].status).toBe("fixed");
453
- expect(r.issues["MF-2"].history.at(-1).status).toBe("fixed");
453
+ expect(r.issues["MF-2"].history!.at(-1)!.status).toBe("fixed");
454
454
  expect(r.stuck).toBe(false);
455
455
  expect(r.knownRemaining).toEqual([]);
456
456
  });
@@ -495,7 +495,7 @@ describe("reconcileIssues", () => {
495
495
  expect(r.issues["MF-1"].status).toBe("regressed");
496
496
  expect(r.issues["MF-1"].fixAttempts).toBe(2);
497
497
  expect(r.issues["MF-1"].openStreak).toBe(1);
498
- expect(r.issues["MF-1"].history.at(-1).status).toBe("regressed");
498
+ expect(r.issues["MF-1"].history!.at(-1)!.status).toBe("regressed");
499
499
  expect(r.stuck).toBe(false);
500
500
  });
501
501
  it("fixed 未再被报告(未 seen)→ 保持 fixed,不误转 regressed(MF-2)", () => {
@@ -616,7 +616,7 @@ describe("reconcileIssues escalate + fixAttempts 起点", () => {
616
616
  { seenIds: [], escalateIds: ["S-1"], round: 3, stuckThreshold: 3 },
617
617
  );
618
618
  expect(rec.issues["S-1"].status).toBe("open");
619
- expect(rec.issues["S-1"].history.at(-1).status).toBe("escalated");
619
+ expect(rec.issues["S-1"].history!.at(-1)!.status).toBe("escalated");
620
620
  expect(rec.knownRemaining).toEqual([]);
621
621
  });
622
622
  it("deferred 无 escalate → 留 known-remaining", () => {
@@ -1194,8 +1194,8 @@ describe("T-2 端到端:normIssueId/findIssueKey 在 validateFixResult 的真
1194
1194
 
1195
1195
  // ── T-3:reconcile 新 ID severity:"unknown" 守卫分支 ──────────────────────
1196
1196
  // validateFixResult 的 tracked severity 交叉核对:trackedIssues 中某 ID 的 severity
1197
- // 为 "unknown"(reconcileIssues 给新发现 ID 的默认值,review-fix-loop-utils.cjs:596
1198
- // `severity: "unknown"`)时不覆盖 fix agent 自报 severity——守卫在 cjs:294-299(仅认
1197
+ // 为 "unknown"(reconcileIssues 给新发现 ID 的默认值,review-fix-loop-utils.cjs:935
1198
+ // `severity: "unknown"`)时不覆盖 fix agent 自报 severity——守卫在 cjs:347-355(仅认
1199
1199
  // critical/major/minor/trivial 为真实等级)。现有 MF-4 测试覆盖了 major/critical/minor
1200
1200
  // tracked + 无此 ID,缺 "unknown" 分支。守卫目的:新发现 ID 的 severity 尚未由 reviewer
1201
1201
  // 结构化确认(reconcile 默认 unknown),不应凭默认值把合法 minor deferral 误升级为违规。
@@ -1251,7 +1251,7 @@ describe("A5 resolveRunRoot: 存储根解析(git slug / 非 git cwd / home 不
1251
1251
  expect(root).toBe(join(home, ".review-fix-loop", "Users-x-proj-my-repo", "wf-test-1"));
1252
1252
  expect(made).toEqual([root]);
1253
1253
  } finally {
1254
- rmSync(home, { recursive: true, force: true });
1254
+ rmSync(home, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
1255
1255
  }
1256
1256
  });
1257
1257
 
@@ -1269,7 +1269,7 @@ describe("A5 resolveRunRoot: 存储根解析(git slug / 非 git cwd / home 不
1269
1269
  expect(slug).toBe("tmp-plain-docs");
1270
1270
  expect(root).toBe(join(home, ".review-fix-loop", "tmp-plain-docs", "run-42"));
1271
1271
  } finally {
1272
- rmSync(home, { recursive: true, force: true });
1272
+ rmSync(home, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
1273
1273
  }
1274
1274
  });
1275
1275
 
@@ -1294,7 +1294,7 @@ describe("A5 resolveRunRoot: 存储根解析(git slug / 非 git cwd / home 不
1294
1294
  expect(root).toBe(join(fallbackTmp, "review-fix-loop", "wf-test-2"));
1295
1295
  expect(made).toEqual([root]);
1296
1296
  } finally {
1297
- rmSync(fallbackTmp, { recursive: true, force: true });
1297
+ rmSync(fallbackTmp, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
1298
1298
  }
1299
1299
  });
1300
1300
 
@@ -1313,7 +1313,7 @@ describe("A5 resolveRunRoot: 存储根解析(git slug / 非 git cwd / home 不
1313
1313
  expect(existsSync(root)).toBe(true);
1314
1314
  expect(root).toContain(join(home, ".review-fix-loop", "Users-x-a b-c", "wf-real-1"));
1315
1315
  } finally {
1316
- rmSync(home, { recursive: true, force: true });
1316
+ rmSync(home, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
1317
1317
  }
1318
1318
  });
1319
1319
  });
@@ -1791,7 +1791,7 @@ describe("filterDormantFromRecon + applyCleanRoundBackfill 的 dormant 分区",
1791
1791
  const out = applyCleanRoundBackfill(state, { reconSeen: new Set(["MF-D1"]), reconEscalate: new Set(), round: 2, stuckThreshold: 3 });
1792
1792
  // 过滤生效:MF-D1 不经对账通道建 issue(复活唯一入口 = 聚合活跃重报)
1793
1793
  expect(out.state.issues["MF-D1"]).toBeUndefined();
1794
- expect(out.state.dormant[0].revived).toBe(false);
1794
+ expect(out.state.dormant![0].revived).toBe(false);
1795
1795
  });
1796
1796
  });
1797
1797
 
@@ -7,14 +7,15 @@
7
7
  //(run.state.errorLogs = ...),每次重试的诊断日志都被最后一次覆盖丢失。
8
8
  // 修复:改为 push + 截断(MAX_ERROR_LOGS=500 防无界增长)。
9
9
  //
10
- // 测试搭建方式参照 error-recovery-handlers.test.ts(mock LifecycleDeps + WorkflowRun)。
10
+ // 测试搭建方式参照 worker-message-pump-handlers.test.ts(mock LifecycleDeps + WorkflowRun)。
11
11
  // - handleScriptError 是 export 的 async function,直接 import 调用
12
12
  // - handleReturn 不是 export 的——通过 handleWorkerMessage 发 { type: "return", ... } 触发
13
13
 
14
14
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
15
15
 
16
- import { handleScriptError, handleWorkerMessage } from "../orchestration/error-recovery.ts";
16
+ import { handleScriptError, handleWorkerMessage } from "../orchestration/worker-message-pump.ts";
17
17
  import type { LifecycleDeps, WorkerHandlers } from "../orchestration/models/ports.ts";
18
+ import type { DoneReason, RunStatus } from "../orchestration/models/types.ts";
18
19
  import type { WorkflowRun } from "../orchestration/models/workflow-run.ts";
19
20
 
20
21
  // ── helpers ──────────────────────────────────────────────────
@@ -52,15 +53,15 @@ function makeRunningRun(): WorkflowRun & { resetRunning(): void } {
52
53
  runtime: {
53
54
  worker: { postMessage: vi.fn() },
54
55
  },
55
- transition(target: string, reason?: string): void {
56
+ transition(this: WorkflowRun, target: RunStatus, reason?: DoneReason): void {
56
57
  this.state.status = target;
57
58
  if (target === "done") this.state.reason = reason;
58
59
  },
59
- replaceRuntime(rt: unknown): void {
60
+ replaceRuntime(this: WorkflowRun, rt: NonNullable<WorkflowRun["runtime"]>): void {
60
61
  this.runtime = rt;
61
62
  },
62
63
  // 多次触发 handleReturn 时把状态从 done 重置回 running
63
- resetRunning(): void {
64
+ resetRunning(this: WorkflowRun): void {
64
65
  this.state.status = "running";
65
66
  this.state.reason = undefined;
66
67
  },
@@ -20,7 +20,7 @@ function readSrc(relPath: string): string {
20
20
  // ── M4: node.live cleared before stale guard ─────────────────
21
21
 
22
22
  describe("M4: dispatchAgentCall .then() clears node.live before stale guard", () => {
23
- const src = readSrc(join("src", "orchestration", "error-recovery.ts"));
23
+ const src = readSrc(join("src", "orchestration", "worker-message-pump.ts"));
24
24
 
25
25
  it("node.live = undefined appears before the stale guard return", () => {
26
26
  // 找到 .then 回调中的 stale guard 和 node.live 清理的相对顺序
@@ -41,7 +41,7 @@ describe("M4: dispatchAgentCall .then() clears node.live before stale guard", ()
41
41
  // ── M7: handleWorkerMessage shape validation ─────────────────
42
42
 
43
43
  describe("M7: handleWorkerMessage validates msg before dereferencing", () => {
44
- const src = readSrc(join("src", "orchestration", "error-recovery.ts"));
44
+ const src = readSrc(join("src", "orchestration", "worker-message-pump.ts"));
45
45
 
46
46
  it("handleWorkerMessage has shape guard for msg before dereferencing opts", () => {
47
47
  // handleWorkerMessage 中 `raw as WorkerMsg` 后应有 typeof/形状校验
@@ -3,6 +3,8 @@
3
3
  // M6: worktree cleanup not gated by patchOk (decoupled)
4
4
  // M9: store.save not fire-and-forget (has .catch)
5
5
  // M12: budget-done transition and onRunDone in separate try blocks
6
+ // (D5-② coda 收敛后语义不变、落点转移:budget-done 分支改调 finalizeRun 单写点,
7
+ // transition / unregister+onRunDone 的错误分离在 finalizeRun 函数体内断言)
6
8
  // [u1-move] M10(notifyDone 序列化守卫,读壳侧 interface/helpers.ts 源文本)随壳件
7
9
  // 留守 pi extension 包:src/__tests__/robustness-medium-batch2-interface.test.ts。
8
10
 
@@ -37,7 +39,7 @@ describe("M6: worktree cleanup not gated by patchOk", () => {
37
39
  // ── M9: store.save has .catch (not fire-and-forget) ──────────
38
40
 
39
41
  describe("M9: store.save not fire-and-forget in dispatchAgentCall", () => {
40
- const src = readSrc(join("src", "orchestration", "error-recovery.ts"));
42
+ const src = readSrc(join("src", "orchestration", "worker-message-pump.ts"));
41
43
 
42
44
  it("no bare `void deps.store.save` without .catch", () => {
43
45
  // 查找所有 void deps.store.save(run) 的出现
@@ -48,18 +50,27 @@ describe("M9: store.save not fire-and-forget in dispatchAgentCall", () => {
48
50
  });
49
51
  });
50
52
 
51
- // ── M12: budget-done has separate try blocks ─────────────────
53
+ // ── M12: budget-done coda finalizeRun 单写点(错误分离语义不变) ──
52
54
 
53
55
  describe("M12: budget-done separates transition and onRunDone error handling", () => {
54
- const src = readSrc(join("src", "orchestration", "error-recovery.ts"));
56
+ const src = readSrc(join("src", "orchestration", "worker-message-pump.ts"));
55
57
 
56
- it("budget-done block has more than one catch (transition vs onRunDone separated)", () => {
58
+ it("budget-done branch delegates to finalizeRun (D5-② single coda write point)", () => {
57
59
  // 找到 budget isExceeded 块
58
60
  const budgetMatch = src.match(/budget\.isExceeded\(\)[\s\S]*?\}\s*\}\s*\)/);
59
61
  expect(budgetMatch).toBeTruthy();
60
62
  const budgetBlock = budgetMatch![0];
61
- // 修复后应有多个 catch(至少 2 个:一个给 transition,一个给 onRunDone/emit)
62
- const catchCount = (budgetBlock.match(/\bcatch\b/g) || []).length;
63
+ // coda 收敛后:budget-done 分支只调 finalizeRun(transition/save/unregister/onRunDone
64
+ // 四步不再内联复制)
65
+ expect(budgetBlock).toContain("finalizeRun(run, deps, \"budget_limited\"");
66
+ });
67
+
68
+ it("finalizeRun body separates transition and onRunDone error handling (>= 2 catch)", () => {
69
+ // finalizeRun 函数体:transition 的 try/catch 与 unregister/onRunDone 的 try/catch
70
+ // 分离(M12 语义锚定不变,随 coda 收敛转移至单写点内)
71
+ const fnMatch = src.match(/export async function finalizeRun\([\s\S]*?\n\}/);
72
+ expect(fnMatch, "finalizeRun 函数定义应存在").toBeTruthy();
73
+ const catchCount = (fnMatch![0].match(/\bcatch\b/g) || []).length;
63
74
  expect(catchCount).toBeGreaterThanOrEqual(2);
64
75
  });
65
76
  });
@@ -6,7 +6,7 @@
6
6
  //
7
7
  // 通过 handleWorkerMessage 触发 dispatchAgentCall / dispatchWorkflowCall(内部函数不 export)。
8
8
  // Mock 构造模式参考 orchestration/__tests__/agent-call-catch-fallback.test.ts 和
9
- // orchestration/__tests__/error-recovery-workflow-call.test.ts。
9
+ // orchestration/__tests__/worker-message-pump-workflow-call.test.ts。
10
10
 
11
11
  import { describe, expect, it, vi } from "vitest";
12
12
 
@@ -22,7 +22,7 @@ vi.mock("../core/logger.ts", () => ({
22
22
  getLogger: () => loggerMock,
23
23
  }));
24
24
 
25
- import { handleWorkerMessage } from "../orchestration/error-recovery.ts";
25
+ import { handleWorkerMessage } from "../orchestration/worker-message-pump.ts";
26
26
  import type { LifecycleDeps, WorkerHandlers } from "../orchestration/models/ports.ts";
27
27
  import { Trace } from "../orchestration/models/trace.ts";
28
28
  import type { AgentResult } from "../orchestration/models/types.ts";
@@ -12,7 +12,7 @@
12
12
  * 因带 delta 字段被误判为 text_delta。正向判定(只放行 text_delta)根治。
13
13
  */
14
14
  import { describe, it, expect } from "vitest";
15
- import { mapAssistantMessageDelta } from "../execution/session-runner.js";
15
+ import { mapAssistantMessageDelta } from "../execution/engine/engines/pi/session-runner.js";
16
16
 
17
17
  describe("mapAssistantMessageDelta: assistantMessageEvent → streaming 事件分流", () => {
18
18
  it("text_delta → forward 为 text_delta", () => {
@@ -62,13 +62,13 @@ describe("getHostServices(未配置 → NULL_HOST)", () => {
62
62
 
63
63
  host.log("warn", "comp-a", "w-message", { k: 1 });
64
64
  expect(warnSpy).toHaveBeenCalledTimes(1);
65
- expect(warnSpy.mock.calls[0][0]).toBe("[comp-a] w-message");
65
+ expect(warnSpy.mock.calls[0]![0]).toBe("[comp-a] w-message");
66
66
  expect(warnSpy.mock.calls[0][1]).toEqual({ k: 1 });
67
67
  expect(errorSpy).not.toHaveBeenCalled();
68
68
 
69
69
  host.log("error", "comp-a", "e-message");
70
70
  expect(errorSpy).toHaveBeenCalledTimes(1);
71
- expect(errorSpy.mock.calls[0][0]).toBe("[comp-a] e-message");
71
+ expect(errorSpy.mock.calls[0]![0]).toBe("[comp-a] e-message");
72
72
  });
73
73
 
74
74
  it("data 缺省时省略第二参数(node console 会把显式 undefined 打成尾巴)", () => {
@@ -24,7 +24,7 @@ describe("facade 顶层缓存惯例 + configureCore 前后透明切换(时序
24
24
  const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
25
25
  topLevelLogger.warn("before-configure", { stage: 1 });
26
26
  expect(warnSpy).toHaveBeenCalledTimes(1);
27
- expect(warnSpy.mock.calls[0][0]).toBe("[top-level-comp] before-configure");
27
+ expect(warnSpy.mock.calls[0]![0]).toBe("[top-level-comp] before-configure");
28
28
  expect(warnSpy.mock.calls[0][1]).toEqual({ stage: 1 });
29
29
 
30
30
  // 2) configureCore:宿主 log 接线(模拟宿主壳初始化时点,晚于本模块加载)。
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 从任意 thrown 值提取可读的错误信息字符串:Error → `.message`,其它 → `String(e)`。
3
+ *
4
+ * 各包独立持有本 helper(core/renderer/runtime/subagent-core/electron/ext-guards 同实现),
5
+ * 不引跨包依赖——收敛 `e instanceof Error ? e.message : String(e)` 样板。
6
+ */
7
+ export function toErrorMessage(e: unknown): string {
8
+ return e instanceof Error ? e.message : String(e);
9
+ }
@@ -45,16 +45,32 @@ export interface HostServices {
45
45
  * 供无自有数据根的轻宿主显式采用;core 自身不静默兜底到该值。 */
46
46
  export const DEFAULT_DATA_ROOT: string = join(homedir(), ".subagent-core");
47
47
 
48
- // 模块级配置态:configureCore 覆盖式写入(重复调用以后者覆盖——测试切宿主依赖此语义)。
49
- let configuredHost: HostServices | undefined;
48
+ // 配置态持有:globalThis[Symbol.for] slot(post-convergence D9 根治)。模块级 `let`
49
+ // dist 双形态(主 bundle × 子入口 bundle 各持模块副本)下会被分裂——configureCore
50
+ // 只写主 bundle 副本,子入口侧恒 undefined。slot 对象形态(非直接存值)规避
51
+ // 「undefined 值与无 key 不可区分」;范式与 execution/subagent-service.ts 进程单例
52
+ // slot 同型。读写语义不变:configureCore 覆盖式写入
53
+ // (重复调用以后者覆盖——测试切宿主依赖此语义)。
54
+ const HOST_SLOT_KEY = Symbol.for("@zhushanwen/subagent-core.host-services");
55
+
56
+ type HostSlot = { current: HostServices | undefined };
57
+
58
+ function getHostSlot(): HostSlot {
59
+ let slot = Reflect.get(globalThis, HOST_SLOT_KEY) as HostSlot | undefined;
60
+ if (!slot) {
61
+ slot = { current: undefined };
62
+ Reflect.set(globalThis, HOST_SLOT_KEY, slot);
63
+ }
64
+ return slot;
65
+ }
50
66
 
51
67
  export function configureCore(host: HostServices): void {
52
- configuredHost = host;
68
+ getHostSlot().current = host;
53
69
  }
54
70
 
55
71
  /** 测试隔离专用:清空配置态(生产禁用——生产宿主配置一次后生命周期与进程一致)。 */
56
72
  export function resetCoreForTests(): void {
57
- configuredHost = undefined;
73
+ getHostSlot().current = undefined;
58
74
  }
59
75
 
60
76
  const NULL_HOST: HostServices = {
@@ -93,5 +109,5 @@ const NULL_HOST: HostServices = {
93
109
  };
94
110
 
95
111
  export function getHostServices(): HostServices {
96
- return configuredHost ?? NULL_HOST;
112
+ return getHostSlot().current ?? NULL_HOST;
97
113
  }
@@ -102,16 +102,29 @@ export interface NotifyDomainPorts {
102
102
  createDelivery?(port: DeliveryPort, options?: DeliveryConfig): DeliveryHandle;
103
103
  }
104
104
 
105
- // 模块级配置态(与 host-services 同款覆盖式语义——重复注入以后者覆盖)。
106
- let configuredPorts: NotifyDomainPorts | undefined;
105
+ // 配置态持有:globalThis[Symbol.for] slot(与 host-services 同款覆盖式语义——重复
106
+ // 注入以后者覆盖;post-convergence D9 根治,dist 双形态下免模块副本分裂,范式与
107
+ // execution/subagent-service.ts 进程单例 slot 同型)。
108
+ const NOTIFY_PORTS_SLOT_KEY = Symbol.for("@zhushanwen/subagent-core.notify-ports");
109
+
110
+ type NotifyPortsSlot = { current: NotifyDomainPorts | undefined };
111
+
112
+ function getNotifyPortsSlot(): NotifyPortsSlot {
113
+ let slot = Reflect.get(globalThis, NOTIFY_PORTS_SLOT_KEY) as NotifyPortsSlot | undefined;
114
+ if (!slot) {
115
+ slot = { current: undefined };
116
+ Reflect.set(globalThis, NOTIFY_PORTS_SLOT_KEY, slot);
117
+ }
118
+ return slot;
119
+ }
107
120
 
108
121
  export function configureNotifyDomain(ports: NotifyDomainPorts): void {
109
- configuredPorts = ports;
122
+ getNotifyPortsSlot().current = ports;
110
123
  }
111
124
 
112
125
  /** 测试隔离专用:清空注入态(生产禁用——注入点在宿主壳初始化,生命周期与进程一致)。 */
113
126
  export function resetNotifyDomainForTests(): void {
114
- configuredPorts = undefined;
127
+ getNotifyPortsSlot().current = undefined;
115
128
  }
116
129
 
117
130
  const DEFAULT_NOTIFY_PORTS: NotifyDomainPorts = {
@@ -122,5 +135,5 @@ const DEFAULT_NOTIFY_PORTS: NotifyDomainPorts = {
122
135
  };
123
136
 
124
137
  export function getNotifyDomainPorts(): NotifyDomainPorts {
125
- return configuredPorts ?? DEFAULT_NOTIFY_PORTS;
138
+ return getNotifyPortsSlot().current ?? DEFAULT_NOTIFY_PORTS;
126
139
  }
@@ -7,7 +7,7 @@
7
7
  // (meta=null 单行兜底)与 parseResourceMeta 严格层新字段投影断言
8
8
  // (AgentMeta 扩 maxTurns/disallowedTools/skills 的 typecheckMeta 行为)。
9
9
 
10
- import { describe, expect, fail, it } from "vitest";
10
+ import { describe, expect, it } from "vitest";
11
11
 
12
12
  import { parseResourceMeta } from "../../shared/meta-parser.ts";
13
13
  import { parseAgentProfile } from "../agent-registry.ts";
@@ -172,7 +172,7 @@ body`,
172
172
  "agent",
173
173
  );
174
174
  expect(meta).not.toBeNull();
175
- if (meta?.kind !== "agent") return fail("kind 应为 agent");
175
+ if (meta?.kind !== "agent") return expect.fail("kind 应为 agent");
176
176
  expect(meta.maxTurns).toBe(2);
177
177
  expect(meta.disallowedTools).toEqual(["write"]);
178
178
  expect(meta.skills).toEqual(["code-review"]);
@@ -200,7 +200,7 @@ body`,
200
200
  "agent",
201
201
  );
202
202
  expect(meta).not.toBeNull();
203
- if (meta?.kind !== "agent") return fail("kind 应为 agent");
203
+ if (meta?.kind !== "agent") return expect.fail("kind 应为 agent");
204
204
  expect("disallowedTools" in meta).toBe(true);
205
205
  expect(meta.disallowedTools).toEqual([]);
206
206
  expect("skills" in meta).toBe(true);
@@ -224,7 +224,7 @@ body`,
224
224
  "agent",
225
225
  );
226
226
  expect(meta).not.toBeNull();
227
- if (meta?.kind !== "agent") return fail("kind 应为 agent");
227
+ if (meta?.kind !== "agent") return expect.fail("kind 应为 agent");
228
228
  expect("maxTurns" in meta).toBe(false);
229
229
  expect("disallowedTools" in meta).toBe(false);
230
230
  expect("skills" in meta).toBe(false);