@zhushanwen/pi-subagent-workflow 8.6.0 → 8.8.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 (364) hide show
  1. package/README.md +5 -11
  2. package/package.json +13 -20
  3. package/relay/relay.mjs +1 -1
  4. package/skills/workflow-script-format/SKILL.md +32 -13
  5. package/src/host/__tests__/pi-host.test.ts +235 -0
  6. package/src/host/pi-host.ts +163 -0
  7. package/src/index.ts +141 -138
  8. package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
  9. package/src/injectors/__tests__/engine-section-stability.test.ts +343 -0
  10. package/src/injectors/__tests__/model-list-injector.test.ts +18 -21
  11. package/src/injectors/__tests__/subagent-list-injector.test.ts +59 -19
  12. package/src/injectors/__tests__/workflow-list-injector.test.ts +31 -17
  13. package/src/injectors/engine-awareness.ts +119 -0
  14. package/src/injectors/model-list-injector.ts +15 -58
  15. package/src/injectors/subagent-list-injector.ts +56 -114
  16. package/src/injectors/workflow-list-injector.ts +37 -70
  17. package/src/interface/__tests__/detectors.test.ts +48 -37
  18. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +2 -2
  19. package/src/interface/__tests__/subagent-tool-prompt.test.ts +6 -3
  20. package/src/interface/__tests__/tool-workflow-run-builtin-name.test.ts +216 -0
  21. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +17 -6
  22. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +38 -2
  23. package/src/interface/bg-notify-render.ts +7 -17
  24. package/src/interface/command-actions.ts +5 -15
  25. package/src/interface/commands.ts +4 -4
  26. package/src/interface/format.ts +17 -6
  27. package/src/interface/gui-mappers.ts +18 -22
  28. package/src/interface/helpers.ts +9 -130
  29. package/src/interface/list-component.ts +5 -5
  30. package/src/interface/list-shared.ts +3 -3
  31. package/src/interface/list-view.ts +3 -3
  32. package/src/interface/subagent-actions.ts +66 -439
  33. package/src/interface/subagent-tool-schema.ts +21 -17
  34. package/src/interface/subagent-tool.ts +12 -7
  35. package/src/interface/subagents.ts +4 -4
  36. package/src/interface/tool-render.ts +37 -15
  37. package/src/interface/tool-workflow-script.ts +34 -76
  38. package/src/interface/tool-workflow.ts +57 -94
  39. package/src/interface/views/WorkflowsView.ts +8 -16
  40. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  41. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  42. package/src/interface/views/detail-content.ts +4 -4
  43. package/src/interface/views/format.ts +23 -62
  44. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +137 -225
  45. package/agents/analyst.md +0 -61
  46. package/agents/coder.md +0 -70
  47. package/agents/debugger.md +0 -67
  48. package/agents/doc-reviewer.md +0 -50
  49. package/agents/explorer.md +0 -64
  50. package/agents/general-purpose.md +0 -32
  51. package/agents/orchestrator.md +0 -63
  52. package/agents/planner.md +0 -54
  53. package/agents/researcher.md +0 -65
  54. package/agents/reviewer.md +0 -74
  55. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  56. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  57. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  58. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  59. package/src/execution/__tests__/alive-store.test.ts +0 -147
  60. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  61. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  62. package/src/execution/__tests__/bg-notify-render.test.ts +0 -329
  63. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  64. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -601
  65. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  66. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  67. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  68. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  69. package/src/execution/__tests__/config.test.ts +0 -110
  70. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  71. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  72. package/src/execution/__tests__/delivery-methods.test.ts +0 -422
  73. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  74. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  75. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  76. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  77. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  78. package/src/execution/__tests__/execution-record.test.ts +0 -1394
  79. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +0 -171
  80. package/src/execution/__tests__/finalize-record.test.ts +0 -368
  81. package/src/execution/__tests__/finalized-marker.test.ts +0 -82
  82. package/src/execution/__tests__/format-schema-instruction.test.ts +0 -169
  83. package/src/execution/__tests__/format.test.ts +0 -458
  84. package/src/execution/__tests__/gc-timer.test.ts +0 -184
  85. package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
  86. package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
  87. package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
  88. package/src/execution/__tests__/helpers/spawn-mock.ts +0 -242
  89. package/src/execution/__tests__/host-mode.test.ts +0 -87
  90. package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
  91. package/src/execution/__tests__/index-session-start.test.ts +0 -672
  92. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  93. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -383
  94. package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
  95. package/src/execution/__tests__/list-component.test.ts +0 -401
  96. package/src/execution/__tests__/list-fields.test.ts +0 -140
  97. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  98. package/src/execution/__tests__/model-resolver.test.ts +0 -465
  99. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
  100. package/src/execution/__tests__/nested-visibility.test.ts +0 -325
  101. package/src/execution/__tests__/notifier-flush.test.ts +0 -612
  102. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  103. package/src/execution/__tests__/notify-ledger.test.ts +0 -826
  104. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  105. package/src/execution/__tests__/output-collector.test.ts +0 -358
  106. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  107. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  108. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  109. package/src/execution/__tests__/record-store.test.ts +0 -1057
  110. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  111. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  112. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  113. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  114. package/src/execution/__tests__/relay-env.test.ts +0 -42
  115. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  116. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  117. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  118. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  119. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -687
  120. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  121. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  122. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  123. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -199
  124. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  125. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  126. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  127. package/src/execution/__tests__/session-pending.test.ts +0 -197
  128. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  129. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  130. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -350
  131. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  132. package/src/execution/__tests__/spawn-args.test.ts +0 -445
  133. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  134. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  135. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  136. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  137. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  138. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  139. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  140. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  141. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  142. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  143. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  144. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  145. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  146. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  147. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -599
  148. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  149. package/src/execution/__tests__/timeout-integration.test.ts +0 -615
  150. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  151. package/src/execution/__tests__/tool-action.test.ts +0 -476
  152. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  153. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  154. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  155. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  156. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  157. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  158. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  159. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  160. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  161. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  162. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  163. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  164. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  165. package/src/execution/agent-registry.ts +0 -199
  166. package/src/execution/agent-result-mapper.ts +0 -90
  167. package/src/execution/alive-store.ts +0 -92
  168. package/src/execution/argv-mirror.ts +0 -113
  169. package/src/execution/best-effort.ts +0 -38
  170. package/src/execution/channel-registry-access.ts +0 -144
  171. package/src/execution/concurrency-pool.ts +0 -116
  172. package/src/execution/config.ts +0 -96
  173. package/src/execution/dialog-queue.ts +0 -330
  174. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  175. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  176. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  177. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  178. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  179. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  180. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  181. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  182. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  183. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  184. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  185. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  186. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  187. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  188. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  189. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  190. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  191. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  192. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  193. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  194. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  195. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  196. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  197. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  198. package/src/execution/engine/common/data-dir.ts +0 -62
  199. package/src/execution/engine/common/errors.ts +0 -183
  200. package/src/execution/engine/common/event-journal.ts +0 -254
  201. package/src/execution/engine/common/journal-replay.ts +0 -62
  202. package/src/execution/engine/common/kill-chain.ts +0 -221
  203. package/src/execution/engine/common/nesting-guard.ts +0 -50
  204. package/src/execution/engine/common/persona-router.ts +0 -108
  205. package/src/execution/engine/common/pool-manager.ts +0 -226
  206. package/src/execution/engine/common/schema-emulation.ts +0 -189
  207. package/src/execution/engine/common/session-view-projection.ts +0 -51
  208. package/src/execution/engine/engine-discovery.ts +0 -65
  209. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  210. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  211. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  212. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  213. package/src/execution/engine/engines/pi/reader.ts +0 -48
  214. package/src/execution/engine/engines/pi/registration.ts +0 -35
  215. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  216. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  217. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  218. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  219. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  220. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  221. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  222. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  223. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
  224. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  225. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  226. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  227. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  228. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  229. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  230. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  231. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -658
  232. package/src/execution/engine/host-task-spec.ts +0 -47
  233. package/src/execution/engine/model-prompt.ts +0 -59
  234. package/src/execution/engine/paths.ts +0 -42
  235. package/src/execution/engine/port.ts +0 -153
  236. package/src/execution/engine/registry.ts +0 -123
  237. package/src/execution/engine/routing.ts +0 -218
  238. package/src/execution/engine/types.ts +0 -309
  239. package/src/execution/execute-options-mapper.ts +0 -112
  240. package/src/execution/execution-record.ts +0 -965
  241. package/src/execution/finalize-record.ts +0 -251
  242. package/src/execution/finalized-marker.ts +0 -51
  243. package/src/execution/get-state-handshake.ts +0 -104
  244. package/src/execution/host-mode.ts +0 -56
  245. package/src/execution/idle-gc.ts +0 -47
  246. package/src/execution/lifecycle-manager.ts +0 -513
  247. package/src/execution/lifecycle-predicates.ts +0 -65
  248. package/src/execution/manifest-store.ts +0 -256
  249. package/src/execution/model-config-service.ts +0 -219
  250. package/src/execution/model-resolver.ts +0 -248
  251. package/src/execution/notifier.ts +0 -330
  252. package/src/execution/notify-ledger.ts +0 -580
  253. package/src/execution/output-collector.ts +0 -228
  254. package/src/execution/path-encoding.ts +0 -60
  255. package/src/execution/pi-invocation.ts +0 -120
  256. package/src/execution/record-entry.ts +0 -132
  257. package/src/execution/record-store.ts +0 -1234
  258. package/src/execution/relay-env.ts +0 -37
  259. package/src/execution/session-context-resolver.ts +0 -64
  260. package/src/execution/session-file-gc.ts +0 -120
  261. package/src/execution/session-pending.ts +0 -164
  262. package/src/execution/session-reconstructor.ts +0 -678
  263. package/src/execution/session-runner.ts +0 -1781
  264. package/src/execution/sessions-index.ts +0 -304
  265. package/src/execution/spawn-event-adapter.ts +0 -363
  266. package/src/execution/stdin-writer.ts +0 -198
  267. package/src/execution/stream-sink.ts +0 -126
  268. package/src/execution/subagent-service.ts +0 -2141
  269. package/src/execution/subprocess-agent-runner.ts +0 -317
  270. package/src/execution/temp-prompt.ts +0 -62
  271. package/src/execution/tombstone-store.ts +0 -72
  272. package/src/execution/turn-limiter.ts +0 -102
  273. package/src/execution/types.ts +0 -973
  274. package/src/execution/ui-channels.ts +0 -216
  275. package/src/execution/ui-interaction-model.ts +0 -48
  276. package/src/execution/ui-request-handler-factory.ts +0 -212
  277. package/src/execution/ui-request-observability.ts +0 -81
  278. package/src/execution/ui-request-queue.ts +0 -184
  279. package/src/execution/worktree-manager.ts +0 -688
  280. package/src/execution/worktree-registry.ts +0 -222
  281. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -349
  282. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -202
  283. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -152
  284. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  285. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  286. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -809
  287. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  288. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  289. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  290. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -451
  291. package/src/orchestration/__tests__/jsonl-run-store-corrupt-entry.test.ts +0 -150
  292. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  293. package/src/orchestration/__tests__/jsonl-run-store-retention.test.ts +0 -202
  294. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  295. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -600
  296. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  297. package/src/orchestration/__tests__/lifecycle.test.ts +0 -659
  298. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +0 -95
  299. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -2025
  300. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  301. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -201
  302. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  303. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +0 -368
  304. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  305. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  306. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -563
  307. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  308. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -129
  309. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  310. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  311. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  312. package/src/orchestration/agent-opts-resolver.ts +0 -174
  313. package/src/orchestration/args-validator.ts +0 -127
  314. package/src/orchestration/config-loader.ts +0 -315
  315. package/src/orchestration/error-recovery.ts +0 -1018
  316. package/src/orchestration/execute-agent-call.ts +0 -256
  317. package/src/orchestration/launcher.ts +0 -455
  318. package/src/orchestration/lifecycle.ts +0 -399
  319. package/src/orchestration/models/__tests__/budget.test.ts +0 -307
  320. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  321. package/src/orchestration/models/agent-call.ts +0 -83
  322. package/src/orchestration/models/budget.ts +0 -118
  323. package/src/orchestration/models/ports.ts +0 -164
  324. package/src/orchestration/models/run-runtime.ts +0 -104
  325. package/src/orchestration/models/run-spec.ts +0 -83
  326. package/src/orchestration/models/run-state.ts +0 -44
  327. package/src/orchestration/models/trace.ts +0 -183
  328. package/src/orchestration/models/types.ts +0 -301
  329. package/src/orchestration/models/workflow-run.ts +0 -254
  330. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  331. package/src/orchestration/models/workflow-script.ts +0 -117
  332. package/src/orchestration/script-lint.ts +0 -766
  333. package/src/orchestration/skill-discovery.ts +0 -115
  334. package/src/orchestration/worker-handle.ts +0 -115
  335. package/src/orchestration/worker-host.ts +0 -98
  336. package/src/orchestration/worker-script-builder.ts +0 -421
  337. package/src/orchestration/workflow-files.ts +0 -85
  338. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  339. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  340. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  341. package/src/shared/__tests__/model-ref.test.ts +0 -306
  342. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  343. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  344. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  345. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  346. package/src/shared/__tests__/timer-delay.test.ts +0 -61
  347. package/src/shared/agent-event.ts +0 -13
  348. package/src/shared/agent-ref.ts +0 -57
  349. package/src/shared/meta-parser.ts +0 -261
  350. package/src/shared/model-ref.ts +0 -286
  351. package/src/shared/resource-discovery.ts +0 -811
  352. package/src/shared/resource-meta.ts +0 -65
  353. package/src/shared/schema-env.ts +0 -44
  354. package/src/shared/schema-jsonify.ts +0 -58
  355. package/src/shared/timer-delay.ts +0 -54
  356. package/src/shared/xml-injection.ts +0 -35
  357. package/workflows/README.md +0 -81
  358. package/workflows/_shared/agent-refs.cjs +0 -40
  359. package/workflows/chain.js +0 -131
  360. package/workflows/map-reduce.js +0 -174
  361. package/workflows/parallel.js +0 -148
  362. package/workflows/review-fix-loop-utils.cjs +0 -1309
  363. package/workflows/review-fix-loop.js +0 -1404
  364. package/workflows/scatter-gather.js +0 -178
