@zhushanwen/pi-subagent-workflow 8.5.0 → 8.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/package.json +13 -16
  2. package/relay/relay.mjs +1 -1
  3. package/src/host/__tests__/pi-host.test.ts +214 -0
  4. package/src/host/pi-host.ts +109 -0
  5. package/src/index.ts +142 -32
  6. package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
  7. package/src/injectors/__tests__/engine-section-stability.test.ts +341 -0
  8. package/src/injectors/__tests__/subagent-list-injector.test.ts +5 -5
  9. package/src/injectors/__tests__/workflow-list-injector.test.ts +5 -5
  10. package/src/injectors/engine-awareness.ts +123 -0
  11. package/src/injectors/model-list-injector.ts +1 -1
  12. package/src/injectors/subagent-list-injector.ts +8 -8
  13. package/src/injectors/workflow-list-injector.ts +8 -8
  14. package/src/interface/__tests__/detectors.test.ts +3 -3
  15. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +157 -0
  16. package/src/interface/__tests__/subagent-tool-prompt.test.ts +12 -0
  17. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +2 -2
  18. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  19. package/src/interface/bg-notify-render.ts +34 -13
  20. package/src/interface/commands.ts +3 -3
  21. package/src/interface/format.ts +2 -2
  22. package/src/interface/helpers.ts +3 -3
  23. package/src/interface/list-component.ts +4 -4
  24. package/src/interface/list-shared.ts +2 -2
  25. package/src/interface/list-view.ts +2 -2
  26. package/src/interface/subagent-actions.ts +288 -19
  27. package/src/interface/subagent-tool-schema.ts +163 -0
  28. package/src/interface/subagent-tool.ts +65 -129
  29. package/src/interface/subagents.ts +5 -5
  30. package/src/interface/tool-render.ts +34 -2
  31. package/src/interface/tool-workflow-script.ts +4 -4
  32. package/src/interface/tool-workflow.ts +6 -6
  33. package/src/interface/views/WorkflowsView.ts +5 -5
  34. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  35. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  36. package/src/interface/views/detail-content.ts +4 -4
  37. package/src/interface/views/format.ts +4 -4
  38. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +132 -18
  39. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  40. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  41. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  42. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  43. package/src/execution/__tests__/alive-store.test.ts +0 -147
  44. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  45. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  46. package/src/execution/__tests__/bg-notify-render.test.ts +0 -256
  47. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  48. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -597
  49. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  50. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  51. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  52. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  53. package/src/execution/__tests__/config.test.ts +0 -110
  54. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  55. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  56. package/src/execution/__tests__/delivery-methods.test.ts +0 -385
  57. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  58. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  59. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  60. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  61. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -189
  62. package/src/execution/__tests__/execution-record.test.ts +0 -1284
  63. package/src/execution/__tests__/finalize-record.test.ts +0 -368
  64. package/src/execution/__tests__/finalized-marker.test.ts +0 -82
  65. package/src/execution/__tests__/format-schema-instruction.test.ts +0 -138
  66. package/src/execution/__tests__/format.test.ts +0 -458
  67. package/src/execution/__tests__/gc-timer.test.ts +0 -184
  68. package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
  69. package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
  70. package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
  71. package/src/execution/__tests__/helpers/spawn-mock.ts +0 -238
  72. package/src/execution/__tests__/host-mode.test.ts +0 -87
  73. package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
  74. package/src/execution/__tests__/index-session-start.test.ts +0 -593
  75. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  76. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -337
  77. package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
  78. package/src/execution/__tests__/list-component.test.ts +0 -401
  79. package/src/execution/__tests__/list-fields.test.ts +0 -109
  80. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  81. package/src/execution/__tests__/model-resolver.test.ts +0 -413
  82. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
  83. package/src/execution/__tests__/nested-visibility.test.ts +0 -325
  84. package/src/execution/__tests__/notifier-flush.test.ts +0 -574
  85. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  86. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  87. package/src/execution/__tests__/output-collector.test.ts +0 -61
  88. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  89. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  90. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  91. package/src/execution/__tests__/record-store.test.ts +0 -1057
  92. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  93. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  94. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  95. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  96. package/src/execution/__tests__/relay-env.test.ts +0 -42
  97. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  98. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  99. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  100. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  101. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -644
  102. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  103. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  104. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  105. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  106. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  107. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  108. package/src/execution/__tests__/session-pending.test.ts +0 -197
  109. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  110. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  111. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -311
  112. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  113. package/src/execution/__tests__/spawn-args.test.ts +0 -434
  114. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  115. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  116. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  117. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  118. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  119. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  120. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  121. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  122. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  123. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  124. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  125. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  126. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  127. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -506
  128. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  129. package/src/execution/__tests__/timeout-integration.test.ts +0 -397
  130. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  131. package/src/execution/__tests__/tool-action.test.ts +0 -385
  132. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  133. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  134. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  135. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  136. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  137. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  138. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  139. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  140. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  141. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  142. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  143. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  144. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  145. package/src/execution/agent-registry.ts +0 -193
  146. package/src/execution/agent-result-mapper.ts +0 -90
  147. package/src/execution/alive-store.ts +0 -92
  148. package/src/execution/argv-mirror.ts +0 -109
  149. package/src/execution/best-effort.ts +0 -38
  150. package/src/execution/channel-registry-access.ts +0 -144
  151. package/src/execution/concurrency-pool.ts +0 -116
  152. package/src/execution/config.ts +0 -96
  153. package/src/execution/dialog-queue.ts +0 -330
  154. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  155. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  156. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  157. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  158. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  159. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  160. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  161. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  162. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  163. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  164. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  165. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  166. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  167. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  168. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  169. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  170. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  171. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  172. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  173. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  174. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  175. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  176. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  177. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  178. package/src/execution/engine/common/data-dir.ts +0 -62
  179. package/src/execution/engine/common/errors.ts +0 -183
  180. package/src/execution/engine/common/event-journal.ts +0 -254
  181. package/src/execution/engine/common/journal-replay.ts +0 -62
  182. package/src/execution/engine/common/kill-chain.ts +0 -221
  183. package/src/execution/engine/common/nesting-guard.ts +0 -50
  184. package/src/execution/engine/common/persona-router.ts +0 -108
  185. package/src/execution/engine/common/pool-manager.ts +0 -226
  186. package/src/execution/engine/common/schema-emulation.ts +0 -189
  187. package/src/execution/engine/common/session-view-projection.ts +0 -51
  188. package/src/execution/engine/engine-discovery.ts +0 -65
  189. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  190. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  191. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  192. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  193. package/src/execution/engine/engines/pi/reader.ts +0 -48
  194. package/src/execution/engine/engines/pi/registration.ts +0 -35
  195. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  196. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  197. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  198. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  199. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  200. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  201. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  202. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  203. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -567
  204. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  205. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  206. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  207. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  208. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  209. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  210. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  211. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -648
  212. package/src/execution/engine/host-task-spec.ts +0 -47
  213. package/src/execution/engine/model-prompt.ts +0 -59
  214. package/src/execution/engine/paths.ts +0 -42
  215. package/src/execution/engine/port.ts +0 -153
  216. package/src/execution/engine/registry.ts +0 -123
  217. package/src/execution/engine/routing.ts +0 -218
  218. package/src/execution/engine/types.ts +0 -304
  219. package/src/execution/execute-options-mapper.ts +0 -111
  220. package/src/execution/execution-record.ts +0 -906
  221. package/src/execution/finalize-record.ts +0 -251
  222. package/src/execution/finalized-marker.ts +0 -51
  223. package/src/execution/get-state-handshake.ts +0 -104
  224. package/src/execution/host-mode.ts +0 -56
  225. package/src/execution/idle-gc.ts +0 -47
  226. package/src/execution/lifecycle-manager.ts +0 -491
  227. package/src/execution/lifecycle-predicates.ts +0 -65
  228. package/src/execution/manifest-store.ts +0 -256
  229. package/src/execution/model-config-service.ts +0 -204
  230. package/src/execution/model-resolver.ts +0 -276
  231. package/src/execution/notifier.ts +0 -260
  232. package/src/execution/output-collector.ts +0 -88
  233. package/src/execution/path-encoding.ts +0 -60
  234. package/src/execution/pi-invocation.ts +0 -120
  235. package/src/execution/record-entry.ts +0 -132
  236. package/src/execution/record-store.ts +0 -1234
  237. package/src/execution/relay-env.ts +0 -37
  238. package/src/execution/session-context-resolver.ts +0 -64
  239. package/src/execution/session-file-gc.ts +0 -120
  240. package/src/execution/session-pending.ts +0 -164
  241. package/src/execution/session-reconstructor.ts +0 -678
  242. package/src/execution/session-runner.ts +0 -1548
  243. package/src/execution/sessions-index.ts +0 -304
  244. package/src/execution/spawn-event-adapter.ts +0 -363
  245. package/src/execution/stdin-writer.ts +0 -198
  246. package/src/execution/stream-sink.ts +0 -126
  247. package/src/execution/subagent-service.ts +0 -2119
  248. package/src/execution/subprocess-agent-runner.ts +0 -303
  249. package/src/execution/temp-prompt.ts +0 -62
  250. package/src/execution/tombstone-store.ts +0 -72
  251. package/src/execution/turn-limiter.ts +0 -102
  252. package/src/execution/types.ts +0 -910
  253. package/src/execution/ui-channels.ts +0 -216
  254. package/src/execution/ui-interaction-model.ts +0 -48
  255. package/src/execution/ui-request-handler-factory.ts +0 -212
  256. package/src/execution/ui-request-observability.ts +0 -81
  257. package/src/execution/ui-request-queue.ts +0 -174
  258. package/src/execution/worktree-manager.ts +0 -688
  259. package/src/execution/worktree-registry.ts +0 -222
  260. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -336
  261. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -208
  262. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -157
  263. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  264. package/src/orchestration/__tests__/concurrency-gate.test.ts +0 -125
  265. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  266. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -724
  267. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  268. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  269. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  270. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -314
  271. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  272. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  273. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -277
  274. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  275. package/src/orchestration/__tests__/lifecycle.test.ts +0 -625
  276. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -1971
  277. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  278. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -157
  279. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  280. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  281. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  282. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -520
  283. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  284. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -110
  285. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  286. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  287. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  288. package/src/orchestration/agent-opts-resolver.ts +0 -93
  289. package/src/orchestration/args-validator.ts +0 -127
  290. package/src/orchestration/concurrency-gate.ts +0 -69
  291. package/src/orchestration/config-loader.ts +0 -315
  292. package/src/orchestration/error-recovery.ts +0 -862
  293. package/src/orchestration/execute-agent-call.ts +0 -217
  294. package/src/orchestration/launcher.ts +0 -410
  295. package/src/orchestration/lifecycle.ts +0 -396
  296. package/src/orchestration/models/__tests__/budget.test.ts +0 -367
  297. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  298. package/src/orchestration/models/agent-call.ts +0 -83
  299. package/src/orchestration/models/budget.ts +0 -148
  300. package/src/orchestration/models/ports.ts +0 -164
  301. package/src/orchestration/models/run-runtime.ts +0 -89
  302. package/src/orchestration/models/run-spec.ts +0 -83
  303. package/src/orchestration/models/run-state.ts +0 -44
  304. package/src/orchestration/models/trace.ts +0 -183
  305. package/src/orchestration/models/types.ts +0 -292
  306. package/src/orchestration/models/workflow-run.ts +0 -254
  307. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  308. package/src/orchestration/models/workflow-script.ts +0 -117
  309. package/src/orchestration/script-lint.ts +0 -766
  310. package/src/orchestration/skill-discovery.ts +0 -92
  311. package/src/orchestration/worker-handle.ts +0 -115
  312. package/src/orchestration/worker-host.ts +0 -98
  313. package/src/orchestration/worker-script-builder.ts +0 -408
  314. package/src/orchestration/workflow-files.ts +0 -85
  315. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  316. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  317. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  318. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  319. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  320. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  321. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  322. package/src/shared/agent-event.ts +0 -13
  323. package/src/shared/agent-ref.ts +0 -57
  324. package/src/shared/meta-parser.ts +0 -261
  325. package/src/shared/resource-discovery.ts +0 -811
  326. package/src/shared/resource-meta.ts +0 -65
  327. package/src/shared/schema-jsonify.ts +0 -56
  328. package/src/shared/xml-injection.ts +0 -35
  329. package/workflows/README.md +0 -81
  330. package/workflows/_shared/agent-refs.cjs +0 -40
  331. package/workflows/chain.js +0 -131
  332. package/workflows/map-reduce.js +0 -174
  333. package/workflows/parallel.js +0 -148
  334. package/workflows/review-fix-loop-utils.cjs +0 -1307
  335. package/workflows/review-fix-loop.js +0 -1396
  336. package/workflows/scatter-gather.js +0 -178
