@zhushanwen/subagent-engine-sdk 0.10.0 → 0.11.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 (67) hide show
  1. package/dist/{chunk-AF2ETADP.js → chunk-2L3I2TWJ.js} +5 -10
  2. package/dist/{chunk-HSNDUHFH.js → chunk-3MCOZY3Z.js} +32 -4
  3. package/dist/{chunk-JZN76I3S.js → chunk-NVF3PADP.js} +29 -1
  4. package/dist/{chunk-LM7P7OTA.js → chunk-QBXDEF4N.js} +35 -3
  5. package/dist/{chunk-NTOLHLCL.js → chunk-QGXILDWB.js} +1 -1
  6. package/dist/{chunk-CT3FEBDO.js → chunk-QOFFM5YW.js} +7 -1
  7. package/dist/{chunk-CNCFMPEH.js → chunk-TJMS3YOR.js} +1 -1
  8. package/dist/{chunk-SGAIDL63.js → chunk-YFSNX3N3.js} +2 -2
  9. package/dist/cli-entry.d.cts +1 -1
  10. package/dist/cli-entry.d.ts +1 -1
  11. package/dist/{contract-types-jSa1g28F.d.cts → contract-types-BUHUMF9R.d.cts} +17 -17
  12. package/dist/{contract-types-jSa1g28F.d.ts → contract-types-BUHUMF9R.d.ts} +17 -17
  13. package/dist/env.cjs +5 -10
  14. package/dist/env.d.cts +6 -17
  15. package/dist/env.d.ts +6 -17
  16. package/dist/env.js +1 -1
  17. package/dist/{error-codes-f-UO4a8D.d.cts → error-codes-D_aPibUt.d.cts} +42 -6
  18. package/dist/{error-codes-DnFru4L4.d.ts → error-codes-DrNf0gwT.d.ts} +42 -6
  19. package/dist/index.cjs +133 -97
  20. package/dist/index.d.cts +29 -41
  21. package/dist/index.d.ts +29 -41
  22. package/dist/index.js +42 -59
  23. package/dist/journal-io.d.cts +1 -1
  24. package/dist/journal-io.d.ts +1 -1
  25. package/dist/journal-replay.cjs +2 -2
  26. package/dist/journal-replay.d.cts +4 -4
  27. package/dist/journal-replay.d.ts +4 -4
  28. package/dist/journal-replay.js +1 -1
  29. package/dist/kill-chain.d.cts +5 -5
  30. package/dist/kill-chain.d.ts +5 -5
  31. package/dist/kill-chain.js +2 -2
  32. package/dist/logger.d.cts +1 -1
  33. package/dist/logger.d.ts +1 -1
  34. package/dist/logs/stderr-rotation.d.cts +4 -4
  35. package/dist/logs/stderr-rotation.d.ts +4 -4
  36. package/dist/{methods-C2zvZqhP.d.ts → methods-BdIH3FwS.d.ts} +5 -5
  37. package/dist/{methods-BLxg4ZFr.d.cts → methods-CHiDwvRK.d.cts} +5 -5
  38. package/dist/node-executor.cjs +1 -1
  39. package/dist/node-executor.d.cts +4 -4
  40. package/dist/node-executor.d.ts +4 -4
  41. package/dist/node-executor.js +2 -2
  42. package/dist/port-contract.d.cts +9 -9
  43. package/dist/port-contract.d.ts +9 -9
  44. package/dist/protocol/index.cjs +73 -4
  45. package/dist/protocol/index.d.cts +57 -14
  46. package/dist/protocol/index.d.ts +57 -14
  47. package/dist/protocol/index.js +20 -2
  48. package/dist/server/index.cjs +1 -1
  49. package/dist/server/index.d.cts +10 -10
  50. package/dist/server/index.d.ts +10 -10
  51. package/dist/server/index.js +1 -1
  52. package/dist/spawn.cjs +32 -3
  53. package/dist/spawn.d.cts +34 -8
  54. package/dist/spawn.d.ts +34 -8
  55. package/dist/spawn.js +5 -3
  56. package/dist/ui-types.d.cts +2 -2
  57. package/dist/ui-types.d.ts +2 -2
  58. package/dist/zcode-db-paths.cjs +9 -2
  59. package/dist/zcode-db-paths.d.cts +11 -1
  60. package/dist/zcode-db-paths.d.ts +11 -1
  61. package/dist/zcode-db-paths.js +5 -3
  62. package/package.json +2 -2
  63. package/dist/chunk-GSW3DMN6.js +0 -39
  64. package/dist/relay-env.cjs +0 -71
  65. package/dist/relay-env.d.cts +0 -37
  66. package/dist/relay-env.d.ts +0 -37
  67. package/dist/relay-env.js +0 -23
