@zhushanwen/subagent-core 0.8.0 → 0.9.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 (167) hide show
  1. package/dist/{chunk-OL5BK4VN.js → chunk-LZJOEDGQ.js} +455 -203
  2. package/dist/engine-discovery-scan-Da4Dkzsi.d.cts +818 -0
  3. package/dist/engine-discovery-scan-Da4Dkzsi.d.ts +818 -0
  4. package/dist/execution/engine/engine-discovery-scan.cjs +216 -155
  5. package/dist/execution/engine/engine-discovery-scan.d.cts +1 -2
  6. package/dist/execution/engine/engine-discovery-scan.d.ts +1 -2
  7. package/dist/execution/engine/engine-discovery-scan.js +1 -1
  8. package/dist/execution/relay-env.js +5 -4
  9. package/dist/index.cjs +7686 -5894
  10. package/dist/index.d.cts +1876 -1360
  11. package/dist/index.d.ts +1876 -1360
  12. package/dist/index.js +7048 -5493
  13. package/dist.bundle/index.cjs +7747 -5957
  14. package/package.json +4 -4
  15. package/src/__tests__/manifest-store.test.ts +16 -15
  16. package/src/__tests__/robustness-medium-batch1.test.ts +10 -14
  17. package/src/__tests__/robustness-medium-batch2.test.ts +7 -2
  18. package/src/execution/__tests__/alive-store.test.ts +117 -1
  19. package/src/execution/__tests__/batch-finalized.test.ts +206 -0
  20. package/src/execution/__tests__/chat-engine-routing.test.ts +117 -1
  21. package/src/execution/__tests__/{cold-resurrect.test.ts → cold-lookup.test.ts} +133 -33
  22. package/src/execution/__tests__/collect-coordinator-service.test.ts +7 -5
  23. package/src/execution/__tests__/conversation-continuation.test.ts +1452 -0
  24. package/src/execution/__tests__/delivery-methods.test.ts +90 -176
  25. package/src/execution/__tests__/dialog-queue.test.ts +70 -3
  26. package/src/execution/__tests__/dispose-manifest-recovery.test.ts +475 -0
  27. package/src/execution/__tests__/execute-and-await-worktree.test.ts +3 -3
  28. package/src/execution/__tests__/execute-nesting.test.ts +8 -5
  29. package/src/execution/__tests__/execution-record.test.ts +8 -148
  30. package/src/execution/__tests__/finalize-record.test.ts +295 -129
  31. package/src/execution/__tests__/get-record-for-action-restart.test.ts +21 -29
  32. package/src/execution/__tests__/helpers/fake-engine-port.ts +13 -68
  33. package/src/execution/__tests__/helpers/legacy-sidecar.ts +33 -0
  34. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +9 -5
  35. package/src/execution/__tests__/idle-gc.test.ts +60 -0
  36. package/src/execution/__tests__/lifecycle-manager.test.ts +3 -254
  37. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +43 -22
  38. package/src/execution/__tests__/model-config-service.test.ts +111 -0
  39. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +10 -6
  40. package/src/execution/__tests__/notify-ledger.test.ts +42 -1
  41. package/src/execution/__tests__/rebuild-indexes.test.ts +329 -0
  42. package/src/execution/__tests__/record-binding.test.ts +613 -0
  43. package/src/execution/__tests__/record-origin.test.ts +318 -0
  44. package/src/execution/__tests__/record-store-intent-api.test.ts +600 -0
  45. package/src/execution/__tests__/record-store-orphan-revive.test.ts +71 -3
  46. package/src/execution/__tests__/record-store.test.ts +72 -54
  47. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +8 -5
  48. package/src/execution/__tests__/round-supervisor-workflow-origin.test.ts +205 -0
  49. package/src/execution/__tests__/run-orchestration-write-lease.test.ts +293 -0
  50. package/src/execution/__tests__/run-orchestration.test.ts +199 -0
  51. package/src/execution/__tests__/session-file-gc.test.ts +35 -4
  52. package/src/execution/__tests__/session-reconstructor.test.ts +78 -0
  53. package/src/execution/__tests__/state-marker.test.ts +288 -0
  54. package/src/execution/__tests__/stream-sink-retirement.test.ts +8 -5
  55. package/src/execution/__tests__/subagent-actions-core.test.ts +67 -16
  56. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +0 -1
  57. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +27 -11
  58. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +17 -11
  59. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +130 -53
  60. package/src/execution/__tests__/subagent-service.test.ts +17 -215
  61. package/src/execution/__tests__/subprocess-agent-runner-no-progress-killall.test.ts +138 -0
  62. package/src/execution/__tests__/subprocess-agent-runner.test.ts +105 -660
  63. package/src/execution/__tests__/sync-collect-recovery.test.ts +23 -16
  64. package/src/execution/__tests__/terminal-write-latency.test.ts +79 -0
  65. package/src/execution/__tests__/workflow-agent-dispatch.test.ts +782 -0
  66. package/src/execution/alive-store.ts +37 -28
  67. package/src/execution/{cold-resurrect.ts → cold-lookup.ts} +48 -45
  68. package/src/execution/config.ts +1 -1
  69. package/src/execution/conversation-continuation.ts +541 -0
  70. package/src/execution/dialog-queue.ts +60 -12
  71. package/src/execution/engine/__tests__/common/capability-gate.test.ts +1 -1
  72. package/src/execution/engine/__tests__/common/journal-wiring.test.ts +16 -1
  73. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +17 -51
  74. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +0 -5
  75. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +1 -1
  76. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +5 -9
  77. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +0 -3
  78. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -3
  79. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -3
  80. package/src/execution/engine/__tests__/registry.test.ts +0 -1
  81. package/src/execution/engine/__tests__/routing.test.ts +0 -1
  82. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +0 -3
  83. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +0 -3
  84. package/src/execution/engine/client/__tests__/engine-client-reap.test.ts +212 -0
  85. package/src/execution/engine/client/__tests__/mirror.test.ts +73 -1
  86. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +2 -9
  87. package/src/execution/engine/client/__tests__/remote-engine.test.ts +46 -12
  88. package/src/execution/engine/client/engine-client.ts +81 -25
  89. package/src/execution/engine/client/mirror.ts +9 -0
  90. package/src/execution/engine/client/remote-engine.ts +52 -34
  91. package/src/execution/engine/client/reverse-router.ts +6 -27
  92. package/src/execution/engine/common/__tests__/run-signals.test.ts +79 -0
  93. package/src/execution/engine/common/capability-gate.ts +27 -0
  94. package/src/execution/engine/common/data-dir.ts +3 -2
  95. package/src/execution/engine/common/errors.ts +1 -1
  96. package/src/execution/engine/common/journal-wiring.ts +18 -9
  97. package/src/execution/engine/common/run-signals.ts +83 -0
  98. package/src/execution/engine/d8-compat.ts +1 -1
  99. package/src/execution/engine/host/__tests__/host-bridge.test.ts +3 -18
  100. package/src/execution/engine/host/host-bridge.ts +19 -41
  101. package/src/execution/engine/host/pi-host-binding.ts +5 -5
  102. package/src/execution/engine/port.ts +34 -54
  103. package/src/execution/engine/types.ts +11 -14
  104. package/src/execution/execution-record.ts +15 -47
  105. package/src/execution/finalize-record.ts +94 -197
  106. package/src/execution/idle-gc.ts +9 -3
  107. package/src/execution/lifecycle-manager.ts +25 -361
  108. package/src/execution/lifecycle-predicates.ts +22 -19
  109. package/src/execution/manifest-store.ts +40 -42
  110. package/src/execution/model-config-service.ts +1 -1
  111. package/src/execution/notifier.ts +39 -1
  112. package/src/execution/notify-host.ts +13 -4
  113. package/src/execution/record-entry.ts +20 -2
  114. package/src/execution/record-store.ts +925 -160
  115. package/src/execution/relay-env.ts +8 -3
  116. package/src/execution/round-supervisor/domain.ts +17 -5
  117. package/src/execution/round-supervisor/service-binding.test.ts +89 -53
  118. package/src/execution/round-supervisor/service-binding.ts +71 -21
  119. package/src/execution/round-supervisor/supervisor.ts +23 -9
  120. package/src/execution/service/record-access.ts +547 -0
  121. package/src/execution/service/record-lifecycle.ts +542 -0
  122. package/src/execution/service/run-orchestration.ts +1647 -0
  123. package/src/execution/service/service-bootstrap.ts +111 -0
  124. package/src/execution/service/service-constants.ts +27 -0
  125. package/src/execution/service/session-baselines.ts +401 -0
  126. package/src/execution/service/sync-collect-domain.ts +442 -0
  127. package/src/execution/service/workflow-dispatch.ts +567 -0
  128. package/src/execution/session-file-gc.ts +11 -8
  129. package/src/execution/session-reconstructor.ts +44 -1
  130. package/src/execution/sessions-index.ts +20 -3
  131. package/src/execution/settled-watchdog.ts +86 -43
  132. package/src/execution/state-marker.ts +516 -0
  133. package/src/execution/stream-sink.ts +1 -1
  134. package/src/execution/subagent-actions-core.ts +53 -31
  135. package/src/execution/subagent-service.ts +643 -2980
  136. package/src/execution/subprocess-agent-runner.ts +46 -323
  137. package/src/execution/types.ts +60 -43
  138. package/src/execution/ui-request-handler-factory.ts +5 -0
  139. package/src/execution/worktree-manager.ts +1 -1
  140. package/src/execution/worktree-registry.ts +1 -1
  141. package/src/index.ts +6 -5
  142. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +2 -3
  143. package/src/orchestration/__tests__/agent-call-stream.test.ts +24 -49
  144. package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +4 -4
  145. package/src/orchestration/__tests__/file-run-store.test.ts +5 -7
  146. package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +2 -3
  147. package/src/orchestration/__tests__/run-snapshot.test.ts +27 -43
  148. package/src/orchestration/__tests__/worker-message-pump-workflow-dispatch.test.ts +274 -0
  149. package/src/orchestration/execute-agent-call.ts +1 -1
  150. package/src/orchestration/file-run-store.ts +1 -1
  151. package/src/orchestration/models/ports.ts +20 -13
  152. package/src/orchestration/models/types.ts +11 -13
  153. package/src/orchestration/run-snapshot.ts +18 -22
  154. package/src/orchestration/worker-message-pump.ts +33 -57
  155. package/src/shared/atomic-write.ts +10 -8
  156. package/dist/chunk-T2SYBW3I.js +0 -24
  157. package/dist/engine-discovery-scan-BXLA8y-z.d.cts +0 -1624
  158. package/dist/engine-discovery-scan-BXLA8y-z.d.ts +0 -1624
  159. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +0 -255
  160. package/src/execution/__tests__/finalized-marker.test.ts +0 -104
  161. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  162. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -488
  163. package/src/execution/__tests__/subprocess-agent-runner-timeout.test.ts +0 -75
  164. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  165. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +0 -230
  166. package/src/execution/finalized-marker.ts +0 -70
  167. package/src/execution/tombstone-store.ts +0 -72
