@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
@@ -69,6 +69,13 @@ const { loggerMock } = vi.hoisted(() => ({
69
69
  // 经 ../core/logger.ts 引用的同一模块)。曾写 ../core/logger.ts 指向不存在的
70
70
  // src/execution/core/,vi.mock 静默失效(D4 上限用例首次断言日志时暴露)。
71
71
  vi.mock("../../core/logger.ts", () => ({ getLogger: () => loggerMock }));
72
+ // [U3 适配] RecordStore 构造点接线 manifestDir 后,markBatchFinalized 的 manifest 面走
73
+ // writeAtomicFileSync 同步写(不再经 manifestStore.writeManifest)——屏障失败注入面
74
+ // 随之迁移到本模块(默认透传真实现,仅「屏障失败」用例内 mockImplementationOnce)。
75
+ vi.mock("../../shared/atomic-write.ts", async (importOriginal) => {
76
+ const actual = await importOriginal<typeof import("../../shared/atomic-write.ts")>();
77
+ return { ...actual, writeAtomicFileSync: vi.fn(actual.writeAtomicFileSync) };
78
+ });
72
79
 
73
80
  // [W3 改写] mock session-runner(execute 链 runSpawn 替身)随 inproc pi 引擎目录 删除消亡——
74
81
  // execute 链改为协议 seam(registerFakePiEngine 替身 + 显式 settle 应答)。
@@ -83,6 +90,7 @@ import { getSubagentRecordsDir, getSubagentSessionDir } from "../path-encoding.t
83
90
  import { RecordStore } from "../record-store.ts";
84
91
  import type { SubagentRecord } from "../types.ts";
85
92
  import { SubagentService } from "../subagent-service.ts";
93
+ import { writeAtomicFileSync } from "../../shared/atomic-write.ts";
86
94
 
87
95
  /** 剥身份/relay env:身份 env 会让 service 误判自己是子进程(跳过恢复扫描),
88
96
  * relay env 属 pi-invocation/relay-env 存量测试的敏感面(测试纪律:env 剥离)。 */
@@ -295,7 +303,7 @@ describe("sync collect recovery (U5 E1/E9) — 真实文件通路", () => {
295
303
  }
296
304
 
297
305
  /** 在 sessionsDir 手工构造子 session 文件(session 头 + identity entry + 末行完整
298
- * JSON record entry,E9 用例同款形态)且**不写** `.finalized`/`.cancelled`/`.alive`
306
+ * JSON record entry,E9 用例同款形态)且**不写** `.state`/`.alive`
299
307
  * 三 sidecar——重建矩阵分支 4 命中条件,保证 orphan 恢复走 finalizeOrphanRecord
300
308
  * 真实路径(entry-born 兜底测不到 D3 merge 所在路径 = 假绿)。
301
309
  * identity 含 reconstructAll 过滤必需字段:id/agent/task string + mode 枚举 +
@@ -462,34 +470,33 @@ describe("sync collect recovery (U5 E1/E9) — 真实文件通路", () => {
462
470
  expect(marks.map((m) => m.id).sort()).toEqual(["sa-a", "sa-b"]);
463
471
  });
464
472
 
465
- it("屏障失败 warn 留痕(D6 #7a/SC-1):manifest 写失败不阻断补发,warn 含成员 id 与 manifest 路径", async () => {
473
+ it("屏障失败 warn 留痕(D6 #7a/SC-1):manifest 同步写失败不阻断补发,warn 含成员 id(U1 同步分支形态)", async () => {
466
474
  const childFile = writeChildSessionFile("sa-bar-fail", "barrier fail task");
467
475
  seedRoundTerminalEntries("sa-bar-fail", childFile, "barrier result", "prov/bar-m", "sync");
468
476
 
469
477
  const recovery = makeRecoveryService(makeAssertPi());
470
478
  const spy = spyNotifier(recovery);
471
479
  loggerMock.warn.mockClear(); // logger 模块级共享,计数从本用例起算
472
- // 私有 manifestStore 打桩(TS private 仅编译期可见性):单成员写失败(EACCES 类),
473
- // 屏障 allSettled 语义 = 不阻断写账投递
474
- const internal = recovery as unknown as {
475
- manifestStore: { writeManifest: (r: { id: string }) => Promise<void> };
476
- };
477
- vi.spyOn(internal.manifestStore, "writeManifest").mockRejectedValueOnce(
478
- Object.assign(new Error("EACCES: permission denied"), { code: "EACCES" }),
479
- );
480
+ // [U3 适配] 构造点接线 manifestDir 后屏障走 writeAtomicFileSync 同步分支——失败
481
+ // 注入面从 manifestStore.writeManifest(异步降级分支打桩)迁至原子写模块。单成员
482
+ // = 单次调用,mockImplementationOnce 恰好命中;同步分支 try/catch 吞错 =
483
+ // 不阻断落标/写账投递(best-effort 与旧 allSettled 同源)。
484
+ vi.mocked(writeAtomicFileSync).mockImplementationOnce(() => {
485
+ throw Object.assign(new Error("EACCES: permission denied"), { code: "EACCES" });
486
+ });
480
487
 
481
488
  await recovery.recoverSyncCollectBatch();
482
489
 
483
490
  // best-effort 语义:写账照常推进(反查索引缺失只影响指针行反查,不构成写账失败)
484
491
  expect(spy.notifyBatch).toHaveBeenCalledTimes(1);
485
- // D6 #7a:原 debug 级排障不可见 warn,且含成员 id + manifest 路径两个定位线索
486
- const manifestFile = path.join(getSubagentRecordsDir(agentDir, agentDir), "sa-bar-fail.json");
492
+ // D6 #7a 适配(U1 同步分支 warn 形态):message sync write failed 语义 +
493
+ // detail.id 定位成员(manifest 路径由 recordsDir/<id>.json 推导——异步分支的
494
+ // 路径直书线索未纳入 U1 同步分支实装,按现行为断言)。
487
495
  const barrierWarns = loggerMock.warn.mock.calls.filter((c) =>
488
- String(c[0]).startsWith("[subagents] batch-finalized manifest write failed"),
496
+ String(c[0]).startsWith("[subagents] batch-finalized manifest sync write failed"),
489
497
  );
490
498
  expect(barrierWarns).toHaveLength(1);
491
- expect(String(barrierWarns[0]![0])).toContain("record=sa-bar-fail");
492
- expect(String(barrierWarns[0]![0])).toContain(manifestFile);
499
+ expect((barrierWarns[0]![1] as { detail?: { id?: string } }).detail?.id).toBe("sa-bar-fail");
493
500
  });
494
501
 
495
502
  it("E1 幂等窗口:账本同 hash 拒绝(accepted=false)也统一补标 → 标记落盘后二次恢复零补发", async () => {
@@ -662,7 +669,7 @@ describe("sync collect recovery (U5 E1/E9) — 真实文件通路", () => {
662
669
  expect(overwritten.result).toBe("kill-9 full result body");
663
670
  expect(overwritten.model).toBe("prov/round-m");
664
671
  // 防重锚落盘(覆写已判终态,二次重启不再进判定)
665
- expect(fs.existsSync(`${childFile}.finalized`)).toBe(true);
672
+ expect(fs.existsSync(`${childFile}.state`)).toBe(true);
666
673
 
667
674
  // ── E1 真实跑:末条(覆写后 closed entry)候选命中 → 补发 + 落标 ──
668
675
  const spy = spyNotifier(recovery);
@@ -0,0 +1,79 @@
1
+ // src/execution/__tests__/terminal-write-latency.test.ts
2
+ //
3
+ // [H4 / D2 / 待验证检查点①] 终态原语同步写时延实测(vitest 内采样,非 bench 文件):
4
+ // markFinalized 的持久化面 = `.state` writeSync + manifest writeSync(D8 v7 双写),
5
+ // D2 重审阈值 = 终态路径 P99 增量 > 10ms(超限方向 = 降级「shutdown 前 flush 批量
6
+ // 同步写」,设计 §3.3 D2)。本测试在真实 mkdtemp 目录采样 N=100 次,断言 P99 <
7
+ // 10ms;实测数字经 console.info 落测试输出,供 H4 文档回写登记。
8
+
9
+ import * as fs from "node:fs";
10
+ import * as os from "node:os";
11
+ import * as path from "node:path";
12
+ import { performance } from "node:perf_hooks";
13
+
14
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
15
+
16
+ import { createRecord } from "../execution-record.ts";
17
+ import { ManifestStore } from "../manifest-store.ts";
18
+ import { RecordStore } from "../record-store.ts";
19
+
20
+ /** 采样次数(D2 口径 N=100)。 */
21
+ const SAMPLE_COUNT = 100;
22
+ /** D2 重审阈值(ms):终态路径 P99 超此值触发设计重审。 */
23
+ const D2_P99_THRESHOLD_MS = 10;
24
+
25
+ describe("D2 时延实测:markFinalized 终态同步双写", () => {
26
+ let tmpDir: string;
27
+ let recordsDir: string;
28
+ let store: RecordStore;
29
+
30
+ beforeEach(() => {
31
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "terminal-latency-"));
32
+ recordsDir = path.join(tmpDir, "records");
33
+ // 生产形态全接线:manifestStore 与 manifestDir(同步写通道,D8 v7)同源同目录。
34
+ store = new RecordStore(
35
+ tmpDir,
36
+ new ManifestStore(recordsDir),
37
+ { appendEntry: () => {} },
38
+ recordsDir,
39
+ );
40
+ });
41
+
42
+ afterEach(() => {
43
+ fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
44
+ });
45
+
46
+ it(`.state + manifest 双写 P99 < ${D2_P99_THRESHOLD_MS}ms(N=${SAMPLE_COUNT},真实磁盘)`, () => {
47
+ const sessionFile = path.join(tmpDir, "session.jsonl");
48
+ fs.writeFileSync(sessionFile, "{}\n", "utf-8");
49
+ const samples: number[] = [];
50
+ for (let i = 0; i < SAMPLE_COUNT; i++) {
51
+ const record = createRecord(`sa-latency-${i}`, {
52
+ agent: "general-purpose",
53
+ model: "test/model",
54
+ mode: "background",
55
+ slug: "t",
56
+ task: "latency probe",
57
+ startedAt: 1000,
58
+ rootSessionId: "root",
59
+ });
60
+ record.sessionFile = sessionFile;
61
+ store.register(record);
62
+ const t0 = performance.now();
63
+ const persisted = store.markFinalized(record, "gc");
64
+ const t1 = performance.now();
65
+ expect(persisted).toBe(true);
66
+ samples.push(t1 - t0);
67
+ }
68
+ samples.sort((a, b) => a - b);
69
+ const p50 = samples[Math.floor(SAMPLE_COUNT * 0.5)]!;
70
+ const p99 = samples[Math.ceil(SAMPLE_COUNT * 0.99) - 1]!;
71
+ const max = samples[SAMPLE_COUNT - 1]!;
72
+ // eslint 基建:__tests__ 豁免 no-console(测试基建通道,非生产源码)。
73
+ console.info(
74
+ `[D2 latency] markFinalized N=${SAMPLE_COUNT}: p50=${p50.toFixed(3)}ms ` +
75
+ `p99=${p99.toFixed(3)}ms max=${max.toFixed(3)}ms (threshold ${D2_P99_THRESHOLD_MS}ms, D8 v7 .state+manifest 双写)`,
76
+ );
77
+ expect(p99).toBeLessThan(D2_P99_THRESHOLD_MS);
78
+ });
79
+ });