@zhushanwen/subagent-core 0.6.0 → 0.7.1

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,377 @@
1
+ // fake-engine-protocol.mjs —— W10 协议黑盒套件的 fake 引擎 CLI(conformance 专用,
2
+ // 与 W2 client/__tests__ 的 fake-engine.mjs 分工:后者测 EngineClient 连接域语义,
3
+ // 本件是协议基线回放器——按 fixture(schemaVersion 1)回放帧序列)。
4
+ //
5
+ // 形态对齐协议 v1(stdout 独占 NDJSON;stdin 帧驱动):
6
+ // - FAKE_PROTOCOL_FIXTURE:fixture JSON 路径(必填);本件 = 该 fixture 的回放引擎;
7
+ // - 正向方法(10 个):initialize / probe / run / cancel / interact / read /
8
+ // listModels / validateModel / dispose / ping——结果取 fixture 对应段;
9
+ // - 反向通道(8 个):host/log / host/askUser / host/permission / host/streamDelta /
10
+ // host/poolResolved / host/handleReady / host/childSpawned / host/childStateChanged
11
+ // ——run 期间按 fixture.run.script 逐动作播放;
12
+ // - 错误帧:FAKE_PROTOCOL_ERROR=run_failed(run 回错误帧)| unknown_method(对任意
13
+ // 未知名方法回 engine_method_unknown——不在 v1 错误码表内的码也必须原样透传,
14
+ // 断言的是帧形态而非码表);FAKE_PROTOCOL_VERSION 越界 → initialize 回
15
+ // engine_protocol_mismatch;
16
+ // - childSpawned 的 pid = 真 spawn 一个同组长眠 node 子进程(供 POSIX kill(-pid,0)
17
+ // 组探测断言与 killAll 收割断言——范围口径 R9-1:一代子进程 + 组内后代)。
18
+ //
19
+ // [W6 conformance 增量] 追加面(全部 env 开关驱动,缺省关闭——既有回放行为不变):
20
+ // - FAKE_PID_FILE:启动时写自身 pid(SIGTERM 用例的 kill 定位锚——core 侧 pidfile
21
+ // 归 EngineClient 所有,fake 侧不触碰,路径自建自删归测试);
22
+ // - FAKE_CAPABILITIES_CONVERSATION:覆写 initialize 应答的
23
+ // capabilities.conversation(chat gate 负向:旧形态引擎 manifest 无该位);
24
+ // - 新 script op(env 注入 script,沿 FAKE_RUN_HANG 先例):
25
+ // { op:"stderr", text } → 引擎 stderr 写点(engine_crashed
26
+ // 的 stderr 尾 400 窗口实证);
27
+ // { op:"roundLifecycle", keyedBy, key,
28
+ // phase, error?, anchor? } → host/roundLifecycle 帧(三相位 ×
29
+ // runId|recordId 关联键分路);
30
+ // streamDelta op 支持 action.recordId → recordId 键 delta(续聊轮关联键);
31
+ // - 数据面应答回声:roundLifecycle / recordId-delta 帧的②应答到达时回发
32
+ // host/log("ack <label>")——core 侧断言「宿主确认收到」回执链闭合的观测锚;
33
+ // - FAKE_RUN_LIFECYCLE=1 / FAKE_RUN_RECORD_DELTA=1 / FAKE_RUN_STDERR_HANG=1:
34
+ // run script 注入上述动作段(三相位 × 双键 / recordId 键 delta / stderr+hang)。
35
+
36
+ import { spawn } from "node:child_process";
37
+ import { readFileSync, writeFileSync } from "node:fs";
38
+ import { createInterface } from "node:readline";
39
+
40
+ const fixturePath = process.env.FAKE_PROTOCOL_FIXTURE;
41
+ if (!fixturePath) {
42
+ process.stderr.write("fake-engine-protocol: FAKE_PROTOCOL_FIXTURE is required\n");
43
+ process.exit(1);
44
+ }
45
+ const fixture = JSON.parse(readFileSync(fixturePath, "utf8"));
46
+
47
+ const MODE = process.env.FAKE_PROTOCOL_ERROR ?? "none"; // none | run_failed | unknown_method
48
+ const PROTOCOL_VERSION = Number(process.env.FAKE_PROTOCOL_VERSION ?? fixture.protocolVersion ?? 1);
49
+
50
+ // [W6] SIGTERM 用例的进程定位锚(测试自建自删;写失败不阻断回放主路径)。
51
+ if (process.env.FAKE_PID_FILE) {
52
+ try {
53
+ writeFileSync(process.env.FAKE_PID_FILE, String(process.pid), "utf8");
54
+ } catch {
55
+ // 定位锚写失败只影响依赖它的用例(该用例 waitFor pidfile 会超时显式红),
56
+ // 不影响其余回放行为。
57
+ }
58
+ }
59
+
60
+ // [W6] 数据面应答回声记账:请求 id → 回声 label(帧②到达时回发 host/log)。
61
+ const ackEchoLabels = new Map();
62
+
63
+ let grandchildren = []; // 同组长眠子进程(killAll 收割断言对象)
64
+
65
+ function send(frame) {
66
+ process.stdout.write(`${JSON.stringify(frame)}\n`);
67
+ }
68
+ function reverseRequest(id, method, params) {
69
+ send({ id, method, params });
70
+ }
71
+
72
+ let nextRequestId = 100;
73
+
74
+ async function playRunScript(runId, script) {
75
+ for (const action of script) {
76
+ if (cancelledRuns.has(runId)) return;
77
+ switch (action.op) {
78
+ case "log":
79
+ reverseRequest(`rev-log-${nextRequestId++}`, "host/log", {
80
+ level: action.level ?? "info",
81
+ component: action.component ?? "fake",
82
+ message: action.message ?? "",
83
+ });
84
+ break;
85
+ case "poolResolved":
86
+ reverseRequest(`rev-pool-${nextRequestId++}`, "host/poolResolved", {
87
+ runId,
88
+ poolKey: action.poolKey ?? "shared",
89
+ });
90
+ break;
91
+ case "handleReady":
92
+ reverseRequest(`rev-ready-${nextRequestId++}`, "host/handleReady", {
93
+ runId,
94
+ sessionRef: action.sessionRef ?? { sessionId: "sess-fixture" },
95
+ poolKey: action.poolKey ?? "shared",
96
+ });
97
+ break;
98
+ case "childSpawned": {
99
+ const grandchild = spawn(
100
+ process.execPath,
101
+ ["-e", "setInterval(() => {}, 1000)"],
102
+ { detached: false, stdio: "ignore" },
103
+ );
104
+ grandchildren.push(grandchild);
105
+ reverseRequest(`rev-child-${nextRequestId++}`, "host/childSpawned", {
106
+ pid: grandchild.pid,
107
+ recordId: action.recordId ?? runId,
108
+ });
109
+ break;
110
+ }
111
+ case "childStateChanged":
112
+ reverseRequest(`rev-childst-${nextRequestId++}`, "host/childStateChanged", {
113
+ pid: grandchildren[grandchildren.length - 1]?.pid,
114
+ recordId: action.recordId ?? runId,
115
+ state: action.state ?? "exited",
116
+ killed: action.killed ?? false,
117
+ ...(action.exitCode !== undefined ? { exitCode: action.exitCode } : {}),
118
+ ...(action.signal !== undefined ? { signal: action.signal } : {}),
119
+ });
120
+ break;
121
+ case "streamDelta": {
122
+ // [W6] action.recordId 有值 = 续聊轮 recordId 键 delta(关联键分路——
123
+ // D1-A:interact 发起的轮无 runId,经 handle.sessionRef 的 recordId 关联)。
124
+ const streamReqId = `rev-stream-${nextRequestId++}`;
125
+ if (action.recordId !== undefined) {
126
+ ackEchoLabels.set(streamReqId, `streamDelta recordId=${action.recordId}`);
127
+ reverseRequest(streamReqId, "host/streamDelta", {
128
+ recordId: action.recordId,
129
+ delta: action.delta ?? "",
130
+ });
131
+ } else {
132
+ reverseRequest(streamReqId, "host/streamDelta", {
133
+ runId,
134
+ delta: action.delta ?? "",
135
+ });
136
+ }
137
+ break;
138
+ }
139
+ case "stderr":
140
+ // [W6] 引擎 stderr 写点(engine_crashed stderr 尾窗的实证面——同步写,
141
+ // 后续动作可用 host/log 做到达锚)。
142
+ process.stderr.write(action.text ?? "");
143
+ break;
144
+ case "roundLifecycle": {
145
+ // [W6] host/roundLifecycle 帧(三相位 × runId|recordId 双关联键)。
146
+ // failed 相位必含 error{code,message}(isHostRoundLifecycleParams 判据)。
147
+ const lcReqId = `rev-lc-${nextRequestId++}`;
148
+ const keyed =
149
+ action.keyedBy === "recordId"
150
+ ? { recordId: action.key }
151
+ : { runId: action.key };
152
+ ackEchoLabels.set(lcReqId, `roundLifecycle ${action.key} ${action.phase}`);
153
+ reverseRequest(lcReqId, "host/roundLifecycle", {
154
+ ...keyed,
155
+ phase: action.phase,
156
+ ...(action.usage !== undefined ? { usage: action.usage } : {}),
157
+ ...(action.error !== undefined ? { error: action.error } : {}),
158
+ ...(action.anchor !== undefined ? { anchor: action.anchor } : {}),
159
+ });
160
+ break;
161
+ }
162
+ case "permission":
163
+ reverseRequest(`rev-perm-${nextRequestId++}`, "host/permission", {
164
+ runId,
165
+ request: action.request ?? {},
166
+ });
167
+ break;
168
+ case "askUser":
169
+ reverseRequest(`rev-ask-${nextRequestId++}`, "host/askUser", {
170
+ runId,
171
+ request: action.request ?? {},
172
+ });
173
+ break;
174
+ case "emit":
175
+ send({ method: "event", params: { runId, seq: action.seq, event: action.event } });
176
+ break;
177
+ case "hang":
178
+ // 挂起至 cancel 收敛(无 cancel 则永久挂起——core 3s 收敛窗口超时杀链面)
179
+ await new Promise((resolveHang) => {
180
+ hangingRuns.set(runId, resolveHang);
181
+ });
182
+ break;
183
+ default:
184
+ break;
185
+ }
186
+ }
187
+ }
188
+
189
+ const KNOWN_METHODS = new Set([
190
+ "initialize", "probe", "run", "cancel", "interact", "read",
191
+ "listModels", "validateModel", "dispose", "ping",
192
+ ]);
193
+
194
+ const askUserResults = new Map(); // 反向请求 id → 最终结果帧②(交互面两阶段)
195
+ const hangingRuns = new Map(); // runId → settle()——cancel 收敛用(hang 动作挂起时登记)
196
+ const cancelledRuns = new Set(); // cancel 已收敛的 runId——后续脚本动作全部跳过
197
+
198
+ createInterface({ input: process.stdin }).on("line", (line) => {
199
+ if (line.trim() === "") return;
200
+ let frame;
201
+ try {
202
+ frame = JSON.parse(line);
203
+ } catch {
204
+ return;
205
+ }
206
+
207
+ // 帧②(core 对反向请求的应答):askUser 最终结果到达——回放层记录后继续。
208
+ // [W6] 数据面(roundLifecycle / recordId-delta)应答到达 → 回发 host/log 回声
209
+ // (core 侧「宿主确认收到」回执链闭合的观测锚;NDJSON 单连接有序,回声先于
210
+ // run 应答帧到达)。
211
+ if (typeof frame.id === "string") {
212
+ const echoLabel = ackEchoLabels.get(frame.id);
213
+ if (echoLabel !== undefined) {
214
+ ackEchoLabels.delete(frame.id);
215
+ reverseRequest(`rev-ack-${nextRequestId++}`, "host/log", {
216
+ level: "debug",
217
+ component: "fake",
218
+ message: `ack ${echoLabel}`,
219
+ });
220
+ }
221
+ askUserResults.set(frame.id, frame.result ?? { unsupported: frame.error !== undefined });
222
+ return;
223
+ }
224
+
225
+ const { id, method, params } = frame;
226
+ if (MODE === "unknown_method" && !KNOWN_METHODS.has(method)) {
227
+ send({
228
+ id,
229
+ error: {
230
+ code: "engine_method_unknown",
231
+ message: `method "${method}" is not part of protocol v1`,
232
+ recovery: "Upgrade the engine package or align the protocol version.",
233
+ },
234
+ });
235
+ return;
236
+ }
237
+
238
+ switch (method) {
239
+ case "initialize": {
240
+ if (PROTOCOL_VERSION !== fixture.protocolVersion) {
241
+ send({
242
+ id,
243
+ error: {
244
+ code: "engine_protocol_mismatch",
245
+ message: `engine speaks protocol v${PROTOCOL_VERSION}, core requested/handshake produced v${fixture.protocolVersion}`,
246
+ recovery: "Align the engine package version with the host.",
247
+ data: { engineVersion: PROTOCOL_VERSION, coreVersion: fixture.protocolVersion },
248
+ },
249
+ });
250
+ return;
251
+ }
252
+ {
253
+ // [W6] chat gate 负向:env 覆写 capabilities.conversation(旧形态引擎
254
+ // manifest 无该 gate 位 → chat 请求同步拒的 initialize 面实证)。
255
+ const initResult = fixture.initialize.result;
256
+ const convOverride = process.env.FAKE_CAPABILITIES_CONVERSATION;
257
+ const result =
258
+ convOverride !== undefined && initResult.capabilities !== undefined
259
+ ? {
260
+ ...initResult,
261
+ capabilities: { ...initResult.capabilities, conversation: convOverride },
262
+ }
263
+ : initResult;
264
+ send({ id, result });
265
+ }
266
+ return;
267
+ }
268
+ case "probe":
269
+ if (process.env.FAKE_PROBE_FAIL === "1" && fixture.probeFailure !== undefined) {
270
+ send({ id, result: fixture.probeFailure });
271
+ } else {
272
+ send({ id, result: fixture.probe.result });
273
+ }
274
+ return;
275
+ case "listModels":
276
+ send({ id, result: fixture.listModels.result });
277
+ return;
278
+ case "validateModel":
279
+ send({ id, result: fixture.validateModel.result });
280
+ return;
281
+ case "interact":
282
+ send({ id, result: fixture.interact.result });
283
+ return;
284
+ case "read":
285
+ send({ id, result: fixture.read.result });
286
+ return;
287
+ case "ping":
288
+ case "dispose":
289
+ send({ id, result: { ok: true } });
290
+ if (method === "dispose") {
291
+ for (const g of grandchildren) g.kill("SIGTERM");
292
+ setImmediate(() => process.exit(0));
293
+ }
294
+ return;
295
+ case "cancel": {
296
+ // 受理应答 + 收敛在途挂起 run(3s 收敛窗口语义):挂起中的 playRunScript
297
+ // 以 cancelResult 终态应答回收(协议 cancel 契约:引擎须在窗口内收敛终态)。
298
+ send({ id, result: { ok: true } });
299
+ const runId = params?.runId;
300
+ const settle = hangingRuns.get(runId);
301
+ if (settle !== undefined) {
302
+ hangingRuns.delete(runId);
303
+ cancelledRuns.add(runId);
304
+ settle(); // 收敛:挂起解除,run 以 cancelResult 终态应答(脚本余项跳过)
305
+ }
306
+ return;
307
+ }
308
+ case "run": {
309
+ if (MODE === "run_failed") {
310
+ send({
311
+ id,
312
+ error: {
313
+ code: "engine_run_failed",
314
+ message: "scripted run failure (redacted)",
315
+ recovery: "Inspect the task and retry.",
316
+ },
317
+ });
318
+ return;
319
+ }
320
+ const runId = params?.runId ?? "run-smoke-1";
321
+ // [W6] env 注入 script 前置段(沿 FAKE_RUN_HANG 先例;顺序 = 注入段 → fixture 段)。
322
+ const injected = [];
323
+ if (process.env.FAKE_RUN_STDERR_HANG === "1") {
324
+ injected.push(
325
+ { op: "stderr", text: process.env.FAKE_STDERR_SAMPLE ?? "" },
326
+ { op: "log", level: "info", component: "fake", message: "stderr-flushed" },
327
+ { op: "hang" },
328
+ );
329
+ }
330
+ if (process.env.FAKE_RUN_LIFECYCLE === "1") {
331
+ injected.push(
332
+ // 三相位 × 双关联键(settled 带 usage;idle/failed 带 anchor;failed 带
333
+ // error{code,message}——isHostRoundLifecycleParams 的相位居留形状)。
334
+ { op: "roundLifecycle", keyedBy: "runId", key: "run-smoke-1", phase: "settled", usage: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 } },
335
+ { op: "roundLifecycle", keyedBy: "runId", key: "run-smoke-1", phase: "idle", anchor: { sessionRef: { sessionId: "sess-fixture" }, poolKey: "shared" } },
336
+ { op: "roundLifecycle", keyedBy: "runId", key: "run-smoke-1", phase: "failed", error: { code: "engine_run_failed", message: "round failed (scripted)", recovery: "Inspect the task and retry." } },
337
+ { op: "roundLifecycle", keyedBy: "recordId", key: "rec-chat-1", phase: "settled" },
338
+ { op: "roundLifecycle", keyedBy: "recordId", key: "rec-chat-1", phase: "idle", anchor: { sessionRef: { sessionId: "sess-chat-1" }, poolKey: "shared" } },
339
+ { op: "roundLifecycle", keyedBy: "recordId", key: "rec-chat-1", phase: "failed", error: { code: "engine_run_failed", message: "chat round failed (scripted)", recovery: "Inspect the task and retry." } },
340
+ );
341
+ }
342
+ if (process.env.FAKE_RUN_RECORD_DELTA === "1") {
343
+ injected.push({ op: "streamDelta", recordId: "rec-chat-1", delta: "chat-delta-not-routed-to-runId" });
344
+ }
345
+ const script = [...injected, ...(process.env.FAKE_RUN_HANG === "1"
346
+ ? [{ op: "poolResolved", poolKey: "shared" }, { op: "hang" }]
347
+ : []), ...fixture.run.script];
348
+ playRunScript(runId, script)
349
+ .then(() => send({ id, result: cancelledRuns.has(runId)
350
+ ? (fixture.run.cancelResult ?? {
351
+ handle: fixture.run.result.handle,
352
+ outcome: { content: "", error: "engine_run_failed: cancelled (fake)", exitCode: null, engineId: fixture.engineId },
353
+ })
354
+ : fixture.run.result }))
355
+ .catch((err) => {
356
+ send({ id, error: { code: "engine_run_failed", message: String(err), recovery: "Inspect the engine logs." } });
357
+ });
358
+ return;
359
+ }
360
+ default:
361
+ send({
362
+ id,
363
+ error: {
364
+ code: "engine_method_unknown",
365
+ message: `unhandled method "${String(method)}"`,
366
+ recovery: "Align protocol versions.",
367
+ },
368
+ });
369
+ }
370
+ });
371
+
372
+ // stdin EOF(宿主死亡)→ 自灭 + 收割同组后代(R9-1:一代子进程 + 组内后代零残留;
373
+ // 引擎自身 detached 后代不在收割覆盖范围——设计 §3.9 已接受代价)。
374
+ process.stdin.on("end", () => {
375
+ for (const g of grandchildren) g.kill("SIGKILL");
376
+ process.exit(0);
377
+ });