@@ -1,8 +1,9 @@
1
1
  // src/execution/engine/common/journal-wiring.ts
2
2
  //
3
- // [D3-③ journal 接线合一] host 侧 event journal 接线的共享 helper(唯一实现,两调用
4
- // 点——SubagentService.runEngineTask(chat 域)与 SubprocessAgentRunner.runworkflow
5
- // 域))。设计权威源:docs/design/subagent-dual-track-convergence.md §3.3 D3-③(writer +
3
+ // [D3-③ journal 接线合一] host 侧 event journal 接线的共享 helper(唯一实现,调用
4
+ // 点全部在 SubagentService:workflow runWorkflowEngineTaskwireEventJournal
5
+ // taskId=record.id)+ chat runEngineTask 与 tool 域 runAndFinalize 两处(同
6
+ // record.id))。设计权威源:docs/design/subagent-dual-track-convergence.md §3.3 D3-③(writer +
6
7
  // retarget + handle 回填两份提为 common 层共享 helper)+ 双轨清单 #6。
7
8
  //
8
9
  // 收敛前形态(两份同构接线):
@@ -17,6 +18,7 @@
17
18
  // fsync 一次,§3.3.6 写入纪律;写失败已由 writer 内部 warn + failed 收口,close 不抛,
18
19
  // journal 是②级尽力而为数据源)。
19
20
 