@@ -1,267 +0,0 @@
1
- // src/execution/__tests__/run-and-finalize-chatmode.test.ts
2
- //
3
- // runAndFinalize 的 chatMode idle 分流测试(M2-A)。
4
- //
5
- // mock session-runner.runSpawn(受控返回 success/failed result),走 SubagentService
6
- // 真实的 runAndFinalize 分流逻辑,验证:
7
- // - chatMode + done → doFinalizeRoundToIdle:record.status=idle、留内存、round+1
8
- // - chatMode + failed → MF-6:回退 idle(可恢复),不销毁(agent 可重试 message 或 close)
9
- // - 非 chatMode + done → doFinalizeRecord:record.status=done、archived(现有行为不变)
10
- //
11
- // 分流效果通过「最终可观察状态」验证(record.status + store.getMutable 是否在内存),
12
- // 不依赖 spy 私有方法调用,更稳健。
13
-
14
- import * as fs from "node:fs";
15
- import * as os from "node:os";
16
- import * as path from "node:path";
17
-
18
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
19
-
20
- // mock logger(doFinalizeRecord 的 manifest 写入降级路径用 logger.error)
21
- const { loggerMock } = vi.hoisted(() => ({
22
- loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn(), info: vi.fn() },
23
- }));
24
- vi.mock("@zhushanwen/pi-extension-logger", () => ({ getLogger: () => loggerMock }));
25
-
26
- // mock session-runner:runSpawn 受控返回 result,killAllSpawnedChildren 空实现。
27
- // 注意:必须在 import SubagentService 之前 mock(vi.mock 提升到顶部)。
28
- vi.mock("../session-runner.ts", () => ({
29
- runSpawn: vi.fn(),
30
- killAllSpawnedChildren: vi.fn(),
31
- }));
32
-
33
- import { runSpawn } from "../session-runner.ts";
34
- import type { SessionRunnerContext } from "../session-runner.ts";
35
- import { createRecord } from "../execution-record.ts";
36
- import { ModelConfigService } from "../model-config-service.ts";
37
- import type { ModelInfo } from "../model-resolver.ts";
38
- import { RecordStore, type StatusFilter } from "../record-store.ts";
39
- import { SubagentService } from "../subagent-service.ts";
40
- import type { PiLike } from "../subagent-service.ts";
41
- import type {
42
- AgentResult,
43
- ExecutionRecord,
44
- ExecuteOptions,
45
- } from "../types.ts";
46
-
47
- const mockRunSpawn = vi.mocked(runSpawn);
48
-
49
- // ── 最小合法 ModelInfo(resolveModel 未注入 registry 会抛错,故 stub;runSpawn 被 mock 不消费)──
50
- const STUB_MODEL: ModelInfo = {
51
- id: "test-model",
52
- name: "Test",
53
- provider: "test",
54
- reasoning: false,
55
- };
56
-
57
- function makeTmpAgentDir(): string {
58
- return fs.mkdtempSync(path.join(os.tmpdir(), "chatmode-test-"));
59
- }
60
-
61
- function makePi(): PiLike & {
62
- appendEntry: ReturnType<typeof vi.fn>;
63
- events: { emit: ReturnType<typeof vi.fn> };
64
- sendMessage: ReturnType<typeof vi.fn>;
65
- } {
66
- return { appendEntry: vi.fn(), events: { emit: vi.fn() }, sendMessage: vi.fn() };
67
- }
68
-
69
- function makeResult(success: boolean): AgentResult {
70
- return {
71
- text: success ? "done" : "err",
72
- turns: 1,
73
- durationMs: 100,
74
- success,
75
- error: success ? undefined : "boom",
76
- sessionId: "sess-1",
77
- toolCalls: [],
78
- };
79
- }
80
-
81
- function makeRecord(chatMode: boolean, id = "sa-test"): ExecutionRecord {
82
- return createRecord(id, {
83
- agent: "general-purpose",
84
- model: "test-model",
85
- mode: "background",
86
- task: "do something",
87
- slug: "test",
88
- startedAt: 1000,
89
- rootSessionId: "root-session",
90
- chatMode,
91
- });
92
- }
93
-
94
- /** 暴露 runAndFinalize + store 的私有访问接口(测试专用 cast)。 */
95
- interface ServiceInternals {
96
- store: RecordStore;
97
- runAndFinalize: (
98
- record: ExecutionRecord,
99
- opts: ExecuteOptions,
100
- ctx: SessionRunnerContext,
101
- identity: {
102
- agent: string;
103
- agentConfig: unknown;
104
- resolved: { model: ModelInfo; thinkingLevel: string | undefined };
105
- },
106
- signal: undefined,
107
- priority: number,
108
- ) => Promise<AgentResult>;
109
- }
110
-
111
- describe("runAndFinalize chatMode idle 分流 (M2-A)", () => {
112
- let agentDir: string;
113
- let modelService: ModelConfigService;
114
- let service: SubagentService;
115
- let internals: ServiceInternals;
116
-
117
- beforeEach(() => {
118
- agentDir = makeTmpAgentDir();
119
- modelService = new ModelConfigService({ agentDir });
120
- service = new SubagentService({ cwd: agentDir, modelService });
121
- service.initSession({ pi: makePi(), sessionId: "root-session" });
122
- internals = service as unknown as ServiceInternals;
123
- mockRunSpawn.mockReset();
124
- });
125
-
126
- afterEach(() => {
127
- service.dispose();
128
- fs.rmSync(agentDir, { recursive: true, force: true });
129
- });
130
-
131
- /** 直接调私有 runAndFinalize(mock runSpawn 后走完整分流逻辑)。 */
132
- async function callRunAndFinalize(record: ExecutionRecord, success: boolean): Promise<void> {
133
- mockRunSpawn.mockResolvedValueOnce(makeResult(success));
134
- const opts: ExecuteOptions = { task: "do something", slug: "test" };
135
- const ctx: SessionRunnerContext = {
136
- cwd: agentDir,
137
- agentDir,
138
- skillDirs: [],
139
- mainCwd: agentDir,
140
- };
141
- const identity = {
142
- agent: "general-purpose",
143
- agentConfig: undefined,
144
- resolved: { model: STUB_MODEL, thinkingLevel: undefined },
145
- };
146
- await internals.runAndFinalize(record, opts, ctx, identity, undefined, 0);
147
- }
148
-
149
- it("chatMode + done → record running(旧 idle 折入),留内存,round 0→1", async () => {
150
- const record = makeRecord(true);
151
- internals.store.register(record);
152
- await callRunAndFinalize(record, true);
153
-
154
- expect(record.status).toBe("running");
155
- expect(record.round).toBe(1);
156
- // record 留内存(未 archive)——idle 分流核心断言(v4 B-1:idle 折入 running)
157
- expect(internals.store.getMutable(record.id)).toBe(record);
158
- });
159
-
160
- it("chatMode + failed → MF-6:回退 running(可恢复),不销毁对话(agent 可重试 message 或 close)", async () => {
161
- const record = makeRecord(true);
162
- internals.store.register(record);
163
- await callRunAndFinalize(record, false);
164
-
165
- // MF-6:chatMode 失败不终态销毁——record 回退 running(留内存),agent 可重试 message 或 close。
166
- expect(record.status).toBe("running");
167
- expect(internals.store.getMutable(record.id)).toBe(record); // 留内存(未 archive)
168
- // record.result 被 finalizeRoundToIdle 设值(MF-2:否则 notifier idle 恒 (empty))。
169
- // makeResult(false) 返回 text:"err" + error:"boom";text 非空 → record.result="err"。
170
- expect(record.result).toBeTruthy();
171
- });
172
-
173
- it("非 chatMode + done → record running(SP-5: 一次性完成后保持活跃,等待 message 触发升级)", async () => {
174
- const record = makeRecord(false);
175
- internals.store.register(record);
176
- await callRunAndFinalize(record, true);
177
-
178
- // SP-5: one-shot 完成后 record 保持 running(旧 idle,非终态归档),用户可通过 message 续聊。
179
- expect(record.status).toBe("running");
180
- expect(internals.store.getMutable(record.id)).toBe(record); // 留内存
181
- });
182
-
183
- it("chatMode 第二轮 done → round 累加(1→2,续聊场景)", async () => {
184
- // 模拟 resume 续聊:第一轮已完成(round=1,旧 idle 折入 running),第二轮 runAndFinalize 再次 done
185
- const record = makeRecord(true);
186
- record.status = "running"; // 第一轮已完成(v4 B-1:旧 idle 折入 running)
187
- record.round = 1;
188
- internals.store.register(record);
189
- await callRunAndFinalize(record, true);
190
-
191
- // 续聊第二轮 done:tryTransition(running→closed) 成功 → chatMode 分流 → finalizeRoundToIdle
192
- // → status 回到 running、round 1→2(record 保持活跃,等待下一轮续聊)。
193
- expect(record.status).toBe("running");
194
- expect(record.round).toBe(2);
195
- expect(mockRunSpawn).toHaveBeenCalled();
196
- });
197
-
198
- it("chatMode + done + closeAfterRound=true → finalizeRecord(done)(不进 idle,M2-B3)", async () => {
199
- // close 优雅关闭(force:false):running 时置 closeAfterRound=true,
200
- // runAndFinalize done 分流终态化为 done(而非进 idle)。
201
- const record = makeRecord(true);
202
- record.status = "running";
203
- record.closeAfterRound = true;
204
- internals.store.register(record);
205
- await callRunAndFinalize(record, true);
206
-
207
- expect(record.status).toBe("closed");
208
- expect(record.closeAfterRound).toBeUndefined(); // 清标志
209
- // 终态化 → archive → 内存无(与 idle 分流「留内存」对比)
210
- expect(internals.store.getMutable(record.id)).toBeUndefined();
211
- });
212
-
213
- it("chatMode + done + 无 closeAfterRound → 进 running(旧 idle 折入,M2-A 行为不变)", async () => {
214
- const record = makeRecord(true);
215
- record.status = "running";
216
- internals.store.register(record);
217
- await callRunAndFinalize(record, true);
218
-
219
- expect(record.status).toBe("running");
220
- expect(record.round).toBe(1);
221
- expect(internals.store.getMutable(record.id)).toBe(record);
222
- });
223
-
224
- it("[M5] 非 chatMode(one-shot)+ done + closeAfterRound=true → 轮完成时消费标志终态化(不进 running-resumable)", async () => {
225
- // one-shot busy 时 close(force:false) 置 closeAfterRound——旧代码非 chatMode 成功分支走
226
- // finalizeRoundToIdle 不消费,tool 返回 {closed:true} 谎报:record 永久 running-resumable、
227
- // 5min idle timer 杀进程、期间还能继续收 message。修复后在本分支消费终态化。
228
- const record = makeRecord(false);
229
- record.status = "running";
230
- record.closeAfterRound = true;
231
- internals.store.register(record);
232
- await callRunAndFinalize(record, true);
233
-
234
- expect(record.status).toBe("closed");
235
- expect(record.closedReason).toBe("user-close");
236
- expect(record.closeAfterRound).toBeUndefined(); // 标志已消费
237
- expect(internals.store.getMutable(record.id)).toBeUndefined(); // archived
238
- });
239
-
240
- it("[M5] chatMode + failed + closeAfterRound=true → 轮完成时消费标志终态化(不回退 resumable)", async () => {
241
- // 失败轮也视为「轮已完成」:close 意图兑现终态化(closedReason=gc),否则标志残留、
242
- // record 被 tool 谎报 closed 后仍可继续收 message。
243
- const record = makeRecord(true);
244
- record.status = "running";
245
- record.closeAfterRound = true;
246
- internals.store.register(record);
247
- await callRunAndFinalize(record, false); // 失败轮
248
-
249
- expect(record.status).toBe("closed");
250
- expect(record.closedReason).toBe("gc"); // !success → gc
251
- expect(record.closeAfterRound).toBeUndefined();
252
- expect(internals.store.getMutable(record.id)).toBeUndefined();
253
- });
254
-
255
- it("[S10] chatMode + failed(无 closeAfterRound)→ 回退 running 后 closedReason 不残留", async () => {
256
- // tryTransition 先设 closed+gc,finalizeRoundToIdle 回退 running——旧代码 closedReason="gc"
257
- // 残留在 running record 上(泄漏进 notify 载荷与 list 投影)。
258
- const record = makeRecord(true);
259
- record.status = "running";
260
- internals.store.register(record);
261
- await callRunAndFinalize(record, false);
262
-
263
- expect(record.status).toBe("running"); // MF-6 回退 resumable
264
- expect(record.closedReason).toBeUndefined(); // [S10] 不残留
265
- expect(internals.store.getMutable(record.id)).toBe(record);
266
- });
267
- });
@@ -1,253 +0,0 @@
1
- // src/execution/__tests__/run-spawn-chatmode-settled.test.ts
2
- //
3
- // [V2 模块 3] chatMode agent_settled 信号换挂单测(Step 3)。
4
- //
5
- // 验证 session-runner 的 V2 改动(5 处):
6
- // ① chatMode record agent_end 不触发 SIGTERM(进程保活,等 agent_settled)
7
- // ② chatMode record agent_settled 触发 armIdleTimer(fake timer + 超时后 kill)
8
- // ③ chatMode agent_settled 调 ctx.onRoundSettled(挂载点,mock 断言被调)
9
- // ④ 非 chatMode agent_settled 不 armIdleTimer、不调 onRoundSettled
10
- //
11
- // mock 结构与 run-spawn-edges.test.ts 一致(FakeChild + session-pending 受控 count=0)。
12
- // lifecycle-manager 用真实模块(hasIdleTimer / _resetLifecycleState 可观测 + 隔离)。
13
-
14
- import { spawn } from "node:child_process";
15
- import * as fs from "node:fs";
16
-
17
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
18
-
19
- vi.mock("node:child_process", async () => {
20
- const { FakeChild } = await import("./helpers/spawn-mock.ts");
21
- return {
22
- spawn: vi.fn(() => new FakeChild()),
23
- // buildEnvBlock 的 git branch 调用(execFile 异步):默认 err-first 兜底 → catch → branch=""
24
- execFile: vi.fn(
25
- (
26
- _cmd: string,
27
- _args: readonly string[],
28
- _opts: unknown,
29
- cb: (err: Error | null, stdout?: string, stderr?: string) => void,
30
- ) => cb(new Error("execFile not configured in this test")),
31
- ),
32
- };
33
- });
34
-
35
- vi.mock("node:fs", async () => {
36
- const actual = await import("node:fs");
37
- return {
38
- default: {
39
- ...actual,
40
- mkdirSync: vi.fn(),
41
- existsSync: vi.fn(() => false),
42
- appendFileSync: vi.fn(),
43
- writeFileSync: vi.fn(),
44
- readdirSync: vi.fn(() => []),
45
- },
46
- mkdirSync: vi.fn(),
47
- existsSync: vi.fn(() => false),
48
- appendFileSync: vi.fn(),
49
- writeFileSync: vi.fn(),
50
- readdirSync: vi.fn(() => []),
51
- promises: actual.promises,
52
- };
53
- });
54
-
55
- vi.mock("../alive-store.ts", () => ({
56
- writeAliveMarker: vi.fn(),
57
- }));
58
-
59
- // chatMode 测试不依赖后代判定(chatMode agent_end 早返回跳过 readActivePending),统一 count=0。
60
- // 非 chatMode 用例 ④ 的 agent_end 走正常 kill 分支(count=0 → SIGTERM)。
61
- vi.mock("../session-pending.ts", () => ({
62
- readActivePendingFromSessionFile: vi.fn(() => ({ count: 0 })),
63
- }));
64
-
65
- vi.mock("../temp-prompt.ts", () => ({
66
- writePromptToTempFile: vi.fn(async (agent: string) => {
67
- const safeName = agent.replace(/[^\w.-]+/g, "_");
68
- return { dir: `/tmp/fake-${safeName}`, filePath: `/tmp/fake-${safeName}/prompt-${safeName}.md` };
69
- }),
70
- cleanupTempPrompt: vi.fn(async () => {}),
71
- }));
72
-
73
- import { runSpawn } from "../session-runner.ts";
74
- import type { SessionRunnerContext } from "../session-runner.ts";
75
- import {
76
- DEFAULT_IDLE_TIMEOUT_MS,
77
- hasIdleTimer,
78
- _resetLifecycleState,
79
- } from "../lifecycle-manager.ts";
80
- import { createRecord } from "../execution-record.ts";
81
- import type { ExecutionRecord } from "../types.ts";
82
- import {
83
- emitStdoutLine,
84
- type FakeChild,
85
- lastSpawnedChild as lastSpawnedChildOf,
86
- makeCtx,
87
- makeOpts,
88
- makeRecord,
89
- sessionHeader,
90
- waitForSpawn as waitForSpawnOf,
91
- } from "./helpers/spawn-mock.ts";
92
-
93
- const mockSpawn = vi.mocked(spawn);
94
-
95
- const lastSpawnedChild = (): FakeChild => lastSpawnedChildOf(mockSpawn);
96
- const waitForSpawn = (timeoutMs = 1000): Promise<void> => waitForSpawnOf(mockSpawn, timeoutMs);
97
-
98
- /** 构造 chatMode record(spawn-mock.makeRecord 默认非 chatMode,此处显式开启)。 */
99
- function makeChatModeRecord(id = "sa-chat"): ExecutionRecord {
100
- return createRecord(id, {
101
- agent: "general-purpose",
102
- model: "test-model",
103
- mode: "sync",
104
- task: "chat task",
105
- slug: "chat",
106
- startedAt: 1_000_000,
107
- rootSessionId: "root-session",
108
- parentRecordId: undefined,
109
- depth: 0,
110
- chatMode: true,
111
- });
112
- }
113
-
114
- describe("[V2 模块 3] chatMode agent_settled 信号换挂", () => {
115
- beforeEach(() => {
116
- vi.clearAllMocks();
117
- // lifecycle-manager 是模块级单例(idleTimers Map 跨用例共享),每用例前清空防泄漏。
118
- _resetLifecycleState();
119
- });
120
-
121
- afterEach(() => {
122
- vi.restoreAllMocks();
123
- vi.useRealTimers();
124
- _resetLifecycleState();
125
- });
126
-
127
- it("① chatMode agent_end → 不触发 SIGTERM(进程保活,等 agent_settled)", async () => {
128
- const record = makeChatModeRecord("sa-chat-end");
129
- const promise = runSpawn(record, "Task: chatmode-end", makeOpts(), makeCtx());
130
-
131
- await waitForSpawn();
132
- const child = lastSpawnedChild();
133
-
134
- emitStdoutLine(child, sessionHeader());
135
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
136
- // 让事件 pump 处理 agent_end(stream flush 异步)
137
- await new Promise((r) => setTimeout(r, 20));
138
-
139
- // [V2 决策 1] chatMode agent_end 不 kill——进程不因轮次死,等 agent_settled。
140
- expect(child.killed).toBe(false);
141
- // agent_end 不 arm idle timer(arm 点是 agent_settled,不是 agent_end)
142
- expect(hasIdleTimer(record.id)).toBe(false);
143
-
144
- // 收尾:手动 close 让 runSpawn resolve(模拟后续 idle timer 超时 kill / 外部终止)
145
- child.stdout.end();
146
- child.stderr.end();
147
- child.emit("close", 143);
148
- const result = await promise;
149
- expect(result.success).toBe(true);
150
- });
151
-
152
- it("② chatMode agent_settled → armIdleTimer,idle 超时后 SIGTERM kill", async () => {
153
- const record = makeChatModeRecord("sa-chat-settled");
154
- const promise = runSpawn(record, "Task: chatmode-settled", makeOpts(), makeCtx());
155
-
156
- await waitForSpawn();
157
- const child = lastSpawnedChild();
158
-
159
- // 必须在 emit agent_settled 前启用 fake timers——armIdleTimer 内 setTimeout 在 agent_settled
160
- // 处理器里新建,新建时已是 fake timer 才可 advance。不 fake setImmediate:stream flush 靠
161
- // 真实事件循环。对齐 run-spawn-edges MF-3/MF-4 模式。
162
- vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout", "Date"] });
163
- try {
164
- emitStdoutLine(child, sessionHeader());
165
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
166
- await new Promise((r) => setImmediate(r));
167
- emitStdoutLine(child, { type: "agent_settled" });
168
- await new Promise((r) => setImmediate(r));
169
-
170
- // agent_settled → arm idle timer(DEFAULT_IDLE_TIMEOUT_MS = 5min)
171
- expect(hasIdleTimer(record.id)).toBe(true);
172
- // 进程仍存活(idle timer 未到期)
173
- expect(child.killed).toBe(false);
174
-
175
- // 未到 idle timeout(5min - 1ms):不 kill
176
- await vi.advanceTimersByTimeAsync(DEFAULT_IDLE_TIMEOUT_MS - 1);
177
- expect(child.killed).toBe(false);
178
-
179
- // idle timeout 到期:onTimeout → child.kill("SIGTERM")(复用现有 kill 路径)
180
- await vi.advanceTimersByTimeAsync(1);
181
- expect(child.killed).toBe(true);
182
- expect(child.killSignal).toBe("SIGTERM");
183
- // timer 触发后从 Map 移除(armIdleTimer 内 setTimeout 回调 idleTimers.delete)
184
- expect(hasIdleTimer(record.id)).toBe(false);
185
- } finally {
186
- vi.useRealTimers();
187
- }
188
-
189
- // 收尾:close 让 runSpawn resolve
190
- child.stdout.end();
191
- child.stderr.end();
192
- child.emit("close", 143);
193
- const result = await promise;
194
- expect(result.success).toBe(true);
195
- });
196
-
197
- it("③ chatMode agent_settled → 调 ctx.onRoundSettled(Step 3 挂载点,回调被调 1 次)", async () => {
198
- const record = makeChatModeRecord("sa-chat-cb");
199
- const onRoundSettled = vi.fn();
200
- const ctx: SessionRunnerContext = makeCtx({ onRoundSettled });
201
- const promise = runSpawn(record, "Task: chatmode-cb", makeOpts(), ctx);
202
-
203
- await waitForSpawn();
204
- const child = lastSpawnedChild();
205
-
206
- emitStdoutLine(child, sessionHeader());
207
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
208
- await new Promise((r) => setTimeout(r, 10));
209
- emitStdoutLine(child, { type: "agent_settled" });
210
- await new Promise((r) => setTimeout(r, 10));
211
-
212
- // agent_settled → onRoundSettled 被调,入参是当前 record
213
- expect(onRoundSettled).toHaveBeenCalledTimes(1);
214
- expect(onRoundSettled).toHaveBeenCalledWith(record);
215
-
216
- // 收尾:手动 close(idle timer 仍 armed,由 afterEach _resetLifecycleState 清理)
217
- child.stdout.end();
218
- child.stderr.end();
219
- child.emit("close", 143);
220
- const result = await promise;
221
- expect(result.success).toBe(true);
222
- });
223
-
224
- it("④ 非 chatMode agent_settled → 不 armIdleTimer、不调 onRoundSettled", async () => {
225
- // makeRecord 默认非 chatMode(createRecord 未传 chatMode)
226
- const record = makeRecord("sa-nonchat-settled");
227
- const onRoundSettled = vi.fn();
228
- const ctx: SessionRunnerContext = makeCtx({ onRoundSettled });
229
- const promise = runSpawn(record, "Task: nonchat-settled", makeOpts(), ctx);
230
-
231
- await waitForSpawn();
232
- const child = lastSpawnedChild();
233
-
234
- emitStdoutLine(child, sessionHeader());
235
- // 直接 emit agent_settled(非 chatMode:handler 应忽略,不 arm、不调回调)
236
- emitStdoutLine(child, { type: "agent_settled" });
237
- await new Promise((r) => setTimeout(r, 20));
238
-
239
- expect(hasIdleTimer(record.id)).toBe(false);
240
- expect(onRoundSettled).not.toHaveBeenCalled();
241
-
242
- // 收尾:emit agent_end 走正常 kill 分支(count=0 → SIGTERM)→ close resolve
243
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
244
- await new Promise((r) => setTimeout(r, 10));
245
- expect(child.killed).toBe(true); // 非 chatMode agent_end → kill(现有行为,V2 不动)
246
-
247
- child.stdout.end();
248
- child.stderr.end();
249
- child.emit("close", 143);
250
- const result = await promise;
251
- expect(result.success).toBe(true);
252
- });
253
- });