@@ -1,211 +0,0 @@
1
- // acquireActivateLock 30s 超时兜底单测 —— v4-lifecycle-convergence.md §3.3 A-2。
2
- //
3
- // 验证:前序 holder 持锁不 release(崩溃/死锁模拟)时,waiter
4
- // - 等待 29999ms 仍 pending(未误伤正常排队)
5
- // - 到 30001ms 抛含恢复指引的超时错误('activation timed out' + 'retry action: message')
6
- //
7
- // 测试策略:纯 Promise 链 + setTimeout 超时,用 vi.useFakeTimers() 控时,
8
- // advanceTimersByTimeAsync 同时推进 fake timer 与 microtask flush。
9
-
10
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
11
-
12
- import {
13
- _getActivateLockTailCountForTest,
14
- _resetLifecycleState,
15
- acquireActivateLock,
16
- } from "../lifecycle-manager.ts";
17
-
18
- describe("acquireActivateLock 30s 超时兜底 (v4 A-2)", () => {
19
- beforeEach(() => {
20
- vi.useFakeTimers();
21
- _resetLifecycleState();
22
- });
23
-
24
- afterEach(() => {
25
- _resetLifecycleState();
26
- vi.useRealTimers();
27
- });
28
-
29
- it("waiter 等待 29999ms 仍 pending;到 30001ms 抛含恢复指引的超时错误", async () => {
30
- // 第一个 holder 持锁后不 release(模拟崩溃/死锁)
31
- await acquireActivateLock("sa-stuck");
32
-
33
- // 第二个 waiter 必然排队(前序未 release)
34
- let errMsg: string | null = null;
35
- let gotRelease: (() => void) | null = null;
36
- const waiter = acquireActivateLock("sa-stuck")
37
- .then((release) => {
38
- gotRelease = release;
39
- })
40
- .catch((err: unknown) => {
41
- errMsg = err instanceof Error ? err.message : String(err);
42
- });
43
-
44
- // flush microtask:waiter 进入 prev.then 等待链
45
- await vi.advanceTimersByTimeAsync(0);
46
- expect(gotRelease).toBe(null); // 尚未拿到锁
47
- expect(errMsg).toBe(null);
48
-
49
- // 29999ms:未满 30s,waiter 仍 pending
50
- await vi.advanceTimersByTimeAsync(29999);
51
- expect(gotRelease).toBe(null);
52
- expect(errMsg).toBe(null);
53
-
54
- // 再推进 2ms(累计 30001ms):超时 timer 触发 → reject
55
- await vi.advanceTimersByTimeAsync(2);
56
- await waiter;
57
-
58
- // 超时:未拿到锁,抛含恢复指引的错误
59
- expect(gotRelease).toBe(null);
60
- expect(errMsg).not.toBe(null);
61
- expect(errMsg).toContain("activation timed out");
62
- expect(errMsg).toContain("retry action: message");
63
- expect(errMsg).toContain("sa-stuck");
64
- });
65
-
66
- it("首次 acquire(无前序 holder)立即返回 release,不触发超时", async () => {
67
- // 首次 acquire:prev=Promise.resolve(),立即 resolve,timer 被 clearTimeout 取消
68
- const release = await acquireActivateLock("sa-fresh");
69
- expect(typeof release).toBe("function");
70
-
71
- // 推进远超 30s,不应有任何未捕获的超时 reject(timer 已清除)
72
- await vi.advanceTimersByTimeAsync(60000);
73
- release();
74
- });
75
-
76
- it("[review 修复] 超时后前序 release → 链可推进:二次 acquire 立即获锁(锁链不瘫痪)", async () => {
77
- // 瘫痪路径回归:waiter 超时 reject 后,若其 current 永久 pending,tail 永久
78
- // pending → 前序 release 后后续 acquire 也只能 30s 超时(只能重启恢复)。
79
- // 修复后超时回调 resolve 自身 current 放行链尾:release1 后 tail settle,
80
- // 二次 acquire 的 prev 已 settle → 立即拿到 releaseFn。
81
- const release1 = await acquireActivateLock("sa-recover");
82
-
83
- let waiterErr: string | null = null;
84
- const waiter = acquireActivateLock("sa-recover").catch((err: unknown) => {
85
- waiterErr = err instanceof Error ? err.message : String(err);
86
- });
87
- await vi.advanceTimersByTimeAsync(0); // waiter 挂链
88
- await vi.advanceTimersByTimeAsync(30001); // 超时 reject(+ 超时放行链尾)
89
- await waiter;
90
- expect(waiterErr).toContain("activation timed out");
91
-
92
- release1(); // 前序释放 → tail settle(current 已被超时放行 resolve)
93
- await vi.advanceTimersByTimeAsync(0); // flush microtask 链
94
-
95
- // 二次 acquire:prev 是已 settle 的 tail → 立即拿到锁,不等 30s
96
- const release2 = await acquireActivateLock("sa-recover");
97
- expect(typeof release2).toBe("function");
98
- release2();
99
- await vi.advanceTimersByTimeAsync(0);
100
- });
101
-
102
- it("[review 修复] 前序持续持锁时超时不放行后续 waiter 提前获锁(互斥保持)", async () => {
103
- // 超时放行只 resolve 自身 current(tail 仍等 prev);前序未 release 时,
104
- // 新 acquire 依然排队等待,不会与前序 holder 形成双写者。
105
- const release1 = await acquireActivateLock("sa-mutex");
106
-
107
- const waiter1 = acquireActivateLock("sa-mutex").catch(() => {});
108
- await vi.advanceTimersByTimeAsync(30001); // waiter1 超时放行自身 current
109
- await waiter1;
110
-
111
- // 前序仍持锁:新 acquire 的 prev(= waiter1 的 tail)等待 release1,不提前获锁
112
- let gotRelease2 = false;
113
- const waiter2 = acquireActivateLock("sa-mutex").then(() => {
114
- gotRelease2 = true;
115
- });
116
- await vi.advanceTimersByTimeAsync(0);
117
- expect(gotRelease2).toBe(false); // 未提前获锁
118
-
119
- release1();
120
- await vi.advanceTimersByTimeAsync(0);
121
- await waiter2; // release1 后链推进,waiter2 获锁
122
- expect(gotRelease2).toBe(true);
123
- });
124
-
125
- it("[review 修复] 超时者对称自清:前序 release 推进链尾后 Map 条目回收;前序持锁期间不提前删", async () => {
126
- // round2 INFO 残留:超时者 releaseFn 永不被调用,原实现条目滞留 Map 直到下次
127
- // 同 recordId acquire 覆盖。修复后挂 tail 尾部自清——tail settle(前序已
128
- // release)时回收;tail pending(前序仍持锁)时回调不执行,条目保留(后续
129
- // acquire 仍排队等待,互斥不被破坏)。
130
- const release1 = await acquireActivateLock("sa-timeout-gc");
131
-
132
- const waiter = acquireActivateLock("sa-timeout-gc").catch(() => {});
133
- await vi.advanceTimersByTimeAsync(0); // waiter 挂链,Map 链尾已覆盖为 waiter 的 tail
134
- expect(_getActivateLockTailCountForTest()).toBe(1);
135
-
136
- await vi.advanceTimersByTimeAsync(30001); // 超时:reject + settleCurrent + tail.then 自清排队
137
- await waiter;
138
- // 前序仍持锁 → tail 仍 pending → 自清回调未执行 → 条目仍在
139
- expect(_getActivateLockTailCountForTest()).toBe(1);
140
-
141
- release1(); // 前序释放 → tail settle → 自清回调执行(identity 匹配,无新 waiter)
142
- await vi.advanceTimersByTimeAsync(0);
143
- expect(_getActivateLockTailCountForTest()).toBe(0);
144
- });
145
- });
146
-
147
- describe("activateLockTails tail-identity 自清(release 后回收)", () => {
148
- beforeEach(() => {
149
- vi.useFakeTimers();
150
- _resetLifecycleState();
151
- });
152
-
153
- afterEach(() => {
154
- _resetLifecycleState();
155
- vi.useRealTimers();
156
- });
157
-
158
- it("W3TC14: 无 waiter 时 release 后 Map 空 + release 后可再次 acquire", async () => {
159
- const release = await acquireActivateLock("sa-gc");
160
- // 自清新增的 test-only 观察点:acquire 后 Map 有 1 条链尾
161
- expect(_getActivateLockTailCountForTest()).toBe(1);
162
-
163
- release();
164
- // 自清经 queueMicrotask 异步执行——advanceTimersByTimeAsync(0) flush microtask
165
- await vi.advanceTimersByTimeAsync(0);
166
- // 无 waiter:Map 中链尾即本链尾,identity 匹配 → delete 回收
167
- expect(_getActivateLockTailCountForTest()).toBe(0);
168
-
169
- // release 后可再次 acquire:prev 回落 Promise.resolve(),立即 resolve 返回 release
170
- const release2 = await acquireActivateLock("sa-gc");
171
- expect(typeof release2).toBe("function");
172
- release2();
173
- await vi.advanceTimersByTimeAsync(0);
174
- expect(_getActivateLockTailCountForTest()).toBe(0);
175
- });
176
-
177
- it("W3TC15: 有 waiter 排队不删、最后释放者回收;不同 recordId 链独立", async () => {
178
- const release1 = await acquireActivateLock("sa-q");
179
-
180
- // 发起 acquire#2 同 recordId(不 await,.then 捕获 release2)
181
- let release2: (() => void) | null = null;
182
- const waiter = acquireActivateLock("sa-q").then((r) => {
183
- release2 = r;
184
- });
185
- // #2 进入等待链——此刻 Map 链尾已被 #2 覆盖
186
- await vi.advanceTimersByTimeAsync(0);
187
-
188
- release1();
189
- await vi.advanceTimersByTimeAsync(0);
190
- // ES7 核心:waiter 的链尾仍在——identity 不匹配不删
191
- expect(_getActivateLockTailCountForTest()).toBe(1);
192
-
193
- // acquire#2 在 release1 后正常 resolve(等待链不被 delete 破坏——waiter 持
194
- // acquire 时刻捕获的 prev Promise 引用而非 Map 查询)
195
- await waiter;
196
- expect(typeof release2).toBe("function");
197
-
198
- // 另一 recordId 独立链:同时持有时各自独立计数
199
- const releaseA = await acquireActivateLock("sa-a");
200
- expect(_getActivateLockTailCountForTest()).toBe(2); // sa-q + sa-a
201
-
202
- release2!();
203
- await vi.advanceTimersByTimeAsync(0);
204
- // 最后释放者回收:release2 的 identity 匹配 → sa-q 条目回收,sa-a 仍在
205
- expect(_getActivateLockTailCountForTest()).toBe(1);
206
-
207
- releaseA();
208
- await vi.advanceTimersByTimeAsync(0);
209
- expect(_getActivateLockTailCountForTest()).toBe(0);
210
- });
211
- });
@@ -1,337 +0,0 @@
1
- // lifecycle-manager 单测 —— V2 §5.2 模块 1(进程生命周期管理)五项职责。
2
- //
3
- // 测试策略:
4
- // - idle timer / ceiling LRU 用 vi.useFakeTimers() + advanceTimersByTime(同时 mock
5
- // Date.now(),让 lastTouched 时间戳可控)。
6
- // - activate 互斥锁是纯 Promise 链(无 timer),用 advanceTimersByTimeAsync(0)
7
- // flush microtask 验证串行化。
8
- // - 每个用例 beforeEach 调 _resetLifecycleState() 隔离模块级单例状态。
9
-
10
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
11
-
12
- import {
13
- DEFAULT_IDLE_TIMEOUT_MS,
14
- DEFAULT_MAX_ALIVE_PROCESSES,
15
- _resetLifecycleState,
16
- acquireActivateLock,
17
- armIdleTimer,
18
- disarmIdleTimer,
19
- evictIfOverCeiling,
20
- getActiveProcessCount,
21
- hasIdleTimer,
22
- reapAllAliveProcesses,
23
- registerActiveProcess,
24
- scanOrphanProcesses,
25
- touchActiveProcess,
26
- unregisterActiveProcess,
27
- } from "../lifecycle-manager.ts";
28
-
29
- describe("lifecycle-manager — V2 §5.2 模块 1", () => {
30
- beforeEach(() => {
31
- vi.useFakeTimers();
32
- _resetLifecycleState();
33
- });
34
-
35
- afterEach(() => {
36
- _resetLifecycleState();
37
- vi.useRealTimers();
38
- });
39
-
40
- // ============================================================
41
- // 职责 1:idle timer
42
- // ============================================================
43
- describe("职责1 idle timer", () => {
44
- it("arm 后到 timeoutMs 触发 onTimeout(边界:差 1ms 不触发)", () => {
45
- const onTimeout = vi.fn();
46
- armIdleTimer("sa-1", onTimeout, 1000);
47
-
48
- expect(hasIdleTimer("sa-1")).toBe(true);
49
- vi.advanceTimersByTime(999);
50
- expect(onTimeout).not.toHaveBeenCalled();
51
-
52
- vi.advanceTimersByTime(1);
53
- expect(onTimeout).toHaveBeenCalledTimes(1);
54
- // 触发后自动从 Map 移除(不残留失效 entry)
55
- expect(hasIdleTimer("sa-1")).toBe(false);
56
- });
57
-
58
- it("disarm 后不再触发 onTimeout", () => {
59
- const onTimeout = vi.fn();
60
- armIdleTimer("sa-1", onTimeout, 1000);
61
- disarmIdleTimer("sa-1");
62
-
63
- expect(hasIdleTimer("sa-1")).toBe(false);
64
- vi.advanceTimersByTime(5000);
65
- expect(onTimeout).not.toHaveBeenCalled();
66
- });
67
-
68
- it("disarm 不存在的 record 为 no-op(不抛错)", () => {
69
- expect(() => disarmIdleTimer("never-armed")).not.toThrow();
70
- });
71
-
72
- it("重复 arm 刷新 timer:旧 timer 作废、重新计时", () => {
73
- const onTimeout = vi.fn();
74
- armIdleTimer("sa-1", onTimeout, 1000);
75
- vi.advanceTimersByTime(500); // 过了 500ms
76
-
77
- armIdleTimer("sa-1", onTimeout, 1000); // 刷新:重新计 1000ms
78
- vi.advanceTimersByTime(999);
79
- expect(onTimeout).not.toHaveBeenCalled(); // 旧 timer 已作废,新的还没到
80
-
81
- vi.advanceTimersByTime(1);
82
- expect(onTimeout).toHaveBeenCalledTimes(1);
83
- });
84
-
85
- it("默认超时 = DEFAULT_IDLE_TIMEOUT_MS", () => {
86
- const onTimeout = vi.fn();
87
- armIdleTimer("sa-1", onTimeout); // 不传 timeoutMs
88
-
89
- vi.advanceTimersByTime(DEFAULT_IDLE_TIMEOUT_MS - 1);
90
- expect(onTimeout).not.toHaveBeenCalled();
91
-
92
- vi.advanceTimersByTime(1);
93
- expect(onTimeout).toHaveBeenCalledTimes(1);
94
- });
95
- });
96
-
97
- // ============================================================
98
- // 职责 2:全局 ceiling(LRU 挤出)
99
- // ============================================================
100
- describe("职责2 全局 ceiling", () => {
101
- it("register 超过上限时 evictIfOverCeiling 挤出最久空闲", () => {
102
- registerActiveProcess("sa-1"); // 最早
103
- vi.advanceTimersByTime(10);
104
- registerActiveProcess("sa-2");
105
- vi.advanceTimersByTime(10);
106
- registerActiveProcess("sa-3"); // 超限(size=3 > ceiling=2)
107
- expect(getActiveProcessCount()).toBe(3);
108
-
109
- const evicted: string[] = [];
110
- evictIfOverCeiling((id) => evicted.push(id), 2);
111
-
112
- expect(evicted).toEqual(["sa-1"]); // lastTouched 最老的被挤出
113
- expect(getActiveProcessCount()).toBe(2);
114
- });
115
-
116
- it("不超过上限时 evictIfOverCeiling 不挤出", () => {
117
- registerActiveProcess("sa-1");
118
- registerActiveProcess("sa-2");
119
-
120
- const evicted: string[] = [];
121
- evictIfOverCeiling((id) => evicted.push(id), 5);
122
-
123
- expect(evicted).toEqual([]);
124
- expect(getActiveProcessCount()).toBe(2);
125
- });
126
-
127
- it("touch 更新 LRU:被 touch 的不再是挤出候选", () => {
128
- registerActiveProcess("sa-1");
129
- vi.advanceTimersByTime(10);
130
- registerActiveProcess("sa-2");
131
- vi.advanceTimersByTime(10);
132
- touchActiveProcess("sa-1"); // sa-1 变最新 → sa-2 变最老
133
-
134
- const evicted: string[] = [];
135
- evictIfOverCeiling((id) => evicted.push(id), 1);
136
-
137
- expect(evicted).toEqual(["sa-2"]); // sa-2 最久未 touch,被挤出
138
- });
139
-
140
- it("touch 不存在的 record 为 no-op(不隐式创建)", () => {
141
- expect(() => touchActiveProcess("never-registered")).not.toThrow();
142
- expect(getActiveProcessCount()).toBe(0);
143
- });
144
-
145
- it("unregister 清理活进程集合", () => {
146
- registerActiveProcess("sa-1");
147
- registerActiveProcess("sa-2");
148
- unregisterActiveProcess("sa-1");
149
- expect(getActiveProcessCount()).toBe(1);
150
- });
151
-
152
- it("挤出时连带 disarm 被挤 record 的 idle timer", () => {
153
- registerActiveProcess("sa-1");
154
- armIdleTimer("sa-1", vi.fn(), 1000);
155
- registerActiveProcess("sa-2");
156
- vi.advanceTimersByTime(10);
157
- registerActiveProcess("sa-3"); // sa-1 最老,将被挤出
158
-
159
- evictIfOverCeiling(() => {
160
- /* kill */
161
- }, 2);
162
-
163
- expect(hasIdleTimer("sa-1")).toBe(false); // 挤出 cascade disarm
164
- });
165
-
166
- it("unregister 连带 disarm idle timer(进程终态 timer 不残留)", () => {
167
- registerActiveProcess("sa-1");
168
- armIdleTimer("sa-1", vi.fn(), 1000);
169
- unregisterActiveProcess("sa-1");
170
- expect(hasIdleTimer("sa-1")).toBe(false);
171
- });
172
-
173
- it("默认上限 = DEFAULT_MAX_ALIVE_PROCESSES(不传 maxAlive)", () => {
174
- for (let i = 0; i < DEFAULT_MAX_ALIVE_PROCESSES; i++) {
175
- registerActiveProcess(`sa-${i}`);
176
- vi.advanceTimersByTime(1); // 保证 lastTouched 严格递增
177
- }
178
- registerActiveProcess("sa-over"); // 超限
179
- const evicted: string[] = [];
180
- evictIfOverCeiling((id) => evicted.push(id)); // 用默认上限
181
-
182
- expect(evicted).toEqual(["sa-0"]); // 默认上限下挤出最早
183
- expect(getActiveProcessCount()).toBe(DEFAULT_MAX_ALIVE_PROCESSES);
184
- });
185
-
186
- it("大幅超限时 while 循环挤出多个直到 ≤ ceiling", () => {
187
- for (let i = 0; i < 5; i++) {
188
- registerActiveProcess(`sa-${i}`);
189
- vi.advanceTimersByTime(1);
190
- }
191
- const evicted: string[] = [];
192
- evictIfOverCeiling((id) => evicted.push(id), 2);
193
-
194
- expect(evicted).toEqual(["sa-0", "sa-1", "sa-2"]); // 挤出 3 个(5-2),按 LRU
195
- });
196
- });
197
-
198
- // ============================================================
199
- // 职责 3:shutdown 收割
200
- // ============================================================
201
- describe("职责3 shutdown 收割", () => {
202
- it("reapAllAliveProcesses 遍历活进程调 killFn 并返回列表", () => {
203
- registerActiveProcess("sa-1");
204
- registerActiveProcess("sa-2");
205
-
206
- const killed: string[] = [];
207
- const reaped = reapAllAliveProcesses((id) => killed.push(id));
208
-
209
- expect(killed).toHaveLength(2);
210
- expect(killed).toEqual(expect.arrayContaining(["sa-1", "sa-2"]));
211
- expect(reaped).toEqual(expect.arrayContaining(["sa-1", "sa-2"]));
212
- expect(getActiveProcessCount()).toBe(0);
213
- });
214
-
215
- it("reap 后 idle timer 已 disarm(advance 不再触发)", () => {
216
- registerActiveProcess("sa-1");
217
- const onTimeout = vi.fn();
218
- armIdleTimer("sa-1", onTimeout, 1000);
219
-
220
- reapAllAliveProcesses(() => {
221
- /* kill */
222
- });
223
- vi.advanceTimersByTime(10000);
224
-
225
- expect(onTimeout).not.toHaveBeenCalled(); // timer 已被 reap 清理
226
- });
227
-
228
- it("无活进程时 reapAll 返回空列表", () => {
229
- const reaped = reapAllAliveProcesses(() => {
230
- /* kill */
231
- });
232
- expect(reaped).toEqual([]);
233
- });
234
- });
235
-
236
- // ============================================================
237
- // 职责 4:孤儿扫描
238
- // ============================================================
239
- describe("职责4 孤儿扫描", () => {
240
- it("pid 存活 + 不在活进程集合 = 孤儿", () => {
241
- registerActiveProcess("sa-active"); // 在集合内
242
- const records = [
243
- { id: "sa-active", pid: 100 },
244
- { id: "sa-orphan", pid: 200 }, // pid 活但不在集合 → 孤儿
245
- { id: "sa-dead", pid: 300 }, // pid 不活 → 非孤儿
246
- { id: "sa-nopid" }, // 无 pid → 非孤儿
247
- ];
248
-
249
- const orphans = scanOrphanProcesses(records, (pid) => pid === 100 || pid === 200);
250
-
251
- expect(orphans).toEqual(["sa-orphan"]);
252
- });
253
-
254
- it("pid 不存活 = 非孤儿", () => {
255
- const records = [{ id: "sa-1", pid: 999 }];
256
- const orphans = scanOrphanProcesses(records, () => false); // 全不活
257
- expect(orphans).toEqual([]);
258
- });
259
-
260
- it("在活进程集合内 = 非孤儿(即使 pid 活)", () => {
261
- registerActiveProcess("sa-1");
262
- const records = [{ id: "sa-1", pid: 100 }];
263
- const orphans = scanOrphanProcesses(records, () => true);
264
- expect(orphans).toEqual([]);
265
- });
266
-
267
- it("无 pid 的 record 不视为孤儿", () => {
268
- const records = [
269
- { id: "sa-1" },
270
- { id: "sa-2", sessionFile: "/x.jsonl" },
271
- ];
272
- const orphans = scanOrphanProcesses(records, () => true);
273
- expect(orphans).toEqual([]);
274
- });
275
-
276
- it("扫描是只读(不改活进程集合)", () => {
277
- registerActiveProcess("sa-1");
278
- scanOrphanProcesses([{ id: "sa-2", pid: 200 }], () => true);
279
- expect(getActiveProcessCount()).toBe(1); // 集合不变
280
- });
281
- });
282
-
283
- // ============================================================
284
- // 职责 5:activate 互斥锁
285
- // ============================================================
286
- describe("职责5 activate 互斥锁", () => {
287
- it("首次 acquire 立即 resolve 返回 release 函数", async () => {
288
- const release = await acquireActivateLock("sa-1");
289
- expect(typeof release).toBe("function");
290
- release();
291
- });
292
-
293
- it("并发 acquire 同一 recordId 串行化:第二次等首次 release", async () => {
294
- const release1 = await acquireActivateLock("sa-1");
295
-
296
- let secondResolved = false;
297
- const secondPromise = acquireActivateLock("sa-1").then((r) => {
298
- secondResolved = true;
299
- return r;
300
- });
301
-
302
- await vi.advanceTimersByTimeAsync(0); // flush microtask
303
- expect(secondResolved).toBe(false); // 还在等首次 release
304
-
305
- release1();
306
- await vi.advanceTimersByTimeAsync(0); // flush microtask
307
- expect(secondResolved).toBe(true);
308
-
309
- const release2 = await secondPromise;
310
- release2();
311
- });
312
-
313
- it("不同 recordId 不互斥(各自独立链)", async () => {
314
- const release1 = await acquireActivateLock("sa-1");
315
-
316
- let secondResolved = false;
317
- acquireActivateLock("sa-2").then((r) => {
318
- secondResolved = true;
319
- r();
320
- });
321
-
322
- await vi.advanceTimersByTimeAsync(0); // flush microtask
323
- expect(secondResolved).toBe(true); // sa-2 不被 sa-1 阻塞
324
-
325
- release1();
326
- });
327
-
328
- it("release 后同 recordId 可再次 acquire", async () => {
329
- const r1 = await acquireActivateLock("sa-1");
330
- r1();
331
-
332
- const r2 = await acquireActivateLock("sa-1");
333
- expect(typeof r2).toBe("function");
334
- r2();
335
- });
336
- });
337
- });
@@ -1,116 +0,0 @@
1
- // lifecycle-predicates 单测(v4 B-1)。
2
- // 验证 isIdle/isResumable/hasLiveProcessHandle 在两态收敛后的判定逻辑。
3
- // 依赖 lifecycle-manager 模块级 idleTimers 与 session-runner.spawnedChildren(单例 Map),
4
- // beforeEach 重置隔离。
5
-
6
- import { describe, it, expect, beforeEach } from "vitest";
7
-
8
- import {
9
- armIdleTimer,
10
- disarmIdleTimer,
11
- _resetLifecycleState,
12
- } from "../lifecycle-manager.ts";
13
- import { spawnedChildren } from "../session-runner.ts";
14
- import type { ChildProcess } from "node:child_process";
15
- import type { ExecutionRecord } from "../types.ts";
16
-
17
- import { hasLiveProcessHandle, isIdle, isResumable } from "../lifecycle-predicates.ts";
18
-
19
- /** 构造最小 ExecutionRecord(status 默认 running)。 */
20
- function makeRecord(overrides: Partial<ExecutionRecord> = {}): ExecutionRecord {
21
- return {
22
- id: "sa-test",
23
- agent: "general-purpose",
24
- model: "test/model",
25
- thinkingLevel: undefined,
26
- mode: "background",
27
- task: "test",
28
- slug: "test",
29
- startedAt: Date.now(),
30
- rootSessionId: "root",
31
- parentRecordId: undefined,
32
- depth: 0,
33
- status: "running",
34
- turns: [],
35
- turnCount: 0,
36
- totalTokens: 0,
37
- lastError: undefined,
38
- round: 0,
39
- endedAt: undefined,
40
- result: undefined,
41
- error: undefined,
42
- agentResult: undefined,
43
- controller: undefined,
44
- ...overrides,
45
- } as ExecutionRecord;
46
- }
47
-
48
- /** 构造最小 ChildProcess fake(hasLiveProcessHandle 只读 .killed)。 */
49
- function fakeChild(killed: boolean): ChildProcess {
50
- // 测试 fake:被测代码仅读 .killed,其余字段不可达,用 unknown 中转满足 Map 类型。
51
- return { killed } as unknown as ChildProcess;
52
- }
53
-
54
- describe("lifecycle-predicates (v4 B-1)", () => {
55
- beforeEach(() => {
56
- _resetLifecycleState();
57
- spawnedChildren.clear();
58
- });
59
-
60
- describe("isIdle (= hasIdleTimer)", () => {
61
- it("armed idle timer → true", () => {
62
- const rec = makeRecord();
63
- armIdleTimer(rec.id, () => {});
64
- expect(isIdle(rec)).toBe(true);
65
- });
66
-
67
- it("no idle timer → false", () => {
68
- expect(isIdle(makeRecord())).toBe(false);
69
- });
70
-
71
- it("disarmed timer → false", () => {
72
- const rec = makeRecord();
73
- armIdleTimer(rec.id, () => {});
74
- disarmIdleTimer(rec.id);
75
- expect(isIdle(rec)).toBe(false);
76
- });
77
- });
78
-
79
- describe("hasLiveProcessHandle", () => {
80
- it("no child in map → false", () => {
81
- expect(hasLiveProcessHandle("sa-test")).toBe(false);
82
- });
83
-
84
- it("child present and not killed → true", () => {
85
- spawnedChildren.set("sa-test", fakeChild(false));
86
- expect(hasLiveProcessHandle("sa-test")).toBe(true);
87
- });
88
-
89
- it("child present but killed → false", () => {
90
- spawnedChildren.set("sa-test", fakeChild(true));
91
- expect(hasLiveProcessHandle("sa-test")).toBe(false);
92
- });
93
- });
94
-
95
- describe("isResumable (= running && !hasLiveProcessHandle)", () => {
96
- it("running + no live process → true (Path B / 跨重启)", () => {
97
- expect(isResumable(makeRecord({ status: "running" }))).toBe(true);
98
- });
99
-
100
- it("running + live process → false (Path A 保活 / 正在执行)", () => {
101
- const rec = makeRecord({ status: "running" });
102
- spawnedChildren.set(rec.id, fakeChild(false));
103
- expect(isResumable(rec)).toBe(false);
104
- });
105
-
106
- it("closed + no live process → false (终态不可 resume)", () => {
107
- expect(isResumable(makeRecord({ status: "closed" }))).toBe(false);
108
- });
109
-
110
- it("closed + live process → false (终态优先)", () => {
111
- const rec = makeRecord({ status: "closed" });
112
- spawnedChildren.set(rec.id, fakeChild(false));
113
- expect(isResumable(rec)).toBe(false);
114
- });
115
- });
116
- });