21
+ import { SHARED_POOL_KEY } from "@zhushanwen/subagent-engine-sdk";
20
22
  import type { AgentEvent } from "../../../shared/agent-event.ts";
21
23
  import { getEngineDataDir } from "./data-dir.ts";
22
24
  import { JournalWriter } from "./event-journal.ts";
@@ -26,16 +28,17 @@ import type { EngineHandle } from "../types.ts";
26
28
  /**
27
29
  * journal 初始占位池 key(= pi 的恒定池 key 'shared')。pi 无隔离池
28
30
  * (PI_CODING_AGENT_DIR 全局一份,设计 §3.3.9),占位即终值;zcode 在 prepare 期
29
- * retarget 到实际池 key。值与 RunContext.poolKey 的初始占位同源——本常量是该值在
30
- * common 层的单一权威(原先 Service 用 'shared' 字面量、SAR 用 PI_POOL_KEY,等值异名)。
31
+ * retarget 到实际池 key。值与 RunContext.poolKey 的初始占位同源——值单源
32
+ * SDK SHARED_POOL_KEY(L3 收编:原先 Service 用 'shared' 字面量、SAR 用 PI_POOL_KEY
33
+ * 等值异名;本名保留 journal 占位语义,值不再本地声明)。
31
34
  */
32
- export const JOURNAL_INITIAL_POOL_KEY = "shared";
35
+ export const JOURNAL_INITIAL_POOL_KEY = SHARED_POOL_KEY;
33
36
 
34
37
  /** wireEventJournal 的参数。 */
35
38
  export interface JournalWiringOptions {
36
39
  /** 实际执行引擎 id(journal 路径分段 + line 元数据)。 */
37
40
  engineId: string;
38
- /** 宿主侧任务标识(journal 文件名与池引用计数 key:chat = record.id;workflow 域 = 'sa-' 前缀占位)。 */
41
+ /** 宿主侧任务标识(journal 文件名与池引用计数 key;三处调用点统一 = record.id)。 */
39
42
  taskId: string;
40
43
  /**
41
44
  * journal 落盘后的事件转发(workflow 域的 liveRecord 通道)。缺省不转发(chat 域
@@ -77,9 +80,15 @@ export function wireEventJournal(opts: JournalWiringOptions): JournalWiring {
77
80
  });
78
81
  return {
79
82
  // 先落盘再转发(原 onEvent 未传时也恒传包装版——下游 onEvent 通道是事件生成后的
80
- // 纯转发,无行为分支,仅多一次入队)
83
+ // 纯转发,无行为分支,仅多一次入队)。
84
+ //
85
+ // activity 豁免 append:纯活性信号不进持久/重放面——双侧 reducer(SDK
86
+ // journal-replay / core execution-record)对其 no-op,豁免不破坏 live≡reload
87
+ // 重放等价性;seq 由 append 铸造、过滤在 append 前故无 seq 空洞;
88
+ // forwardEvents 照发(workflow liveRecord reducer no-op,chat/守护刷新面在
89
+ // observedEvent 上游不受影响);取证面由 pi stdout/stderr tee 覆盖。
81
90
  onEvent: (event) => {
82
- journal.append(event);
91
+ if (event.type !== "activity") journal.append(event);
83
92
  opts.forwardEvents?.(event);
84
93
  },
85
94
  onPoolResolved: (poolKey) => {
@@ -0,0 +1,83 @@
1
+ // src/execution/engine/common/run-signals.ts
2
+ //
3
+ // [H2 W2 迁移步⑥] 运行期 signal 合流公共 helper——原定义在 subprocess-agent-runner.ts
4
+ // (模块内直调),随 service 统一编排入口 executeWorkflowAgent 接管 workflow 派发
5
+ // (设计 docs/design/subagent-workflow-record-unification.md §5 W2 八步迁移表)提为
6
+ // engine/common 公共面:SAR 与 SubagentService 两调用点共用同一实现(行为逐字节
7
+ // 等价搬移,函数体不改)。SAR 侧经 re-export 保持既有 import 路径(测试消费面零
8
+ // 改动),W4 掏空 SAR.run 后本文件成为唯一权威落点。
9
+
10
+ import { HOST_TIMEOUT_ABORT_REASON } from "./kill-chain.ts";
11
+
12
+ /** 合并 signal 的句柄:signal 供 engine.run 消费,dispose 移除桥接 listener(finally 必达)。 */
13
+ export interface MergedRunSignalHandle {
14
+ signal: AbortSignal;
15
+ /** 移除全部桥接 listener(幂等)。run 正常收敛(merged 不 abort)时是唯一清理通道。 */
16
+ dispose(): void;
17
+ }
18
+
19
+ /**
20
+ * D-A9 + [M3] 运行期 signal 合流:外部 signal(run 级 abort)+ per-call 墙钟 timeoutMs
21
+ * + [M3] no-progress watchdog abort —— 任一 abort 都让返回 signal abort。
22
+ *
23
+ * reason 语义保持 D-A9 原样:timeoutMs 到期 abort 带 HOST_TIMEOUT_ABORT_REASON 标记
24
+ *(引擎合成终态时判别「宿主超时」vs「外部 cancel」);外部 signal 与 watchdog 的
25
+ * abort 不带标记(wireAbortSignal 只消费 abort 事实,不读 reason)。
26
+ *
27
+ * 无任何信号源(timeoutMs 缺省/<=0 且无 watchdog)时原样返回 external signal(零新对象,
28
+ * 既有行为逐点不变)。
29
+ *
30
+ * dispose 的必要性:merged signal 正常收敛(不 abort)时,桥接在外部 run 级 signal 上的
31
+ * listener 不会自行移除——同一 run 多次 agent 调用会累积 listener 直至
32
+ * MaxListenersExceededWarning,故由调用方 finally 调 dispose。
33
+ */
34
+ export function mergeRunSignals(
35
+ signal: AbortSignal,
36
+ timeoutMs?: number,
37
+ noProgressSignal?: AbortSignal,
38
+ ): MergedRunSignalHandle {
39
+ const hasTimeout = timeoutMs !== undefined && timeoutMs > 0;
40
+ if (!hasTimeout && noProgressSignal === undefined) {
41
+ return { signal, dispose: () => {} };
42
+ }
43
+
44
+ const controller = new AbortController();
45
+ const bridges: Array<{ source: AbortSignal; handler: () => void }> = [];
46
+ let timer: NodeJS.Timeout | undefined;
47
+
48
+ const dispose = (): void => {
49
+ for (const bridge of bridges) bridge.source.removeEventListener("abort", bridge.handler);
50
+ bridges.length = 0;
51
+ if (timer !== undefined) {
52
+ clearTimeout(timer);
53
+ timer = undefined;
54
+ }
55
+ };
56
+
57
+ // 先挂清理 listener:任一信号源已 abort 时 bridge 会同步 abort controller,若清理
58
+ // listener 尚未就位,timeout timer / 已挂 listener 将不会被回收(原实现的既有时序盲区)。
59
+ controller.signal.addEventListener(
60
+ "abort",
61
+ () => dispose(),
62
+ { once: true },
63
+ );
64
+
65
+ if (hasTimeout) {
66
+ timer = setTimeout(() => controller.abort(HOST_TIMEOUT_ABORT_REASON), timeoutMs);
67
+ timer.unref();
68
+ }
69
+
70
+ const bridge = (source: AbortSignal): void => {
71
+ // 已 abort(前序信号源抢先 / 外部 signal 传入时已中止)后不再挂新 listener:
72
+ // 否则该 listener 永远等不到 controller 的清理(已过 abort 时点)。
73
+ if (controller.signal.aborted) return;
74
+ const handler = (): void => controller.abort();
75
+ bridges.push({ source, handler });
76
+ if (source.aborted) handler();
77
+ else source.addEventListener("abort", handler, { once: true });
78
+ };
79
+ bridge(signal);
80
+ if (noProgressSignal !== undefined) bridge(noProgressSignal);
81
+
82
+ return { signal: controller.signal, dispose };
83
+ }
@@ -32,7 +32,7 @@ import { EngineClient } from "./client/engine-client.ts";
32
32
  import { RemoteEngine, type RemoteEngineManifestSnapshot } from "./client/remote-engine.ts";
33
33
  import {
34
34
  readRelayForwardEnv,
35
- } from "../relay-env.ts";
35
+ } from "@zhushanwen/subagent-engine-sdk";
36
36
  import { getEngineDataDir } from "./common/data-dir.ts";
