@zhushanwen/subagent-core 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-KXVBIVOU.js +16 -0
  3. package/dist/chunk-T2SYBW3I.js +24 -0
  4. package/dist/chunk-VURUAGMM.js +2305 -0
  5. package/dist/{types-C3fE3R9x.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +770 -668
  6. package/dist/{types-C3fE3R9x.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +770 -668
  7. package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
  8. package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
  9. package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
  10. package/dist/execution/engine/engine-discovery-scan.js +20 -0
  11. package/dist/execution/engine/paths.cjs +6 -23
  12. package/dist/execution/engine/paths.d.cts +1 -8
  13. package/dist/execution/engine/paths.d.ts +1 -8
  14. package/dist/execution/engine/paths.js +1 -1
  15. package/dist/execution/relay-env.cjs +12 -28
  16. package/dist/execution/relay-env.d.cts +1 -33
  17. package/dist/execution/relay-env.d.ts +1 -33
  18. package/dist/execution/relay-env.js +5 -3
  19. package/dist/index.cjs +14045 -16059
  20. package/dist/index.d.cts +1035 -1579
  21. package/dist/index.d.ts +1035 -1579
  22. package/dist/index.js +9838 -13800
  23. package/dist.bundle/index.cjs +28875 -30323
  24. package/package.json +20 -26
  25. package/src/__tests__/record-store-last-line.test.ts +16 -7
  26. package/src/core/error-message.ts +7 -6
  27. package/src/core/host-services.ts +8 -2
  28. package/src/core/notify-ports.ts +17 -2
  29. package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
  30. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
  31. package/src/execution/__tests__/collect-coordinator-service.test.ts +36 -47
  32. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +20 -53
  33. package/src/execution/__tests__/delivery-methods.test.ts +179 -237
  34. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
  35. package/src/execution/__tests__/execute-nesting.test.ts +20 -13
  36. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +20 -33
  37. package/src/execution/__tests__/gc-timer.test.ts +7 -22
  38. package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
  39. package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
  40. package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
  41. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
  42. package/src/execution/__tests__/idle-gc.test.ts +200 -0
  43. package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
  44. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
  45. package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
  46. package/src/execution/__tests__/record-store.test.ts +60 -6
  47. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
  48. package/src/execution/__tests__/round-supervisor.test.ts +293 -0
  49. package/src/execution/__tests__/session-pending.test.ts +119 -17
  50. package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
  51. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +1 -11
  52. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
  53. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
  54. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
  55. package/src/execution/__tests__/subagent-service.test.ts +2 -2
  56. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
  57. package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
  58. package/src/execution/__tests__/sync-collect-recovery.test.ts +21 -36
  59. package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
  60. package/src/execution/agent-registry.ts +6 -2
  61. package/src/execution/dialog-queue.ts +6 -73
  62. package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
  63. package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
  64. package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
  65. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
  66. package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
  67. package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
  68. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
  69. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
  70. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
  71. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
  72. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
  73. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
  74. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
  75. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +81 -54
  76. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
  77. package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
  78. package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
  79. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +7 -2
  80. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
  81. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
  82. package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
  83. package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
  84. package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
  85. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
  86. package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
  87. package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
  88. package/src/execution/engine/__tests__/registry.test.ts +206 -1
  89. package/src/execution/engine/__tests__/routing.test.ts +97 -0
  90. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
  91. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
  92. package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
  93. package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
  94. package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
  95. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
  96. package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
  97. package/src/execution/engine/client/client-options.ts +103 -0
  98. package/src/execution/engine/client/engine-client.ts +687 -0
  99. package/src/execution/engine/client/mirror.ts +167 -0
  100. package/src/execution/engine/client/pid-file.ts +392 -0
  101. package/src/execution/engine/client/reaper.ts +95 -0
  102. package/src/execution/engine/client/remote-engine.ts +441 -0
  103. package/src/execution/engine/client/reverse-router.ts +255 -0
  104. package/src/execution/engine/common/capability-gate.ts +109 -22
  105. package/src/execution/engine/common/errors.ts +9 -25
  106. package/src/execution/engine/common/event-journal.ts +4 -50
  107. package/src/execution/engine/common/journal-replay.ts +3 -1
  108. package/src/execution/engine/common/kill-chain.ts +18 -251
  109. package/src/execution/engine/common/nesting-guard.ts +18 -114
  110. package/src/execution/engine/common/pool-manager.ts +4 -0
  111. package/src/execution/engine/common/session-view-service.ts +56 -84
  112. package/src/execution/engine/config.ts +151 -0
  113. package/src/execution/engine/d8-compat.ts +346 -0
  114. package/src/execution/engine/engine-discovery-roots.ts +107 -0
  115. package/src/execution/engine/engine-discovery-scan.ts +269 -0
  116. package/src/execution/engine/engine-discovery.ts +30 -7
  117. package/src/execution/engine/engine-inspect-package.ts +282 -0
  118. package/src/execution/engine/engine-manifest.ts +244 -0
  119. package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
  120. package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
  121. package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
  122. package/src/execution/engine/host/host-bridge.ts +150 -0
  123. package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
  124. package/src/execution/engine/host/pi-host-binding.ts +91 -0
  125. package/src/execution/engine/host/spawned-children.ts +139 -0
  126. package/src/execution/engine/host-task-spec.ts +29 -2
  127. package/src/execution/engine/model-validation.ts +55 -2
  128. package/src/execution/engine/paths.ts +16 -41
  129. package/src/execution/engine/port.ts +48 -2
  130. package/src/execution/engine/registry.ts +153 -34
  131. package/src/execution/engine/routing.ts +225 -52
  132. package/src/execution/engine/types.ts +25 -200
  133. package/src/execution/finalize-record.ts +25 -0
  134. package/src/execution/idle-gc.ts +89 -14
  135. package/src/execution/lifecycle-manager.ts +10 -7
  136. package/src/execution/lifecycle-predicates.ts +10 -8
  137. package/src/execution/record-store.ts +29 -2
  138. package/src/execution/relay-env.ts +19 -36
  139. package/src/execution/round-supervisor/domain.ts +89 -0
  140. package/src/execution/round-supervisor/index.ts +33 -0
  141. package/src/execution/round-supervisor/notify-accounting.ts +87 -0
  142. package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
  143. package/src/execution/round-supervisor/service-binding.test.ts +661 -0
  144. package/src/execution/round-supervisor/service-binding.ts +273 -0
  145. package/src/execution/round-supervisor/supervisor.ts +426 -0
  146. package/src/execution/session-pending.ts +68 -74
  147. package/src/execution/settled-watchdog.ts +39 -0
  148. package/src/execution/subagent-service.ts +746 -400
  149. package/src/execution/subprocess-agent-runner.ts +16 -8
  150. package/src/execution/types.ts +41 -117
  151. package/src/execution/ui-channels.ts +13 -214
  152. package/src/execution/ui-request-handler-factory.ts +7 -4
  153. package/src/execution/ui-request-observability.ts +2 -2
  154. package/src/execution/workflow-state-root.ts +67 -0
  155. package/src/execution/worktree-git-ops.ts +5 -0
  156. package/src/execution/worktree-manager.ts +11 -1
  157. package/src/index.ts +55 -26
  158. package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
  159. package/src/orchestration/execute-agent-call.ts +1 -1
  160. package/src/orchestration/file-run-store.ts +144 -59
  161. package/src/orchestration/models/types.ts +43 -42
  162. package/src/shared/zcode-model-ref.ts +31 -0
  163. package/dist/chunk-43ONBFZX.js +0 -240
  164. package/dist/chunk-A4IVZWVX.js +0 -31
  165. package/dist/chunk-APZY4IME.js +0 -27
  166. package/dist/chunk-V3VHZ2VX.js +0 -59
  167. package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
  168. package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
  169. package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
  170. package/dist/execution/engine/engines/zcode/constants.js +0 -54
  171. package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
  172. package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
  173. package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
  174. package/dist/execution/engine/engines/zcode/reader.js +0 -9
  175. package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
  176. package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
  177. package/src/__tests__/session-runner.test.ts +0 -69
  178. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  179. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
  180. package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
  181. package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
  182. package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
  183. package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
  184. package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
  185. package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
  186. package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
  187. package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
  188. package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
  189. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
  190. package/src/execution/__tests__/output-collector.test.ts +0 -469
  191. package/src/execution/__tests__/pi-invocation.test.ts +0 -166
  192. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
  193. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  194. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
  195. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
  196. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
  197. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
  198. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  199. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  200. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  201. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
  202. package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
  203. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
  204. package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
  205. package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
  206. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
  207. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
  208. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
  209. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
  210. package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
  211. package/src/execution/__tests__/spawn-args.test.ts +0 -446
  212. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
  213. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  214. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
  215. package/src/execution/__tests__/spawned-children.test.ts +0 -236
  216. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  217. package/src/execution/__tests__/stdin-writer.test.ts +0 -464
  218. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
  219. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  220. package/src/execution/__tests__/timeout-integration.test.ts +0 -616
  221. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  222. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  223. package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
  224. package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
  225. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
  226. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  227. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
  228. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  229. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
  230. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  231. package/src/execution/engine/common/schema-emulation.ts +0 -189
  232. package/src/execution/engine/common/session-view-projection.ts +0 -51
  233. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
  234. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  235. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
  236. package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
  237. package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
  238. package/src/execution/engine/engines/pi/output-collector.ts +0 -317
  239. package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
  240. package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
  241. package/src/execution/engine/engines/pi/reader.ts +0 -59
  242. package/src/execution/engine/engines/pi/registration.ts +0 -37
  243. package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
  244. package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
  245. package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
  246. package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
  247. package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
  248. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
  249. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
  250. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
  251. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
  252. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
  253. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
  254. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  255. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
  256. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
  257. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
  258. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
  259. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
  260. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
  261. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
  262. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
  263. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
  264. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
  265. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
  266. package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
  267. package/src/execution/engine/engines/zcode/connection.ts +0 -598
  268. package/src/execution/engine/engines/zcode/constants.ts +0 -176
  269. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
  270. package/src/execution/engine/engines/zcode/parser.ts +0 -102
  271. package/src/execution/engine/engines/zcode/preparer.ts +0 -235
  272. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  273. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  274. package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
  275. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
  276. package/src/execution/round-settlement.ts +0 -93
  277. package/src/execution/ui-request-queue.ts +0 -215
  278. package/src/shared/schema-env.ts +0 -44
@@ -0,0 +1,235 @@
1
+ // src/execution/round-supervisor/reconcile-sweep.ts
2
+ //
3
+ // [W4] 注册对账 sweep——死亡窗口投递缺口的补发通道(发射点枚举第 5 处)。
4
+ //
5
+ // 设计权威源:docs/design/chat-domain-v1x-liveness-governance.md §3.2 D2「注册对账
6
+ // sweep」(R2 增补、R3 钉死判据与写法)。
7
+ //
8
+ // 问题:注销经进程内 pi.events appendEntry 落盘,进程死亡时发射源消失
9
+ // (notify-host getPi() 为 null),注销 entry 可能永久缺位 → goal 守卫幻 defer、
10
+ // pending_notifications 工具虚报活跃。
11
+ //
12
+ // 补发机制:对「本 session 的 register entry × 对应 record 状态 ∈ 终态集 ∪ record
13
+ // 已归档/不存在」的差集补发 unregister。**已归档**(archive 从内存移除、磁盘有
14
+ // finalized sidecar → 读侧重建 closed)与**不存在**(畸形条目对不上任何 record)
15
+ // 同视同终态——「查不到即补注销」判据兜底链才闭合。
16
+ //
17
+ // 写法钉死(照 base-tool-enhance/src/background/pending-reconcile.ts 先例):
18
+ // **直接 appendEntry 权威落盘 + 尽力 emit 同步内存视图**——不经 bus emit 作权威:
19
+ // pending-notifications 的 unregister listener 落盘条件是其内存 registry 该 id
20
+ // active,而两个 extension 的加载/派发顺序无保障,顺序反转时 emit 被静默吞。
21
+ // 差集消费方(goal 守卫)从持久化 entries 算差集,appendEntry 对守卫直接生效;
22
+ // emit 之外尽力同步 listener 内存视图(失败无害)。
23
+ //
24
+ // 触发时机:session reattach / session_start / 监督器启动(由 subagent-service 在
25
+ // initSession 链内调用)。与 session_start 的 registry rebuild 先后时序不作保证,
26
+ // 残余窗口由下次 session_start 收口(设计明示容忍)。
27
+ //
28
+ // 判据保守性([F2] 按类型分流收口):
29
+ // - type=subagent → record 差集对账(lookupRecordState);
30
+ // - type=workflow 及缺失/未知的畸形条目(normalizePendingType 归 workflow 的偏好)
31
+ // → workflow run 判据(lookupWorkflowRunState,生产装配查 WorkflowRun store 的
32
+ // run state 文件):终态 ∪ 文件不存在 → 补注销;running → 跳过;全部行损坏
33
+ // (读不出 ≠ 不存在)由判据侧保守按 running 处理(宁挂账不失明——误注销活跃
34
+ // workflow run 是事故方向)。deps 未注入该判据时维持旧保守跳过(向后兼容)。
35
+ // - type=bash → 无 record/store 可查(bash 注册随进程退出注销,进程死亡窗口的
36
+ // 丢失无补发通道)→ 保守跳过,显式偏差登记(impl-plan §5 #5):挂账方向代价 =
37
+ // 每孤儿 bash 注册 1 条静态虚报,无空转驱动源(goal 守卫读侧过滤已使子 session
38
+ // 不受污染,本 session 虚报 defer 由熔断限损)。
39
+
40
+ import * as fs from "node:fs";
41
+
42
+ import { getLogger } from "../../core/logger.ts";
43
+
44
+ const logger = getLogger("subagents");
45
+
46
+ /** sweep 的 record 状态判据(subagent-service 供 store 读侧:内存 getMutable ∪
47
+ * 磁盘 findLightById 两级)。 */
48
+ export type SupervisedRecordState =
49
+ /** 活跃(running-resumable,监督域或等待 upgrade)——不动。 */
50
+ | "active"
51
+ /** 终态(closed,含 closedReason——映射 pending reason 用)。 */
52
+ | { terminal: true; closedReason: string | undefined }
53
+ /** 已归档/不存在(视同终态,补注销)。 */
54
+ | "missing";
55
+
56
+ /** sweep 依赖注入(全部单测可替身)。 */
57
+ export interface ReconcileSweepDeps {
58
+ /** 主 session 文件(差集输入源)。undefined = 无法读取,本轮空跑。 */
59
+ sessionFile: string | undefined;
60
+ /** record 状态判据(见 SupervisedRecordState)。 */
61
+ lookupRecordState: (id: string) => SupervisedRecordState;
62
+ /**
63
+ * [F2] workflow run 状态判据(type=workflow 及畸形条目的收口依据)。生产装配查
64
+ * WorkflowRun store(service-binding → FileRunStore.findStateByIdSync)。
65
+ * 缺省(未注入)= workflow/畸形条目无收口通道,保守跳过(skippedNonSubagent)。
66
+ */
67
+ lookupWorkflowRunState?: (runId: string) => SupervisedRecordState;
68
+ /** 权威写(pi.appendEntry)。缺失(dispose 后)= 本轮只判不写。 */
69
+ appendEntry?: (customType: string, data: unknown) => void;
70
+ /** 尽力 emit(pi.events.emit;listener 缺失/抛错无害)。 */
71
+ emit?: (channel: string, data: unknown) => void;
72
+ }
73
+
74
+ /** sweep 结果(日志 + 测试断言面)。 */
75
+ export interface ReconcileSweepResult {
76
+ /** 补发 unregister 的注册 id。 */
77
+ reconciled: string[];
78
+ /** 差集内但判据为活跃(record/run running)而保守跳过的注册 id。 */
79
+ skippedActive: string[];
80
+ /** 差集内无收口通道而保守跳过的注册 id(bash;或 deps 未注入 workflow 判据时
81
+ * 的 workflow/未知类型——显式偏差面,见文件头注 bash 段)。 */
82
+ skippedNonSubagent: string[];
83
+ }
84
+
85
+ /**
86
+ * 执行一次对账 sweep。同步(fs 读 + appendEntry 均同步,session_start 链内毫秒级)。
87
+ * 幂等:重复执行时已补发的 id 有 unregister entry 抵消,差集不再出现。
88
+ */
89
+ export function runReconcileSweep(deps: ReconcileSweepDeps): ReconcileSweepResult {
90
+ const result: ReconcileSweepResult = {
91
+ reconciled: [],
92
+ skippedActive: [],
93
+ skippedNonSubagent: [],
94
+ };
95
+ if (!deps.sessionFile) return result;
96
+
97
+ const activeRegisters = collectActiveRegisterEntries(deps.sessionFile);
98
+ for (const entry of activeRegisters) {
99
+ sweepSingleRegister(deps, entry, result);
100
+ }
101
+ if (result.reconciled.length > 0) {
102
+ logger.warn(
103
+ `[subagents] reconcile sweep re-emitted ${result.reconciled.length} unregister(s) for terminal/missing records: ${result.reconciled.join(",")}`,
104
+ );
105
+ }
106
+ return result;
107
+ }
108
+
109
+ /**
110
+ * 差集单条对账(保守性分流 [F2]):按注册类型选收口判据——subagent 走 record 差集;
111
+ * workflow/畸形(normalizePendingType 归 workflow 偏好)走 workflow run 判据;bash 无
112
+ * record/store 可查,保守跳过(显式偏差,头注 bash 段)。
113
+ */
114
+ function sweepSingleRegister(
115
+ deps: ReconcileSweepDeps,
116
+ entry: ActiveRegisterEntry,
117
+ result: ReconcileSweepResult,
118
+ ): void {
119
+ const id = entry.id;
120
+ if (entry.type === "bash") {
121
+ result.skippedNonSubagent.push(id);
122
+ return;
123
+ }
124
+ const state = entry.type === "subagent"
125
+ ? deps.lookupRecordState(id)
126
+ : deps.lookupWorkflowRunState?.(id);
127
+ if (state === undefined) {
128
+ // deps 未注入 workflow 判据:无收口通道,保守跳过(向后兼容——判据注入面
129
+ // 缺席 ≠ 条目可注销)。
130
+ result.skippedNonSubagent.push(id);
131
+ return;
132
+ }
133
+ if (state === "active") {
134
+ result.skippedActive.push(id);
135
+ return;
136
+ }
137
+ reemitUnregister(deps, id, state, result);
138
+ }
139
+
140
+ /** 补发单条 unregister:appendEntry 权威落盘 + 尽力 emit 同步内存视图(均失败保守处理)。 */
141
+ function reemitUnregister(
142
+ deps: ReconcileSweepDeps,
143
+ id: string,
144
+ state: Exclude<SupervisedRecordState, "active">,
145
+ result: ReconcileSweepResult,
146
+ ): void {
147
+ const reason =
148
+ state === "missing" ? "expired" : closedReasonToPendingReason(state.closedReason);
149
+ // 权威路径:直接 appendEntry 落盘(不经 bus emit 作权威——先例论证见文件头注)。
150
+ try {
151
+ deps.appendEntry?.("pending:unregister", { id, reason, status: reason });
152
+ } catch (err) {
153
+ // 落盘失败:差集残留交下次 sweep(session_start / 监督器启动)重试。
154
+ logger.warn(
155
+ `[subagents] reconcile sweep appendEntry failed for ${id} (retry on next sweep): ${
156
+ err instanceof Error ? err.message : String(err)
157
+ }`,
158
+ );
159
+ return;
160
+ }
161
+ // 尽力补 emit(listener 就绪时同步 pending 内存视图,缩短工具投影不一致窗口)。
162
+ try {
163
+ deps.emit?.("pending:unregister", { id, reason });
164
+ } catch (err) {
165
+ // 尽力语义:emit 失败无害(appendEntry 已是权威路径),debug 留痕供排查。
166
+ logger.debug(
167
+ `[subagents] reconcile sweep best-effort emit failed (harmless) for ${id}: ${
168
+ err instanceof Error ? err.message : String(err)
169
+ }`,
170
+ );
171
+ }
172
+ result.reconciled.push(id);
173
+ }
174
+
175
+ /** closedReason → pending reason(未知值交 pending-notifications mapReasonToStatus
176
+ * 的 default=completed 兜底——诚实且对差集消费方无行为影响,reason 不参与计数)。 */
177
+ function closedReasonToPendingReason(closedReason: string | undefined): string {
178
+ return closedReason ?? "completed";
179
+ }
180
+
181
+ // ── 差集读取(独立轻量实现,不复用 session-pending 的 per-file 增量游标——sweep
182
+ // 是低频全量操作,与后代判定的游标记账解耦,避免交错消费 offset)──
183
+
184
+ interface ActiveRegisterEntry {
185
+ id: string;
186
+ type: string | undefined;
187
+ }
188
+
189
+ /** entry.data 的最小形状(对齐 pending-notifications RegisterEntryData)。 */
190
+ interface RegisterDataLike {
191
+ id?: unknown;
192
+ type?: unknown;
193
+ }
194
+
195
+ function isRegisterDataLike(v: unknown): v is RegisterDataLike {
196
+ return typeof v === "object" && v !== null;
197
+ }
198
+
199
+ /**
200
+ * 读主 session 文件的 pending:register − pending:unregister 差集(register 顺序
201
+ * 保留;同 id 重 register 去重)。文件不可读(首条 assistant 前未 flush / 被删)
202
+ * 返回空集——sweep 空跑,下次触发点重试。坏行跳过(append 中途崩溃的截断行)。
203
+ */
204
+ function collectActiveRegisterEntries(sessionFile: string): ActiveRegisterEntry[] {
205
+ let content: string;
206
+ try {
207
+ content = fs.readFileSync(sessionFile, "utf-8");
208
+ } catch {
209
+ return [];
210
+ }
211
+ const unregistered = new Set<string>();
212
+ const registers = new Map<string, string | undefined>();
213
+ for (const line of content.split("\n")) {
214
+ // 快速路径(对齐 session-pending S-4 按值匹配):只解析含 pending 值的行。
215
+ if (!line.includes('"pending:register"') && !line.includes('"pending:unregister"')) continue;
216
+ let parsed: unknown;
217
+ try {
218
+ parsed = JSON.parse(line);
219
+ } catch {
220
+ continue; // 坏行跳过
221
+ }
222
+ if (typeof parsed !== "object" || parsed === null) continue;
223
+ const entry = parsed as { customType?: unknown; data?: unknown };
224
+ if (!isRegisterDataLike(entry.data)) continue;
225
+ const id = entry.data.id;
226
+ if (typeof id !== "string") continue;
227
+ if (entry.customType === "pending:register") {
228
+ registers.set(id, typeof entry.data.type === "string" ? entry.data.type : undefined);
229
+ } else if (entry.customType === "pending:unregister") {
230
+ unregistered.add(id);
231
+ registers.delete(id);
232
+ }
233
+ }
234
+ return [...registers.entries()].map(([id, type]) => ({ id, type }));
235
+ }