@@ -13,8 +13,6 @@ var ENGINE_ENV_DENY_LIST = [
13
13
  "TAIJI_AGENT_PACKAGED",
14
14
  "TAIJI_RUNTIME_TOKEN",
15
15
  "TAIJI_AGENT_API_KEY",
16
- "TAIJI_SUBAGENT_RELAY_SESSION_ID",
17
- "TAIJI_SUBAGENT_RELAY_RECORD_ID",
18
16
  // 预设回落事实(env 名 SSOT = shared PRESET_FALLBACK_ENV_KEYS):「本进程本次运行」
19
17
  // 事实只对 runtime 直接 spawn 的 pi 成立,引擎一跳继承会造成子 agent pi 假披露
20
18
  "TAIJI_PRESET_FALLBACK_FROM",
@@ -25,9 +23,11 @@ var ENGINE_ENV_L0_INFRA_KEYS = [
25
23
  "TAIJI_AGENT_ENGINE_NODE",
26
24
  "ELECTRON_RUN_AS_NODE",
27
25
  "TAIJI_AGENT_SUBAGENT",
28
- "TAIJI_SUBAGENT_RELAY_SOCKET",
29
- "TAIJI_SUBAGENT_RELAY_NODE",
30
- "TAIJI_SUBAGENT_RELAY_SCRIPT"
26
+ // [M3] control 两键(键名 SSOT = src/control-env.ts):runtime 注入主 pi 与引擎的
27
+ // L0 基础设施键,嵌套 task pi 经引擎出站 env 继承同值。刻意不进 ENGINE_ENV_DENY_LIST:
28
+ // 引擎/嵌套 extension 是合法读者(transport 选择谓词 + engine_open 归属键)。
29
+ "TAIJI_SUBAGENT_CONTROL_SOCKET",
30
+ "TAIJI_SUBAGENT_CONTROL_ROOT_SESSION_ID"
31
31
  ];
32
32
  var ENV_PREFIX_SHAPE_RE = /^[A-Za-z0-9_]+$/;
33
33
  function deleteEnvKeysCaseInsensitive(env, names) {
@@ -81,11 +81,6 @@ function injectL0InfraKeys(env, opts) {
81
81
  if (opts.engineNode !== void 0) env.TAIJI_AGENT_ENGINE_NODE = opts.engineNode;
82
82
  if (opts.electronRunAsNode === true) env.ELECTRON_RUN_AS_NODE = "1";
83
83
  env.TAIJI_AGENT_SUBAGENT = "1";
84
- if (opts.relay !== void 0) {
85
- env.TAIJI_SUBAGENT_RELAY_SOCKET = opts.relay.socket;
86
- env.TAIJI_SUBAGENT_RELAY_NODE = opts.relay.node;
87
- env.TAIJI_SUBAGENT_RELAY_SCRIPT = opts.relay.script;
88
- }
89
84
  if (opts.identityEnv !== void 0) {
90
85
  for (const [key, value] of Object.entries(opts.identityEnv)) {
91
86
  if (value !== void 0) env[key] = value;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  killChain,
3
3
  safeKill
4
- } from "./chunk-CNCFMPEH.js";
4
+ } from "./chunk-TJMS3YOR.js";
5
5
  import {
6
6
  getLogger
7
7
  } from "./chunk-NXNNXGTY.js";
@@ -58,13 +58,40 @@ function resolveHostRequestTimeoutMs(opts) {
58
58
  }
59
59
  return parsed;
60
60
  }
61
- function killOwnProcessGroup() {
61
+ function killOwnProcessGroup(deps = {}) {
62
62
  const pid = process.pid;
63
+ const kill = deps.killFn ?? ((targetPid, signal) => process.kill(targetPid, signal));
64
+ if ((deps.platform ?? process.platform) === "win32") {
65
+ const fallbackSelfKill = (reason) => {
66
+ logger.warn(`taskkill self-tree failed (${reason}); falling back to self SIGKILL`);
67
+ try {
68
+ kill(pid, "SIGKILL");
69
+ } catch (err) {
70
+ logger.warn(
71
+ `self SIGKILL fallback failed (${String(err)}); descendant pi may linger until runtime sweep`
72
+ );
73
+ }
74
+ };
75
+ const spawnFn = deps.spawnFn ?? ((command, args, options) => spawn(command, [...args], options));
76
+ try {
77
+ const child = spawnFn("taskkill", ["/PID", String(pid), "/T", "/F"], {
78
+ stdio: "ignore",
79
+ windowsHide: true
80
+ });
81
+ child.on("error", (err) => {
82
+ fallbackSelfKill(String(err));
83
+ });
84
+ child.unref?.();
85
+ } catch (err) {
86
+ fallbackSelfKill(`spawn threw: ${String(err)}`);
87
+ }
88
+ return;
89
+ }
63
90
  try {
64
- process.kill(-pid, "SIGKILL");
91
+ kill(-pid, "SIGKILL");
65
92
  } catch (err) {
66
93
  logger.warn(`process-group kill failed (${String(err)}), falling back to self kill`);
67
- process.kill(pid, "SIGKILL");
94
+ kill(pid, "SIGKILL");
68
95
  }
69
96
  }
70
97
  function armEngineSelfDestruct(opts) {
@@ -133,6 +160,7 @@ export {
133
160
  spawnEngineChild,
134
161
  DEFAULT_ENGINE_HOST_REQUEST_TIMEOUT_MS,
135
162
  ENGINE_HOST_REQUEST_TIMEOUT_ENV,
163
+ killOwnProcessGroup,
136
164
  armEngineSelfDestruct,
137
165
  pumpNdjsonLines
138
166
  };
@@ -12,6 +12,30 @@ var SET_MODEL_REQUEST_TIMEOUT_MS = 1e4;
12
12
  var STDERR_TAIL_CHARS = 400;
13
13
 
14
14
  // src/protocol/error-codes.ts
15
+ var ENGINE_SPAWN_DELIVERY_ERROR_CODES = [
16
+ "engine_prompt_not_delivered",
17
+ "engine_prompt_rejected",
18
+ "engine_spawn_handshake_timeout"
19
+ ];
20
+ var ENGINE_TRANSPORT_ERROR_CODES = [
21
+ "engine_transport_unavailable",
22
+ "engine_transport_lost",
23
+ "engine_open_timeout",
24
+ "engine_frame_too_large",
25
+ "engine_backpressure_overflow"
26
+ ];
27
+ var ENGINE_SPAWN_DELIVERY_ERROR_RECOVERY = {
28
+ engine_prompt_not_delivered: "The task never reached the child pi (zero stdout after the prompt write, or the engine stdin was unavailable). Re-run the task; if it recurs, inspect the engine/pi logs (the failure carries the delivery diagnostics) and the runtime log.",
29
+ engine_prompt_rejected: "The child pi explicitly rejected the prompt command (success:false). Check the pi-side reason carried in the error detail (busy/queue/extension takeover states are reported by pi itself), then re-run.",
30
+ engine_spawn_handshake_timeout: "The engine spawn handshake did not complete in time. Check the runtime log for a spawn/handshake stall, then restart taiji and re-run the task."
31
+ };
32
+ var ENGINE_TRANSPORT_ERROR_RECOVERY = {
33
+ engine_transport_unavailable: "The runtime control socket is unreachable (connect or hello failed). The runtime side is failing explicitly instead of silently falling back to local spawn \u2014 restart taiji and re-run the task.",
34
+ engine_transport_lost: "The control connection to the runtime was lost mid-flight (runtime restart or crash). In-flight requests were rejected; restart taiji (or wait for the runtime to come back) and re-run the task \u2014 the connection is not retried in place.",
35
+ engine_open_timeout: "The runtime did not finish opening the engine channel in time (spawn/attribution stalled). Check the runtime log (engine opened / kill decision lines), then re-run the task.",
36
+ engine_frame_too_large: "A single frame exceeded the control-plane size limit and the channel was closed without truncation. Shrink the task/result payload (e.g. point the agent at files instead of inlining them) and re-run.",
37
+ engine_backpressure_overflow: "The control-plane write queue overflowed (engine consumed frames too slowly) and the overflowed scope was torn down without dropping frames silently. Re-run the task; if it recurs, reduce concurrent subagent fan-out."
38
+ };
15
39
  var SET_MODEL_ERROR_CODES = [
16
40
  /** 目标模型不在当前进程快照(子进程模型快照冻结于 spawn 时刻——模型本身有效,
17
41
  * 下一轮 spawn 现取目录即可用;宿主按「写覆盖意图」处置,设计 §7.2 快照型失败行)。 */
@@ -56,7 +80,7 @@ var EngineSdkError = class extends Error {
56
80
  this.recovery = recovery;
57
81
  this.data = data;
58
82
  }
59
- /** 协议 error 帧载荷投影。 */
83
+ /** 协议 error 帧载荷派生视图。 */
60
84
  toStructured() {
61
85
  return { code: this.code, message: this.message, recovery: this.recovery, data: this.data };
62
86
  }
@@ -117,6 +141,10 @@ export {
117
141
  SET_MODEL_STAGE_TIMEOUT_MS,
118
142
  SET_MODEL_REQUEST_TIMEOUT_MS,
119
143
  STDERR_TAIL_CHARS,
144
+ ENGINE_SPAWN_DELIVERY_ERROR_CODES,
145
+ ENGINE_TRANSPORT_ERROR_CODES,
146
+ ENGINE_SPAWN_DELIVERY_ERROR_RECOVERY,
147
+ ENGINE_TRANSPORT_ERROR_RECOVERY,
120
148
  SET_MODEL_ERROR_CODES,
121
149
  SET_MODEL_NOT_ACTIVE_CODE,
122
150
  ENGINE_PROTOCOL_ERROR_CODES,
@@ -30,12 +30,39 @@ var REVERSE_CHANNEL_TIMEOUT_CLASS = {
30
30
  "host/askUser": "interaction"
31
31
  };
32
32
 
33
+ // src/protocol/control-protocol.ts
34
+ var SUBAGENT_CONTROL_PROTOCOL_VERSION = 1;
35
+ var SUBAGENT_CONTROL_FRAME_KINDS = {
36
+ hello: "hello",
37
+ helloOk: "hello_ok",
38
+ helloReject: "hello_reject",
39
+ engineOpen: "engine_open",
40
+ engineOpened: "engine_opened",
41
+ engineOpenFailed: "engine_open_failed",
42
+ engineFrame: "engine_frame",
43
+ engineClose: "engine_close",
44
+ engineClosed: "engine_closed",
45
+ error: "error"
46
+ };
47
+ function isSubagentControlFrameKind(value) {
48
+ return typeof value === "string" && Object.values(SUBAGENT_CONTROL_FRAME_KINDS).includes(value);
49
+ }
50
+ var SUBAGENT_CONTROL_CLOSED_REASONS = {
51
+ engineExit: "engine_exit",
52
+ engineSignal: "engine_signal",
53
+ killedByControl: "killed_by_control",
54
+ openTimeout: "open_timeout"
55
+ };
56
+ function isSubagentControlClosedReason(value) {
57
+ return typeof value === "string" && Object.values(SUBAGENT_CONTROL_CLOSED_REASONS).includes(value);
58
+ }
59
+
33
60
  // src/protocol/contract-types.ts
34
61
  var AGENT_EVENT_TYPE_NAMES = [
35
62
  "tool_start",
36
63
  // noop-safe: 旧宿主 default 分支零写入——丢弃仅缺 tool 起始占位(显示降级),turn 结构不受损
37
64
  "tool_end",
38
- // noop-safe: 旧宿主 default 分支零写入——丢弃仅缺 result,turn 收口由 turn_end/message_end 承担
65
+ // noop-safe: 旧宿主 default 分支零写入——丢弃仅缺 result,turn 收尾由 turn_end/message_end 承担
39
66
  "text_delta",
40
67
  // noop-safe: 旧宿主 default 分支零写入——丢弃仅缺正文增量,不产生半解析状态
41
68
  "thinking_delta",
@@ -43,7 +70,7 @@ var AGENT_EVENT_TYPE_NAMES = [
43
70
  "turn_end",
44
71
  // noop-safe: 旧宿主 default 分支零写入——丢弃则该 turn 滞留进行态,journal 重放仍按序重建
45
72
  "message_end",
46
- // noop-safe: 旧宿主 default 分支零写入——丢弃仅缺 usage 聚合与闭合计量,已累积内容不回滚
73
+ // noop-safe: 旧宿主 default 分支零写入——丢弃仅缺 usage 聚合与结束计量,已累积内容不回滚
47
74
  "compaction",
48
75
  // noop-safe: 事件无载荷且现行 reducer 即直接 return——丢弃与处理零差异
49
76
  "activity",
@@ -125,7 +152,7 @@ var notificationFrameSchema = {
125
152
  type: {
126
153
  type: "string",
127
154
  // 事件 enum 从词表 SSOT 派生(U2 词表锁:union⟷词表互证后,此处不再
128
- // 手写字面量集合——手写即漂移面,病灶 1 的第三处同步点)
155
+ // 手写字面量集合——手写即漂移点,问题点 1 的第三处同步点)
129
156
  enum: [...AGENT_EVENT_TYPE_NAMES]
130
157
  }
131
158
  }
@@ -187,6 +214,11 @@ export {
187
214
  PROTOCOL_METHODS,
188
215
  REVERSE_CHANNELS,
189
216
  REVERSE_CHANNEL_TIMEOUT_CLASS,
217
+ SUBAGENT_CONTROL_PROTOCOL_VERSION,
218
+ SUBAGENT_CONTROL_FRAME_KINDS,
219
+ isSubagentControlFrameKind,
220
+ SUBAGENT_CONTROL_CLOSED_REASONS,
221
+ isSubagentControlClosedReason,
190
222
  AGENT_EVENT_TYPE_NAMES,
191
223
  protocolErrorSchema,
192
224
  requestFrameSchema,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  EngineSdkError
3
- } from "./chunk-JZN76I3S.js";
3
+ } from "./chunk-NVF3PADP.js";
4
4
 
5
5
  // src/node-executor.ts
6
6
  import { spawn } from "child_process";
@@ -1,8 +1,14 @@
1
1
  // src/zcode-db-paths.ts
2
2
  var ZCODE_HOST_DB_SUFFIX = [".zcode", "cli", "db", "db.sqlite"];
3
3
  var ZCODE_ISOLATED_DB_SEGMENTS = ["engines", "zcode", "session-db", "db.sqlite"];
4
+ var ZCODE_PI_SYNCED_PROVIDER_CONFIG_SEGMENTS = [
5
+ "engines",
6
+ "zcode",
7
+ "pi-synced-provider-config.json"
8
+ ];
4
9
 
5
10
  export {
6
11
  ZCODE_HOST_DB_SUFFIX,
7
- ZCODE_ISOLATED_DB_SEGMENTS
12
+ ZCODE_ISOLATED_DB_SEGMENTS,
13
+ ZCODE_PI_SYNCED_PROVIDER_CONFIG_SEGMENTS
8
14
  };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-PYO3YR7W.js";
4
4
  import {
5
5
  engineTimeoutDetail
6
- } from "./chunk-JZN76I3S.js";
6
+ } from "./chunk-NVF3PADP.js";
7
7
  import {
8
8
  getLogger
9
9
  } from "./chunk-NXNNXGTY.js";
@@ -152,7 +152,7 @@ function updateFromEvent(record, event) {
152
152
  return applyToolStart(record, event);
153
153
  case "tool_end":
154
154
  return applyToolEnd(record, event);
155
- // ── turn_end:闭合当前 turn ──
155
+ // ── turn_end:结束当前 turn ──
156
156
  case "turn_end":
157
157
  return applyTurnEnd(record);
158
158
  // ── message_end:usage 增量累加 + totalTokens 累加 ──
@@ -168,7 +168,7 @@ function updateFromEvent(record, event) {
168
168
  case "activity":
169
169
  return;
170
170
  // ── armed:武装确认回执([D3 协议版 P6],协议语义见 contract-types)——监控
171
- // 信号不进 record 投影,消费方 = 宿主等待门 + run 事件 journal(C3 第④步
171
+ // 信号不进 record 派生视图,消费方 = 宿主等待门 + run 事件 journal(C3 第④步
172
172
  // 双侧 reducer no-op 义务的 SDK 侧)
173
173
  case "armed":
174
174
  return;
@@ -5,7 +5,7 @@
5
5
  interface CliProtocolServerSink {
6
6
  /** 入站协议帧处理(readline 已拆行 + JSON.parse 后的帧)。 */
7
7
  handleFrame(frame: unknown): void;
8
- /** 数据面反向请求(host/log 等;应答分类由各包 server 实现承载)。 */
8
+ /** 数据范围反向请求(host/log 等;应答分类由各包 server 实现承载)。 */
9
9
  reverseRequest(method: string, params: unknown): Promise<unknown>;
10
10
  }
11
11
  /** runEngineCliEntry 参数。 */
@@ -5,7 +5,7 @@
5
5
  interface CliProtocolServerSink {
6
6
  /** 入站协议帧处理(readline 已拆行 + JSON.parse 后的帧)。 */
7
7
  handleFrame(frame: unknown): void;
8
- /** 数据面反向请求(host/log 等;应答分类由各包 server 实现承载)。 */
8
+ /** 数据范围反向请求(host/log 等;应答分类由各包 server 实现承载)。 */
9
9
  reverseRequest(method: string, params: unknown): Promise<unknown>;
10
10
  }
11
11
  /** runEngineCliEntry 参数。 */
@@ -17,7 +17,7 @@ interface AgentUsage {
17
17
  cost?: number;
18
18
  }
19
19
  interface AgentUsageTotal extends AgentUsage {
20
- /** 四项之和。投影时不再手工求和。 */
20
+ /** 四项之和。派生时不再手工求和。 */
21
21
  total: number;
22
22
  /** 累计成本(USD)。无成本数据时为 0。 */
23
23
  cost: number;
@@ -50,14 +50,14 @@ interface Turn {
50
50
  toolCalls: InternalToolCall[];
51
51
  /** 本 turn message_end 的 token 增量(聚合得 usage 总量)。 */
52
52
  usageDelta?: AgentUsage;
53
- /** turn_end 是否已到达。false=正在进行;true=已闭合。 */
53
+ /** turn_end 是否已到达。false=正在进行;true=已结束。 */
54
54
  closed: boolean;
55
55
  /** turn_end 到达时的墙钟时间戳(Date.now(),ms)。 */
56
56
  closedTs?: number;
57
57
  }
58
58
  /**
59
59
  * 引擎事件(10 种,协议 event.params.event 逐字序列化——「事件与 handle 序列化逐字
60
- * 兼容」不变量 3 的类型面)。语义锚点 = pi(ACP 词汇对照见 core execution/assembly/types.ts 注释)。
60
+ * 兼容」不变量 3 的类型范围)。语义锚点 = pi(ACP 词汇对照见 core execution/assembly/types.ts 注释)。
61
61
  *
62
62
  * activity = 纯活性信号:双侧 reducer no-op、不开 turn、不写状态、不落 journal
63
63
  * (core event-journal-wiring 对其豁免 append),只承诺「引擎活跃时周期性出现」——供宿主
@@ -115,7 +115,7 @@ type AgentEvent = {
115
115
  * 每个成员必须带一行 `// noop-safe: <论证>`:未知成员宽容语义四行①(ADR-0071)的
116
116
  * 逐变体登记——旧宿主 reducer 遇未知 event.type 走 default 分支零写入,标记后写
117
117
  * 「本变体被丢弃时状态无损」的一行论证(no-op 安全性属运行时消费语义,不可静态
118
- * 判定——守卫只查标记存在不查内容,落点 contract-closure.test.ts「noop-safe 标记守卫」)。
118
+ * 判定——检查只查标记存在不查内容,落点 contract-closure.test.ts「noop-safe 标记检查」)。
119
119
  *
120
120
  * 编译锁(漏改任一侧 typecheck 红,且错误指向漏点):
121
121
  * ① union 侧——成员 type 必须经 `EventName<"x">` 取名(约束 = 本词表):union 加
@@ -123,9 +123,9 @@ type AgentEvent = {
123
123
  * ② 词表侧——`satisfies readonly AgentEvent["type"][]`:词表加成员不加 union
124
124
  * → 错误直接落在词表漏改的成员行;
125
125
  * ③ 兜底——成员绕过 EventName 约束裸加字面量 → _EventVocabSyncLock 爆红。
126
- * 新增事件变体的同步面分两层,漏改任一处 typecheck 均红且精确指路(验收 A1 演练
127
- * 实证):协议面两笔(词表 + union)即协议面全同步——schema enum 与遍历型测试断言
128
- * 自动跟随;同仓消费面另有两处编译期同步点——journal-replay reducer case(穷尽
126
+ * 新增事件变体的同步点分两层,漏改任一处 typecheck 均红且精确指路(验收 A1 演练
127
+ * 实证):协议范围两笔(词表 + union)即协议范围全同步——schema enum 与遍历型测试断言
128
+ * 自动跟随;同仓消费方另有两处编译期同步点——journal-replay reducer case(穷尽
129
129
  * switch never 检查)与 contract-closure 构造冒烟(Record<AgentEventTypeName,…>
130
130
  * 漏键爆红)。不 bump 版本、不改任何引擎(演进政策 additive 面,判据全文见头注)。
131
131
  */
@@ -160,7 +160,7 @@ interface EngineHandleData {
160
160
  adapterVersion: string;
161
161
  }
162
162
  /**
163
- * [v1.x] 冷续 resume 锚点——EngineHandleData 定位键的投影子集(诊断字段
163
+ * [v1.x] 冷续 resume 锚点——EngineHandleData 定位键的派生子集(诊断字段
164
164
  * v/engineVersion/adapterVersion 不属锚点语义,不随锚点走)。消费点:
165
165
  * - run.params.resume(宿主 → 引擎:冷续重开已 idle 的 session,pi 消费
166
166
  * sessionRef.sessionFile —— 对照 core SpawnResumeOpts.sessionFile 的锚点面)。
@@ -199,7 +199,7 @@ interface SessionView {
199
199
  * 用户覆盖记账共用的模型指向形状(设计 subagent-model-switch §6.2/§7.3)。
200
200
  *
201
201
  * 刻意用结构化对象而非现役 wire 的字符串 canonical ref(`ctx.model` = "provider/id"):
202
- * 切换操作的原生输入面就是「provider 选了哪个模型」两个独立选择(前端模型选择器 /
202
+ * 切换操作的原生输入范围就是「provider 选了哪个模型」两个独立选择(前端模型选择器 /
203
203
  * runtime `model.switch` 均平铺 provider/modelId),字符串拼接形态会在协议两侧各做一次
204
204
  * 拆/拼(拆分规则 = provider 含 '/' 时无法无歧义反转),结构化形状让拆装只发生在宿主
205
205
  * 编排层单点(U2 组帧时拼 canonical ref、读回执时拆 ref)。
@@ -230,7 +230,7 @@ type EngineProcessModel = "per-window" | "shared-service";
230
230
  * 引擎能力声明(11 必填位 + 1 可选位 setModel)。三级:native / emulated / unsupported。
231
231
  * 声明的是本仓 subagent 链路实际接通的能力,不是引擎 RPC 层的理论能力。
232
232
  * 同步权威 = manifest(注册期直读);握手应答仅诊断(§3.3「同步成员清单」)。
233
- * 进程形态声明是独立字段(上方 EngineProcessModel——manifest 契约面,不在本
233
+ * 进程形态声明是独立字段(上方 EngineProcessModel——manifest 契约范围,不在本
234
234
  * 接口内),两套字段服务不同裁决(任务能力 vs 宿主实例管理)。
235
235
  */
236
236
  interface EngineCapabilities {
@@ -242,7 +242,7 @@ interface EngineCapabilities {
242
242
  * [H1 D5 语义收窄 + modeless] 「怎么续」形态轴兼 message 资格轴:
243
243
  * 位非 'unsupported' = 引擎可续聊(core capability-gate 的 message 资格门消费),
244
244
  * 值区分续聊形态——native(原地续写)/ cold(冷恢复重建 + 新 run + resume 锚点)。
245
- * 原名字沿用——conversation 位保留、语义从「interact 长驻控制面」收窄为
245
+ * 原名字沿用——conversation 位保留、语义从「interact 长驻控制范围」收窄为
246
246
  * 「resume 续聊能力」。[modeless 波2] 会话形态键只剩 run.params.resume(协议
247
247
  * task.conversation 已删),本轴不再是 per-run 模式开关——描述各引擎的真实
248
248
  * 续聊差异(gate 判据仍是 `=== "unsupported"` 拒绝,"cold" 与 "native" 等价
@@ -354,7 +354,7 @@ interface AgentOutcome {
354
354
  /** null = 被信号杀死(杀链/abort 合成终态的判据)。 */
355
355
  exitCode?: number | null;
356
356
  /**
357
- * [D5 诊断引用落账] 失败时子进程 stderr tee 文件绝对路径(引擎侧 W11 已有落盘)。
357
+ * [D5 诊断引用写入记录] 失败时子进程 stderr tee 文件绝对路径(引擎侧 W11 已有落盘)。
358
358
  *
359
359
  * 通道裁决(协议演进宪法 ADR-0071 判据链,2026-09-22 一致性审查 P1 修复登记):stderr
360
360
  * tee 路径是引擎产生的诊断事实,宿主不可靠推导(文件名格式/dataDir 解析/轮转
@@ -375,7 +375,7 @@ interface AgentOutcome {
375
375
  }
376
376
  /**
377
377
  * 引擎模型目录条目(manifest `modelCatalog.models` 条目形态,设计 §3.4 示例)。
378
- * 协议面 = initialize 应答 models? 与 listModels 应答 models 的元素型;
378
+ * 协议范围 = initialize 应答 models? 与 listModels 应答 models 的元素型;
379
379
  * manifest 解析与生成(gen:model-catalog)归 W4/W5 实装。
380
380
  */
381
381
  interface ModelCatalogEntry {
@@ -384,15 +384,15 @@ interface ModelCatalogEntry {
384
384
  canonicalRef?: string;
385
385
  }
386
386
  /**
387
- * 单次 agent 调用的任务声明——引擎面子集(协议 run.params.task;core 全量
388
- * AgentCallOpts 22 字段留 core,core 侧反向 re-export 保消费面)。
387
+ * 单次 agent 调用的任务声明——引擎侧子集(协议 run.params.task;core 全量
388
+ * AgentCallOpts 22 字段留 core,core 侧反向 re-export 保消费方)。
389
389
  *
390
390
  * 字段归属判据(协议演进宪法 ADR-0071 成文,权威源
391
391
  * docs/architecture/subagent-engine-protocolization.md §3.3「协议演进宪法」与
392
392
  * docs/adr/decisions.md ADR-0071;
393
- * 本注释是判据与存量结论的投影,新增字段按决策树依序裁决后在此登记):
393
+ * 本注释是判据与存量结论的派生整理,新增字段按决策树依序裁决后在此登记):
394
394
  * ① 引擎不消费它任务能否正确完成?能 → 宿主自持不上协议(「正确」含满足字段
395
- * 声明携带的约束面——轮次预算/超时等约束被引擎忽略即任务语义受损,视为消费);
395
+ * 声明携带的约束侧——轮次预算/超时等约束被引擎忽略即任务语义受损,视为消费);
396
396
  * ② 描述「任务是什么」(what) 还是「在什么环境跑/怎么跑」(where/how)?
397
397
  * what → task(预算/验收类约束 = 任务自带语义归 task,宿主偏好参数走③);
398
398
  * ③ 引擎能否自行推导该环境值且与宿主恒等?能 → 不上协议(推导权归引擎,设计期
@@ -17,7 +17,7 @@ interface AgentUsage {
17
17
  cost?: number;
18
18
  }
19
19
  interface AgentUsageTotal extends AgentUsage {
20
- /** 四项之和。投影时不再手工求和。 */
20
+ /** 四项之和。派生时不再手工求和。 */
21
21
  total: number;
22
22
  /** 累计成本(USD)。无成本数据时为 0。 */
23
23
  cost: number;
@@ -50,14 +50,14 @@ interface Turn {
50
50
  toolCalls: InternalToolCall[];
51
51
  /** 本 turn message_end 的 token 增量(聚合得 usage 总量)。 */
52
52
  usageDelta?: AgentUsage;
53
- /** turn_end 是否已到达。false=正在进行;true=已闭合。 */
53
+ /** turn_end 是否已到达。false=正在进行;true=已结束。 */
54
54
  closed: boolean;
55
55
  /** turn_end 到达时的墙钟时间戳(Date.now(),ms)。 */
56
56
  closedTs?: number;
57
57
  }
58
58
  /**
59
59
  * 引擎事件(10 种,协议 event.params.event 逐字序列化——「事件与 handle 序列化逐字
60
- * 兼容」不变量 3 的类型面)。语义锚点 = pi(ACP 词汇对照见 core execution/assembly/types.ts 注释)。
60
+ * 兼容」不变量 3 的类型范围)。语义锚点 = pi(ACP 词汇对照见 core execution/assembly/types.ts 注释)。
61
61
  *
62
62
  * activity = 纯活性信号:双侧 reducer no-op、不开 turn、不写状态、不落 journal
63
63
  * (core event-journal-wiring 对其豁免 append),只承诺「引擎活跃时周期性出现」——供宿主
@@ -115,7 +115,7 @@ type AgentEvent = {
115
115
  * 每个成员必须带一行 `// noop-safe: <论证>`:未知成员宽容语义四行①(ADR-0071)的
116
116
  * 逐变体登记——旧宿主 reducer 遇未知 event.type 走 default 分支零写入,标记后写
117
117
  * 「本变体被丢弃时状态无损」的一行论证(no-op 安全性属运行时消费语义,不可静态
118
- * 判定——守卫只查标记存在不查内容,落点 contract-closure.test.ts「noop-safe 标记守卫」)。
118
+ * 判定——检查只查标记存在不查内容,落点 contract-closure.test.ts「noop-safe 标记检查」)。
119
119
  *
120
120
  * 编译锁(漏改任一侧 typecheck 红,且错误指向漏点):
121
121
  * ① union 侧——成员 type 必须经 `EventName<"x">` 取名(约束 = 本词表):union 加
@@ -123,9 +123,9 @@ type AgentEvent = {
123
123
  * ② 词表侧——`satisfies readonly AgentEvent["type"][]`:词表加成员不加 union
124
124
  * → 错误直接落在词表漏改的成员行;
125
125
  * ③ 兜底——成员绕过 EventName 约束裸加字面量 → _EventVocabSyncLock 爆红。
126
- * 新增事件变体的同步面分两层,漏改任一处 typecheck 均红且精确指路(验收 A1 演练
127
- * 实证):协议面两笔(词表 + union)即协议面全同步——schema enum 与遍历型测试断言
128
- * 自动跟随;同仓消费面另有两处编译期同步点——journal-replay reducer case(穷尽
126
+ * 新增事件变体的同步点分两层,漏改任一处 typecheck 均红且精确指路(验收 A1 演练
127
+ * 实证):协议范围两笔(词表 + union)即协议范围全同步——schema enum 与遍历型测试断言
128
+ * 自动跟随;同仓消费方另有两处编译期同步点——journal-replay reducer case(穷尽
129
129
  * switch never 检查)与 contract-closure 构造冒烟(Record<AgentEventTypeName,…>
130
130
  * 漏键爆红)。不 bump 版本、不改任何引擎(演进政策 additive 面,判据全文见头注)。
131
131
  */
@@ -160,7 +160,7 @@ interface EngineHandleData {
160
160
  adapterVersion: string;
161
161
  }
162
162
  /**
163
- * [v1.x] 冷续 resume 锚点——EngineHandleData 定位键的投影子集(诊断字段
163
+ * [v1.x] 冷续 resume 锚点——EngineHandleData 定位键的派生子集(诊断字段
164
164
  * v/engineVersion/adapterVersion 不属锚点语义,不随锚点走)。消费点:
165
165
  * - run.params.resume(宿主 → 引擎:冷续重开已 idle 的 session,pi 消费
166
166
  * sessionRef.sessionFile —— 对照 core SpawnResumeOpts.sessionFile 的锚点面)。
@@ -199,7 +199,7 @@ interface SessionView {
199
199
  * 用户覆盖记账共用的模型指向形状(设计 subagent-model-switch §6.2/§7.3)。
200
200
  *
201
201
  * 刻意用结构化对象而非现役 wire 的字符串 canonical ref(`ctx.model` = "provider/id"):
202
- * 切换操作的原生输入面就是「provider 选了哪个模型」两个独立选择(前端模型选择器 /
202
+ * 切换操作的原生输入范围就是「provider 选了哪个模型」两个独立选择(前端模型选择器 /
203
203
  * runtime `model.switch` 均平铺 provider/modelId),字符串拼接形态会在协议两侧各做一次
204
204
  * 拆/拼(拆分规则 = provider 含 '/' 时无法无歧义反转),结构化形状让拆装只发生在宿主
205
205
  * 编排层单点(U2 组帧时拼 canonical ref、读回执时拆 ref)。
@@ -230,7 +230,7 @@ type EngineProcessModel = "per-window" | "shared-service";
230
230
  * 引擎能力声明(11 必填位 + 1 可选位 setModel)。三级:native / emulated / unsupported。
231
231
  * 声明的是本仓 subagent 链路实际接通的能力,不是引擎 RPC 层的理论能力。
232
232
  * 同步权威 = manifest(注册期直读);握手应答仅诊断(§3.3「同步成员清单」)。
233
- * 进程形态声明是独立字段(上方 EngineProcessModel——manifest 契约面,不在本
233
+ * 进程形态声明是独立字段(上方 EngineProcessModel——manifest 契约范围,不在本
234
234
  * 接口内),两套字段服务不同裁决(任务能力 vs 宿主实例管理)。
235
235
  */
236
236
  interface EngineCapabilities {
@@ -242,7 +242,7 @@ interface EngineCapabilities {
242
242
  * [H1 D5 语义收窄 + modeless] 「怎么续」形态轴兼 message 资格轴:
243
243
  * 位非 'unsupported' = 引擎可续聊(core capability-gate 的 message 资格门消费),
244
244
  * 值区分续聊形态——native(原地续写)/ cold(冷恢复重建 + 新 run + resume 锚点)。
245
- * 原名字沿用——conversation 位保留、语义从「interact 长驻控制面」收窄为
245
+ * 原名字沿用——conversation 位保留、语义从「interact 长驻控制范围」收窄为
246
246
  * 「resume 续聊能力」。[modeless 波2] 会话形态键只剩 run.params.resume(协议
247
247
  * task.conversation 已删),本轴不再是 per-run 模式开关——描述各引擎的真实
248
248
  * 续聊差异(gate 判据仍是 `=== "unsupported"` 拒绝,"cold" 与 "native" 等价
@@ -354,7 +354,7 @@ interface AgentOutcome {
354
354
  /** null = 被信号杀死(杀链/abort 合成终态的判据)。 */
355
355
  exitCode?: number | null;
356
356
  /**
357
- * [D5 诊断引用落账] 失败时子进程 stderr tee 文件绝对路径(引擎侧 W11 已有落盘)。
357
+ * [D5 诊断引用写入记录] 失败时子进程 stderr tee 文件绝对路径(引擎侧 W11 已有落盘)。
358
358
  *
359
359
  * 通道裁决(协议演进宪法 ADR-0071 判据链,2026-09-22 一致性审查 P1 修复登记):stderr
360
360
  * tee 路径是引擎产生的诊断事实,宿主不可靠推导(文件名格式/dataDir 解析/轮转
@@ -375,7 +375,7 @@ interface AgentOutcome {
375
375
  }
376
376
  /**
377
377
  * 引擎模型目录条目(manifest `modelCatalog.models` 条目形态,设计 §3.4 示例)。
378
- * 协议面 = initialize 应答 models? 与 listModels 应答 models 的元素型;
378
+ * 协议范围 = initialize 应答 models? 与 listModels 应答 models 的元素型;
379
379
  * manifest 解析与生成(gen:model-catalog)归 W4/W5 实装。
380
380
  */
381
381
  interface ModelCatalogEntry {
@@ -384,15 +384,15 @@ interface ModelCatalogEntry {
384
384
  canonicalRef?: string;
385
385
  }
386
386
  /**
387
- * 单次 agent 调用的任务声明——引擎面子集(协议 run.params.task;core 全量
388
- * AgentCallOpts 22 字段留 core,core 侧反向 re-export 保消费面)。
387
+ * 单次 agent 调用的任务声明——引擎侧子集(协议 run.params.task;core 全量
388
+ * AgentCallOpts 22 字段留 core,core 侧反向 re-export 保消费方)。
389
389
  *
390
390
  * 字段归属判据(协议演进宪法 ADR-0071 成文,权威源
391
391
  * docs/architecture/subagent-engine-protocolization.md §3.3「协议演进宪法」与
392
392
  * docs/adr/decisions.md ADR-0071;
393
- * 本注释是判据与存量结论的投影,新增字段按决策树依序裁决后在此登记):
393
+ * 本注释是判据与存量结论的派生整理,新增字段按决策树依序裁决后在此登记):
394
394
  * ① 引擎不消费它任务能否正确完成?能 → 宿主自持不上协议(「正确」含满足字段
395
- * 声明携带的约束面——轮次预算/超时等约束被引擎忽略即任务语义受损,视为消费);
395
+ * 声明携带的约束侧——轮次预算/超时等约束被引擎忽略即任务语义受损,视为消费);
396
396
  * ② 描述「任务是什么」(what) 还是「在什么环境跑/怎么跑」(where/how)?
397
397
  * what → task(预算/验收类约束 = 任务自带语义归 task,宿主偏好参数走③);
398
398
  * ③ 引擎能否自行推导该环境值且与宿主恒等?能 → 不上协议(推导权归引擎,设计期
package/dist/env.cjs CHANGED
@@ -94,8 +94,6 @@ var ENGINE_ENV_DENY_LIST = [
94
94
  "TAIJI_AGENT_PACKAGED",
95
95
  "TAIJI_RUNTIME_TOKEN",
96
96
  "TAIJI_AGENT_API_KEY",
97
- "TAIJI_SUBAGENT_RELAY_SESSION_ID",
98
- "TAIJI_SUBAGENT_RELAY_RECORD_ID",
99
97
  // 预设回落事实(env 名 SSOT = shared PRESET_FALLBACK_ENV_KEYS):「本进程本次运行」
100
98
  // 事实只对 runtime 直接 spawn 的 pi 成立,引擎一跳继承会造成子 agent pi 假披露
101
99
  "TAIJI_PRESET_FALLBACK_FROM",
@@ -106,9 +104,11 @@ var ENGINE_ENV_L0_INFRA_KEYS = [
106
104
  "TAIJI_AGENT_ENGINE_NODE",
107
105
  "ELECTRON_RUN_AS_NODE",
108
106
  "TAIJI_AGENT_SUBAGENT",
109
- "TAIJI_SUBAGENT_RELAY_SOCKET",
110
- "TAIJI_SUBAGENT_RELAY_NODE",
111
- "TAIJI_SUBAGENT_RELAY_SCRIPT"
107
+ // [M3] control 两键(键名 SSOT = src/control-env.ts):runtime 注入主 pi 与引擎的
108
+ // L0 基础设施键,嵌套 task pi 经引擎出站 env 继承同值。刻意不进 ENGINE_ENV_DENY_LIST:
109
+ // 引擎/嵌套 extension 是合法读者(transport 选择谓词 + engine_open 归属键)。
110
+ "TAIJI_SUBAGENT_CONTROL_SOCKET",
111
+ "TAIJI_SUBAGENT_CONTROL_ROOT_SESSION_ID"
112
112
  ];
113
113
  var ENV_PREFIX_SHAPE_RE = /^[A-Za-z0-9_]+$/;
114
114
  function deleteEnvKeysCaseInsensitive(env, names) {
@@ -162,11 +162,6 @@ function injectL0InfraKeys(env, opts) {
162
162
  if (opts.engineNode !== void 0) env.TAIJI_AGENT_ENGINE_NODE = opts.engineNode;
163
163
  if (opts.electronRunAsNode === true) env.ELECTRON_RUN_AS_NODE = "1";
164
164
  env.TAIJI_AGENT_SUBAGENT = "1";
165
- if (opts.relay !== void 0) {
166
- env.TAIJI_SUBAGENT_RELAY_SOCKET = opts.relay.socket;
167
- env.TAIJI_SUBAGENT_RELAY_NODE = opts.relay.node;
168
- env.TAIJI_SUBAGENT_RELAY_SCRIPT = opts.relay.script;
169
- }
170
165
  if (opts.identityEnv !== void 0) {
171
166
  for (const [key, value] of Object.entries(opts.identityEnv)) {
172
167
  if (value !== void 0) env[key] = value;
package/dist/env.d.cts CHANGED
@@ -1,18 +1,9 @@
1
1
  /** L2 manifest 放行的保留前缀拒绝表(镜像 shared SSOT,勿单独改动)。 */
2
2
  declare const ENGINE_ENV_PREFIXES: readonly string[];
3
- /** L1 deny + 显式剥除键集(镜像 shared SSOT,勿单独改动)。
4
- * 互引(场景域分化,勿互混):dev 装配器(apps/electron/scripts/dev-instance-lib.mjs
5
- * `LEAK_ENV_KEYS`)仍剥 RELAY_STD* 三键——dev 宿主进程环境防泄漏口径独立于引擎
6
- * spawn 面;本清单(引擎侧)已退役同名三键,写入方已清零。 */
3
+ /** L1 deny + 显式剥除键集(镜像 shared SSOT,勿单独改动)。 */
7
4
  declare const ENGINE_ENV_DENY_LIST: readonly string[];
8
- /** L0 注入的全部基础设施键(守卫断言:与 ENGINE_ENV_DENY_LIST 交集 = ∅)。 */
5
+ /** L0 注入的全部基础设施键(检查断言:与 ENGINE_ENV_DENY_LIST 交集 = ∅)。 */
9
6
  declare const ENGINE_ENV_L0_INFRA_KEYS: readonly string[];
10
- /** relay 三键形态(宿主 relay 激活时三值同时非空,全有或全无)。 */
11
- interface EngineRelayEnv {
12
- socket: string;
13
- node: string;
14
- script: string;
15
- }
16
7
  /** buildEngineChildEnv 入参。 */
17
8
  interface EngineChildEnvOptions {
18
9
  /** L0:引擎数据根(隔离库/池/journal 都相对它推导;缺 env 且无注入引擎侧须显式报错) */
@@ -21,8 +12,6 @@ interface EngineChildEnvOptions {
21
12
  engineNode?: string;
22
13
  /** L0:执行器为 Electron 二进制 → 注入 ELECTRON_RUN_AS_NODE=1 */
23
14
  electronRunAsNode?: boolean;
24
- /** L0:relay 三键(宿主 relay 激活时传;三键必经 L0——L1 拒绝 TAIJI_SUBAGENT_ 前缀、L2 是 manifest 面,两层都到不了) */
25
- relay?: EngineRelayEnv;
26
15
  /**
27
16
  * L0:引擎宿主(engine-host)进程的 env 透传通道。**注意它不是子代理身份通道**:
28
17
  * 引擎宿主是长驻进程(每窗口一个),而子代理身份(recordId / depth 等)是 per-run 的
@@ -46,9 +35,9 @@ interface EngineChildEnvOptions {
46
35
  *
47
36
  * 层规格(impl-plan §2.12 三层表):
48
37
  * - L0 基础设施键:TAIJI_AGENT_DATA_DIR / TAIJI_AGENT_ENGINE_NODE / ELECTRON_RUN_AS_NODE
49
- * (条件)/ TAIJI_AGENT_SUBAGENT=1 / relay 三键 / identityEnv(injectL0InfraKeys);
38
+ * (条件)/ TAIJI_AGENT_SUBAGENT=1 / identityEnv(injectL0InfraKeys);
50
39
  * - L1 deny + 显式剥除(恒高于 manifest 放行):ENGINE_ENV_DENY_LIST
51
- * (deny 两键 + 凭证键 + 父身份键 + 防御性剥除三死名);
40
+ * (deny 两键 + 凭证键 + 预设回落两键);
52
41
  * - L2 manifest 放行:envPrefixes 声明前缀的 processEnv 键(保留前缀拒绝、
53
42
  * 形态校验、未声明前缀不放行 + warn)(applyManifestAllowlist)。
54
43
  *
@@ -70,7 +59,7 @@ interface BuildOutboundChildEnvOptions {
70
59
  * 消费生命周期标志 / WS 令牌。
71
60
  *
72
61
  * 与 @taiji/shared 版 buildOutboundChildEnv 的刻意差异:**缺省不做白名单过滤**
73
- * (prefixes 省略 = 全量继承父 env + deny 剥除)。理由:SDK 消费面(zsw 宿主 /
62
+ * (prefixes 省略 = 全量继承父 env + deny 剥除)。理由:SDK 消费方(zsw 宿主 /
74
63
  * 引擎 CLI)不可 import shared 的 ENV_WHITELIST_PREFIXES;引擎 spawn 的基座由
75
64
  * 调用方先经 buildEngineChildEnv 组装(其 baseEnv 已是 core 过滤后的),而
76
65
  * ambient 场景(git 需要 GIT_* / proxy / ssh 等)必须保留继承面——deny-by-default
@@ -80,4 +69,4 @@ interface BuildOutboundChildEnvOptions {
80
69
  */
81
70
  declare function buildOutboundChildEnv(opts: BuildOutboundChildEnvOptions): Record<string, string>;
82
71
 
83
- export { type BuildOutboundChildEnvOptions, ENGINE_ENV_DENY_LIST, ENGINE_ENV_L0_INFRA_KEYS, ENGINE_ENV_PREFIXES, type EngineChildEnvOptions, type EngineRelayEnv, buildEngineChildEnv, buildOutboundChildEnv };
72
+ export { type BuildOutboundChildEnvOptions, ENGINE_ENV_DENY_LIST, ENGINE_ENV_L0_INFRA_KEYS, ENGINE_ENV_PREFIXES, type EngineChildEnvOptions, buildEngineChildEnv, buildOutboundChildEnv };