37
37
  import {
38
38
  CONSERVATIVE_CAPABILITIES,
@@ -1,6 +1,6 @@
1
- // HostBridge 契约 + core 实现 单测(W6,impl-plan §2.6 2 / 设计 §3.8 最小示例 9 方法)。
2
- // 覆盖:9 方法委托行为、getRecordForAction 异常 → null、cancel 的 void 包装、
3
- // takeChatRound 未提供 → null、armIdleTimer/disarmIdleTimer 对 lifecycle-manager 的
1
+ // HostBridge 契约 + core 实现 单测(W6;[H1 U6] takeChatRound 交接面用例随 chat
2
+ // 退役删除)。覆盖:方法委托行为、getRecordForAction 异常 → null、cancel 的 void 包装、
3
+ // armIdleTimer/disarmIdleTimer 对 lifecycle-manager 的
4
4
  // 接线(含超时回调 onIdleTimeout 触发,fake timers)。
5
5
 
6
6
  import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
@@ -9,7 +9,6 @@ import {
9
9
  createHostBridge,
10
10
  type HostBridge,
11
11
  type HostBridgeServiceFace,
12
- type HostChatRoundTicket,
13
12
  } from "../host-bridge.ts";
14
13
  import {
15
14
  _resetLifecycleState,
@@ -32,7 +31,6 @@ function makeService(): HostBridgeServiceFace & {
32
31
  closeSubagent: vi.fn(async () => {}),
33
32
  cancel: vi.fn(() => true),
34
33
  collectRecords: vi.fn((): SubagentRecord[] => [{ id: "r1" } as SubagentRecord]),
35
- takeChatRound: vi.fn(() => undefined),
36
34
  reportRecordTransition: vi.fn(() => {}),
37
35
  };
38
36
  return {
@@ -42,7 +40,6 @@ function makeService(): HostBridgeServiceFace & {
42
40
  closeSubagent: spies.closeSubagent,
43
41
  cancel: spies.cancel,
44
42
  collectRecords: spies.collectRecords,
45
- takeChatRound: spies.takeChatRound as HostBridgeServiceFace["takeChatRound"],
46
43
  reportRecordTransition: spies.reportRecordTransition,
47
44
  };
48
45
  }
@@ -96,18 +93,6 @@ describe("HostBridge(W6,设计 §3.8 最小示例 9 方法)", () => {
96
93
  expect(service.spies.cancel).toHaveBeenCalledWith("r1");
97
94
  });
98
95
 
99
- it("takeChatRound:有票 → 透传;无票 / 服务面未提供 → null", () => {
100
- expect(bridge.takeChatRound("t1")).toBeNull();
101
- const ticket: HostChatRoundTicket = {
102
- record: fakeRecord("r1"),
103
- opts: {} as HostChatRoundTicket["opts"],
104
- signal: undefined,
105
- priority: 1,
106
- };
107
- (service.spies.takeChatRound as ReturnType<typeof vi.fn>).mockReturnValue(ticket);
108
- expect(bridge.takeChatRound("t1")).toBe(ticket);
109
- });
110
-
111
96
  it("reportRecordTransition 委托(record 整体上报,无 patch 形态——见契约头注释)", () => {
112
97
  const record = fakeRecord("r1");
113
98
  bridge.reportRecordTransition(record);
@@ -2,12 +2,12 @@
2
2
  //
3
3
  // HostBridge 契约 + core 侧实现(W6,impl-plan §2.6 / 设计 §3.8 D2 表 + 最小示例)。
4
4
  //
5
- // 归属裁定(设计 §3.8 D2 表逐条):PiEngineService 9 成员中——executeAndAwait /
6
- // getRecordForAction / collectRecords / closeSubagent / cancel / ChatRoundTicket /
7
- // record 状态回写 / idle+activate lock 定时器——都是「宿主执行链 / 数据所有权在宿主」,
8
- // HostBridge(core);pi 包(W7)经 host/* 反向请求消费本面。spawnedChildren
9
- // 引擎进程(core 镜像见同目录 spawned-children.ts);sendPromptCommand / EPIPE 兜底 /
10
- // 冷续轮 resume(stdin-writer)归 pi 包(W7 迁移物)。
5
+ // 归属裁定(设计 §3.8 D2 表逐条):executeAndAwait / getRecordForAction /
6
+ // collectRecords / closeSubagent / cancel / record 状态回写 / idle+activate lock
7
+ // 定时器——都是「宿主执行链 / 数据所有权在宿主」,归 HostBridge(core);pi 包(W7)
8
+ // host/* 反向请求消费本面。spawnedChildren 归引擎进程(core 镜像见同目录
9
+ // spawned-children.ts);sendPromptCommand / EPIPE 兜底归 pi 包(W7 迁移物)。
10
+ // [H1 U6] ChatRoundTicket 交接面与冷续轮 resume(stdin-writer)已随 chat 域退役。
11
11
  //
12
12
  // 本文件只依赖 core 公共类型(types.ts / record-store / stream-sink /
13
13
  // lifecycle-manager / orchestration 类型),不 import inproc pi 引擎目录 内部——它是 pi 包
@@ -26,34 +26,21 @@ import type { StatusFilter } from "../../record-store.ts";
26
26
  import type { SubagentStream } from "../../stream-sink.ts";
27
27
  import type {
28
28
  AgentEvent,
29
- AgentResult,
30
29
  ExecuteOptions,
31
30
  ExecutionRecord,
32
31
  SubagentRecord,
33
32
  } from "../../types.ts";
34
33
 
35
- /**
36
- * chat 域轮次交接包的 core 契约基座(设计 §3.8 D2「ChatRoundTicket → HostBridge」)。
37
- * pi 专有扩展(identity / SessionRunnerContext / SpawnResumeOpts resume)在
38
- * pi-engine.ChatRoundTicket extends 本接口(W7 随包迁移;过渡期 record/opts/signal/
39
- * priority/stream 五字段的宿主编排语义在此单一权威)。
40
- */
41
- export interface HostChatRoundTicket {
42
- record: ExecutionRecord;
43
- opts: ExecuteOptions;
44
- signal: AbortSignal | undefined;
45
- priority: number;
46
- stream?: SubagentStream;
47
- }
48
-
49
34
  /**
50
35
  * HostBridge 的服务实现面(SubagentService 的结构子集,鸭子类型——与原 pi-engine 的
51
- * PiEngineService 同一形态的协议化泛化:chat 域轮次面泛型参数化,pi 绑定 =
52
- * HostBridgeServiceFace<ChatRoundTicket>,见 pi-host-binding.ts re-export)。
53
- * 为什么用结构接口而非 import SubagentService 类型:防 Service 内部演进连锁影响
54
- * 契约面 + 测试可注入 fake(PiEngineService 的既有先例,语义照搬)。
36
+ * PiEngineService 同一形态的协议化泛化)。为什么用结构接口而非 import SubagentService
37
+ * 类型:防 Service 内部演进连锁影响契约面 + 测试可注入 fake(PiEngineService 的既有
38
+ * 先例,语义照搬)。
39
+ * [H1 U6] chat 域轮次交接可选面(HostChatRoundTicket / takeChatRound / runChatRound /
40
+ * resumeChatRound)已随 chat 域退役删除——续聊 = Continuation → 新 run + resume,
41
+ * 引擎经协议 converse,不再回调宿主编排面。
55
42
  */
56
- export interface HostBridgeServiceFace<TTicket extends HostChatRoundTicket = HostChatRoundTicket> {
43
+ export interface HostBridgeServiceFace {
57
44
  executeAndAwait(
58
45
  opts: ExecuteOptions,
59
46
  signal?: AbortSignal,
@@ -64,23 +51,18 @@ export interface HostBridgeServiceFace<TTicket extends HostChatRoundTicket = Hos
64
51
  closeSubagent(record: ExecutionRecord, force: boolean): Promise<void>;
65
52
  cancel(id: string): boolean;
66
53
  collectRecords(limit: number, statusFilter?: StatusFilter): SubagentRecord[];
67
- /** chat 域轮次交接(run 的 chat 分支入口):按 taskId 取走预备包(一次性消费)。 */
68
- takeChatRound?(taskId: string): TTicket | undefined;
69
- /** 执行预备的 chat 轮次(编排归 Service:pool 槽 + runSpawn + 终态迁移)。 */
70
- runChatRound?(ticket: TTicket): Promise<AgentResult>;
71
- /** 冷路径续轮(interact message 分支的编排回调:守卫 + record 迁移 + kick-off)。 */
72
- resumeChatRound?(record: ExecutionRecord, text: string): void;
73
54
  /** record 状态迁移上报(热路径投递后让 runtime 派生缓存失效 / GUI 回流)。 */
74
55
  reportRecordTransition?(record: ExecutionRecord): void;
75
56
  }
76
57
 
77
58
  /**
78
- * HostBridge 接口(设计 §3.8 最小示例,9 方法)。core 侧实现;pi 包经 host/* 反向
79
- * 请求消费。签名与最小示例的两处实现级偏差(均按现状语义落地):
59
+ * HostBridge 接口(设计 §3.8 最小示例的协议化视图)。core 侧实现;pi 包经 host/*
60
+ * 反向请求消费。签名与最小示例的实现级偏差(均按现状语义落地):
80
61
  * - getRecordForAction 返回 ExecutionRecord | null(现状实现面的活 record 形态;
81
62
  * 不存在 / 不可达 → null,引擎侧 resolveRecord 的 try/catch 语义内聚到本面);
82
63
  * - reportRecordTransition 收 record 对象(现状状态回写以 record 为单位整体上报,
83
64
  * 无 patch 增量形态——造 patch 形态属凭空造词,W7 反向通道载荷再议)。
65
+ * [H1 U6] takeChatRound(chat 域轮次交接)已随 chat 域退役删除。
84
66
  */
85
67
  export interface HostBridge {
86
68
  executeAndAwait(
@@ -93,7 +75,6 @@ export interface HostBridge {
93
75
  collectRecords(limit: number, filter?: StatusFilter): SubagentRecord[];
94
76
  closeSubagent(record: ExecutionRecord, force: boolean): Promise<void>;
95
77
  cancel(id: string): Promise<void>;
96
- takeChatRound(taskId: string): HostChatRoundTicket | null;
97
78
  reportRecordTransition(record: ExecutionRecord): void;
98
79
  armIdleTimer(id: string, ms: number): void;
99
80
  disarmIdleTimer(id: string): void;
@@ -111,10 +92,8 @@ export interface HostBridgeDeps {
111
92
  onIdleTimeout: (recordId: string) => void;
112
93
  // [F-3 删除登记] 曾有的 waitForRoundTerminal / escalateKill 可选注入(W3 D3 cancel
113
94
  // 终态等待面)已删:createHostBridge 全仓无生产调用点,且该面与生产 cancel 链结构
114
- // 冲突(cancelBackground 同步 unregisterChatRoundRoute 后,waitForRoundTerminal
115
- // race 轮终相位恒等满 3s 超时)。D3 core 侧收敛语义由引擎面等价承接 =
116
- // chat-session.cancel(waiter 先于 kill 注册 + killChain 有界升级),偏差登记见
117
- // chat-domain-v1x-liveness-governance.impl-plan.md §5。
95
+ // 冲突(waitForRoundTerminal race 轮终相位恒等满 3s 超时)。[H1 U6] 注释内旧符号
96
+ // (chat 轮路由注销 / chat-session.cancel)已随 chat 域退役消亡。
118
97
  }
119
98
 
120
99
  /** HostBridge core 实现(SubagentService 编排面的协议化视图)。 */
@@ -136,14 +115,13 @@ export function createHostBridge(deps: HostBridgeDeps): HostBridge {
136
115
  * cancel 语义 = 受理即返回(service.cancel 同步布尔 → 契约 void)。
137
116
  * [F-3 删除登记] 终态等待/杀链升级面已删(无生产装配点 + 与 cancelBackground 的
138
117
  * 路由注销冲突,见 HostBridgeDeps 尾注);生产收敛语义由引擎面承接 =
139
- * chat-session.cancel(waiter 先于 kill 注册 → roundLifecycle 终态相位
118
+ * chat-session.cancel(waiter 先于 kill 注册 → 等轮次终态相位
140
119
  * CANCEL_SETTLE_GRACE_MS 未收敛走 killChain 有界升级)。resolve 语义归引擎侧
141
120
  * 判 notResumable(契约注释,W6 起如此)。
142
121
  */
143
122
  cancel: async (id) => {
144
123
  service.cancel(id);
145
124
  },
146
- takeChatRound: (taskId) => service.takeChatRound?.(taskId) ?? null,
147
125
  reportRecordTransition: (record) => service.reportRecordTransition?.(record),
148
126
  armIdleTimer: (id, ms) => {
149
127
  armIdleTimer(id, () => deps.onIdleTimeout(id), ms);
@@ -23,11 +23,12 @@
23
23
  // (pi-subagent-cli spawn-runner 的 spawn watchdog)保持同源常量,漂移由 conformance
24
24
  // chat golden(spawn-args 断言)在引擎包侧守护。
25
25
 
26
+ import { SHARED_POOL_KEY } from "@zhushanwen/subagent-engine-sdk";
26
27
  import type { EnginePort } from "../port.ts";
27
28
  import { EngineNotFoundError, getEngine, hasEngine, listEngines } from "../registry.ts";
28
29
 
29
30
  /** pi 无隔离池(PI_CODING_AGENT_DIR 全局一份,协议化设计 §3.3.9),poolKey 恒 'shared'。 */
30
- export const PI_POOL_KEY = "shared";
31
+ export const PI_POOL_KEY = SHARED_POOL_KEY;
31
32
 
32
33
  /** watchdog 换算下限(分钟):与引擎包 spawn-runner 的 floor 同源(30min)。 */
33
34
  const WATCHDOG_FLOOR_MINUTES = 30;
@@ -46,9 +47,9 @@ export function maxTurnsToWatchdogMs(maxTurns: number): number {
46
47
  }
47
48
 
48
49
  /**
49
- * 宿主侧 pi EnginePort 解析(SAR / chat 域路由):registry 的 'pi'(发现器装载的
50
- * cli descriptor → RemoteEngine)直接返回——chat 轮次与 run 域同路(协议 run(interact)
51
- * 发往 pi-subagent-cli 引擎进程)。
50
+ * 宿主侧 pi EnginePort 解析(SAR / 会话形态轮路由):registry 的 'pi'(发现器装载的
51
+ * cli descriptor → RemoteEngine)直接返回——续聊轮与 run 域同路(协议 run 帧发往
52
+ * pi-subagent-cli 引擎进程)。
52
53
  * [U-2 一致性修复] pi **未注册**(引擎包未装/发现失败)时返回不可用 stub,不静默
53
54
  * 直构任何本地实例——保留设计 D4「全不可用 → 派发期 engine_not_found + 安装指引」
54
55
  * 错误契约(zcode 侧 d8-compat 同语义,两引擎对称)。
@@ -85,7 +86,6 @@ function piUnavailableEnginePort(): EnginePort {
85
86
  }),
86
87
  probe: () => fail(),
87
88
  run: () => fail(),
88
- interact: () => fail(),
89
89
  read: () => fail(),
90
90
  };
91
91
  }
@@ -16,20 +16,16 @@
16
16
  // (滚动重启推迟谓词输入)。权威源:
17
17
  // docs/design/crash-forensics-and-watchdog.md §3.3 D5。
18
18
  //
19
- // 四个能力面(D1):
20
- // run —— 主语义:一次性 fire-to-completion 任务执行;
21
- // interact —— 交互控制面(chatMode message/close/cancel + idle,可选能力面,
22
- // capabilities.conversation 声明接通与否);
19
+ // 三个能力面(D1;[H1 U6] interact 面已随 chat 域退役删除——续聊统一为新 run + resume):
20
+ // run —— 主语义:一次性 fire-to-completion 任务执行(会话形态续聊轮同走 run,
21
+ // resume 锚点经 RunContext.resume 携带);
23
22
  // read —— session 历史读取(D6 三级降级链);
24
23
  // probe —— 探针(D7:二进制存在/版本解析/干跑校验)。
25
24
  // capabilities() 同步无副作用——「调用前拒绝」(D11 处置三级)的判据。
26
25
 
27
26
  import type { ChildProcess } from "node:child_process";
28
27
 
29
- import type {
30
- HostRoundLifecycleParams,
31
- ResumeAnchor,
32
- } from "@zhushanwen/subagent-engine-sdk";
28
+ import type { ResumeAnchor } from "@zhushanwen/subagent-engine-sdk";
33
29
 
34
30
  import type { AgentCallOpts } from "../../orchestration/models/types.ts";
35
31
  import type { ModelInfo } from "../model-resolver.ts";
@@ -40,8 +36,6 @@ import type {
40
36
  EngineCapabilities,
41
37
  EngineHandle,
42
38
  EngineHandleData,
43
- InteractAction,
44
- InteractResult,
45
39
  ProbeReport,
46
40
  SessionView,
47
41
  } from "./types.ts";
@@ -96,6 +90,25 @@ export interface RunContext {
96
90
  * pi 引擎另经 ExecuteOptions 投影进 record)。
97
91
  */
98
92
  engineFallback?: { from: string; reason: string };
93
+ /**
94
+ * [F6] 根 session id(SubagentService.sessionRootId 注入)——pi 引擎 relay 归属键
95
+ * SESSION_ID 的权威来源(经 wire ctx.sessionRootId → server 还原 → SpawnRunParams
96
+ * → buildChildEnv)。刻意走 per-run ctx 而非 EngineClient 的进程级 env:客户端按
97
+ * 引擎缓存为惰性单例,进程级 env 在 pi fork 换 sessionId 后会陈旧;per-run ctx 恒
98
+ * 新鲜,且与 RECORD_ID 已有的 per-run 形态一致。additive:undefined/null/空串不
99
+ * 上 wire,zcode 等引擎忽略。
100
+ */
101
+ sessionRootId?: string;
102
+ /**
103
+ * [Option C 协议化] 权威 subagent session 目录(getSubagentSessionDir(agentDir,
104
+ * rootCwd) 宿主推导值)——经 wire ctx.sessionDir 送达 pi 引擎组装 `--session-dir`。
105
+ * 生产注入方 = RemoteEngine(cli 形态引擎的唯一宿主侧适配点,env 同源推导,见
106
+ * remote-engine buildRunParams);编排层显式注入(ctx.sessionDir 有值)时优先于
107
+ * RemoteEngine 自推导。zcode 等不消费 session 目录的引擎忽略本字段。编排层可
108
+ * 不注入;RemoteEngine 缺省以同源 env 推导值补齐后恒上 wire;[LEGACY] fallback
109
+ * 仅旧宿主/独立运行引擎形态可达。
110
+ */
111
+ sessionDir?: string;
99
112
  /**
100
113
  * [P4 对齐点③] 引擎声明实际隔离池 key(journal 落盘路径权威)。宿主创建 journal
101
114
  * writer 时只能用缺省占位 poolKey(pi 恒 'shared'),非池化稳定的引擎(zcode 按
@@ -129,33 +142,16 @@ export interface RunContext {
129
142
  */
130
143
  onChildSpawned?: (child: ChildProcess) => void;
131
144
  /**
132
- * [W3 v1.x] chat 会话形态参数(协议 run.params.chat 的 RunContext 承载位):
133
- * - recordId:core 预建 record 的关联键(引擎据此上报首轮 runId 键之外的反向
134
- * 载荷与 interact 定位)——task.conversation === true 的 chat 轮必传;
135
- * - resume:冷续锚点(重开已 idle session 续聊;pi 消费 sessionRef.sessionFile
136
- * ——对照协议化设计前 SpawnResumeOpts.sessionFile 的锚点面)。
137
- * 类型权威 = SDK RunChatParams(remote-engine 直传,结构互证由 implements 关系
138
- * typecheck 期承载)。非 chat 轮不传,wire 上不出现该键。
145
+ * [W3 v1.x → H1 U6 终态] 会话形态参数(协议 run.params.resume 的 RunContext
146
+ * 承载位,键已随 U6 键切换从 `chat` 泛化为 `resume`):
147
+ * - recordId:core 预建 record 的关联键(引擎据此上报 childSpawned/childStateChanged
148
+ * record 键形态与 handle 锚定)——会话形态轮(task.conversation === true)必传;
149
+ * - resume:续聊锚点(record.sessionFile 续写原文件;pi 消费
150
+ * sessionRef.sessionFile——对照协议化设计前 SpawnResumeOpts.sessionFile 的锚点面)。
151
+ * 类型权威 = SDK RunResumeParams(remote-engine 直传,结构互证由 implements 关系
152
+ * 在 typecheck 期承载)。一次性轮不传,wire 上不出现该键。
139
153
  */
140
- chat?: { recordId: string; resume?: ResumeAnchor };
141
- /**
142
- * [W3 v1.x] host/roundLifecycle 轮次生命周期消费口(第 9 反向通道,settled/idle/
143
- * failed 三相位;关联键 runId|recordId 互斥)。首轮(run 会话形态)经 run 作用域
144
- * 路由到达(runId 键);续聊轮(interact)无 runId——经 EnginePort
145
- * registerChatRoundRoute 的 recordId 键路由到达(见下)。消费语义(arm/disarm/
146
- * settled 交棒)归宿主编排层(settled-watchdog 协议事件面接线,W4 三入口)。
147
- */
148
- onRoundLifecycle?: (phase: HostRoundLifecycleParams) => void;
149
- }
150
-
151
- /**
152
- * [W3 v1.x] chat 轮次反向通道路由(recordId 键)——interact 续聊轮的 streamDelta /
153
- * roundLifecycle 分发目标(协议关联键裁定 D1-A:续聊轮无独立 runId)。与 run 作用域
154
- * RunRoute 同构的薄消费面;注册/注销时机归宿主 chat 编排(轮开始注册、record 终态注销)。
155
- */
156
- export interface ChatRoundRoute {
157
- onStreamDelta?: (delta: string) => void | Promise<void>;
158
- onRoundLifecycle?: (phase: HostRoundLifecycleParams) => void | Promise<void>;
154
+ resume?: { recordId: string; resume?: ResumeAnchor };
159
155
  }
160
156
 
161
157
  // ============================================================
@@ -197,29 +193,13 @@ export interface EnginePort {
197
193
  probe(opts?: { force?: boolean }): Promise<ProbeReport>;
198
194
 
199
195
  /** D1 主语义:fire-to-completion。[D6 合流] task = AgentCallOpts(单一任务形状,
200
- * 原 AgentTaskSpec 已并入——字段裁定见 orchestration/models/types.ts)。 */
196
+ * 原 AgentTaskSpec 已并入——字段裁定见 orchestration/models/types.ts)。会话形态
197
+ * 续聊轮同走本方法(resume 锚点经 ctx.resume 携带,[H1 U6] interact 面退役)。 */
201
198
  run(task: AgentCallOpts, ctx: RunContext): Promise<EngineRunResult>;
202
199
 
203
- /**
204
- * D1 可选面:交互控制面。pi 首期原生实现(现有 chatMode 行为直通);不支持
205
- * conversation 的引擎返回 engine_capability_unsupported(同步拒绝、不创建进程)。
206
- */
207
- interact(handle: EngineHandle, action: InteractAction): Promise<InteractResult>;
208
-
209
200
  /** D6 三级降级链:①引擎原生读取 → ②宿主 event journal(P2)→ ③outcome-only。 */
210
201
  read(handle: EngineHandle): Promise<SessionView>;
211
202
 
212
- /**
213
- * [W3 v1.x] 可选面:chat 轮次反向通道路由注册(recordId 键)。interact 续聊轮的
214
- * streamDelta / roundLifecycle 按 recordId 关联(无 runId,D1-A),引擎进程发射后
215
- * 经协议客户端分发到本路由。与 validateModel/listModels 同款的 additively-optional
216
- * 演进:宿主 feature-detect(`typeof registerChatRoundRoute === "function"`),
217
- * 未实现的引擎(不支持 chat 域或旧客户端)续聊轮 delta/生命周期静默不可达——
218
- * conversation gate 已在派发前拦住无 chat 能力的引擎,本缺省只在「能力声明与
219
- * 客户端实现错位」的诊断形态出现。返回注销函数(record 终态时宿主调用)。
220
- */
221
- registerChatRoundRoute?(recordId: string, route: ChatRoundRoute): () => void;
222
-
223
203
  /**
224
204
  * [U7] 可选面:模型可发现性——引擎自带 provider/model 体系时(如 zcode 的 v2 桌面
225
205
  * 登录态),列出当前环境实际可用的模型清单(带凭据校验),供 system prompt 引擎段
@@ -4,10 +4,11 @@
4
4
  // §3.3.5(EnginePort 与中立类型完整契约)+ §3.3.6(EngineHandle/journal/SessionView 格式)。
5
5
  //
6
6
  // [S4 簇 3 收编] 契约类型单源化(type-only):AgentOutcome / EngineHandleData /
7
- // ReplayedTurn / SessionView / EngineCapabilities / ProbeReport / InteractAction /
8
- // InteractResult 的本地定义已删除,自 @zhushanwen/subagent-engine-sdk re-export
9
- // (SDK protocol/contract-types.ts 是类型闭包 SSOT,core 反向 re-export 保上层消费面
10
- // ——import 方路径零改动;结构等价由 protocol-closure.test.ts 断言族守卫)。
7
+ // ReplayedTurn / SessionView / EngineCapabilities / ProbeReport 的本地定义已删除,
8
+ // @zhushanwen/subagent-engine-sdk re-export(SDK protocol/contract-types.ts 是
9
+ // 类型闭包 SSOT,core 反向 re-export 保上层消费面——import 方路径零改动;结构等价
10
+ // protocol-closure.test.ts 断言族守卫)。[H1 U5/U6] InteractAction / InteractResult
11
+ // 已随 chat 域 interact 面退役删除。
11
12
  // EngineHandle 留守本地:SDK 无此类型(协议面用裸 data 载荷),宿主侧句柄包装接口
12
13
  // 是 core 域概念。
13
14
  //
@@ -20,7 +21,7 @@
20
21
 
21
22
  import type { EngineHandleData } from "@zhushanwen/subagent-engine-sdk";
22
23
 
23
- // AgentEvent 8 种事件:权威定义在 SDK contract-types,经 execution/types.ts re-export
24
+ // AgentEvent 9 种事件:权威定义在 SDK contract-types,经 execution/types.ts re-export
24
25
  // → shared/agent-event.ts 转发层 → 本文件(链条保持,维持「shared/ 是类型共享层」的
25
26
  // 架构约定)。新增粗粒度约束(coarse 引擎至少合成一次 message_end + 一次 turn_end)
26
27
  // 由 conformance 套件断言(P4),不在类型层编码。
@@ -34,26 +35,22 @@ export type {
34
35
  AgentOutcome,
35
36
  EngineCapabilities,
36
37
  EngineHandleData,
37
- InteractAction,
38
- InteractResult,
39
38
  ProbeReport,
40
39
  ReplayedTurn,
41
40
  SessionView,
42
41
  } from "@zhushanwen/subagent-engine-sdk";
43
42
 
44
43
  // ============================================================
45
- // EngineHandle(run/interact/read 三面的连接件,D1/§3.3.6)——core 域类型留宿主侧
44
+ // EngineHandle(run/read 两面的连接件,D1/§3.3.6)——core 域类型留宿主侧
46
45
  // ============================================================
47
46
 
48
47
  /**
49
- * 引擎会话句柄(run 返回、interact/read 入参)。
48
+ * 引擎会话句柄(run 返回、read 入参;[H1 U5/U6] interact 面退役后不再有 interact
49
+ * 消费方)。
50
50
  *
51
51
  * 契约三条(D1):不透明(上层不解构——唯一例外是 record 持久化层序列化 data 字段与
52
- * read 降级链)、可持久化(data 是纯 JSON,主会话 reload 后 read/interact 仍可用)、
53
- * 自描述(data 含 engineId + 引擎 session 定位符 + pool key + adapter 版本)。
54
- *
55
- * 对进程已死的 handle 调 interact 必须返回 engine_session_not_resumable(指向 cold
56
- * resume 路径),而非笼统失败——由各引擎 interact 实现保证。
52
+ * read 降级链)、可持久化(data 是纯 JSON,主会话 reload 后 read 仍可用)、自描述
53
+ * data 含 engineId + 引擎 session 定位符 + pool key + adapter 版本)。
57
54
  */
58
55
  export interface EngineHandle {
59
56
  /** 持久化数据。上层不得解构其内部字段(见契约三条)。 */