@zhushanwen/subagent-core 0.5.1 → 0.6.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.
- package/dist/execution/engine/engines/zcode/reader.d.cts +1 -1
- package/dist/execution/engine/engines/zcode/reader.d.ts +1 -1
- package/dist/index.cjs +1122 -452
- package/dist/index.d.cts +188 -5
- package/dist/index.d.ts +188 -5
- package/dist/index.js +1133 -463
- package/dist/{types-Dv4QhSJ_.d.cts → types-C3fE3R9x.d.cts} +65 -0
- package/dist/{types-Dv4QhSJ_.d.ts → types-C3fE3R9x.d.ts} +65 -0
- package/dist.bundle/index.cjs +34933 -0
- package/package.json +2 -2
- package/src/execution/__tests__/agent-registry.test.ts +1 -1
- package/src/execution/__tests__/alive-store.test.ts +1 -1
- package/src/execution/__tests__/collect-budget.test.ts +291 -0
- package/src/execution/__tests__/collect-coordinator-service.test.ts +327 -0
- package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
- package/src/execution/__tests__/collect-mixed-dispatch.test.ts +262 -0
- package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
- package/src/execution/__tests__/config.test.ts +1 -1
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +1 -1
- package/src/execution/__tests__/finalized-marker.test.ts +1 -1
- package/src/execution/__tests__/gc-timer.test.ts +1 -1
- package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
- package/src/execution/__tests__/notify-batch.test.ts +500 -0
- package/src/execution/__tests__/notify-ledger.test.ts +27 -0
- package/src/execution/__tests__/pi-invocation.test.ts +34 -2
- package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
- package/src/execution/__tests__/relay-env.test.ts +12 -1
- package/src/execution/__tests__/session-file-gc.test.ts +1 -1
- package/src/execution/__tests__/spawn-event-adapter.test.ts +2 -2
- package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
- package/src/execution/__tests__/start-sync-model-guard.test.ts +1 -1
- package/src/execution/__tests__/subagent-actions-core.test.ts +6 -0
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +13 -0
- package/src/execution/__tests__/sync-collect-recovery.test.ts +1117 -0
- package/src/execution/__tests__/tombstone-store.test.ts +1 -1
- package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
- package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
- package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
- package/src/execution/__tests__/worktree-registry.test.ts +1 -1
- package/src/execution/collect-coordinator.ts +200 -0
- package/src/execution/config.ts +77 -5
- package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
- package/src/execution/engine/__tests__/common/pool-manager.test.ts +2 -2
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +1 -1
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +1 -1
- package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +1 -1
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +1 -1
- package/src/execution/execution-record.ts +7 -0
- package/src/execution/finalize-record.ts +15 -11
- package/src/execution/notifier.ts +234 -25
- package/src/execution/notify-host.ts +21 -1
- package/src/execution/record-entry.ts +16 -0
- package/src/execution/record-store.ts +161 -30
- package/src/execution/subagent-actions-core.ts +62 -6
- package/src/execution/subagent-service.ts +416 -7
- package/src/execution/sync-rebuild.ts +87 -0
- package/src/execution/types.ts +63 -0
- package/src/index.ts +1 -1
- package/src/orchestration/__tests__/config-loader.test.ts +1 -1
- package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
- package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
- package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
- package/src/orchestration/__tests__/script-generate.test.ts +5 -5
- package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
- package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
- package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
- package/src/shared/__tests__/atomic-write.test.ts +1 -1
- package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
package/src/execution/types.ts
CHANGED
|
@@ -479,6 +479,14 @@ export interface ExecutionRecord {
|
|
|
479
479
|
* 回填(sessionFile 即定位符)。持久化经 subagent-record entry。
|
|
480
480
|
*/
|
|
481
481
|
engineHandle?: { sessionRef: Record<string, string>; journalPath?: string; poolKey: string };
|
|
482
|
+
/**
|
|
483
|
+
* 同步收集模式标记(subagent-sync-collect 设计 §3.1.3,U1 foundation 契约)。
|
|
484
|
+
* 创建时确定不可变;undefined = async(缺省语义,旧记录零迁移)。持久化经
|
|
485
|
+
* subagent-record entry(record-entry.ts 序列化白名单,entry 唯一写点)。
|
|
486
|
+
* 消费方:U2 collectCoordinator 路由(sync→批缓冲)、U5 E1 重建投影。
|
|
487
|
+
* U2 接线点:service.createRecordForMode 从 ExecuteOptions.collect 读入 identity。
|
|
488
|
+
*/
|
|
489
|
+
readonly collectMode?: "sync";
|
|
482
490
|
|
|
483
491
|
// ── 状态(实时更新)──
|
|
484
492
|
status: ExecutionStatus;
|
|
@@ -492,6 +500,13 @@ export interface ExecutionRecord {
|
|
|
492
500
|
* record 无此字段,投影层按 projectOutcome 兜底(closed-legacy 语义)。
|
|
493
501
|
*/
|
|
494
502
|
outcome?: ExecutionOutcome;
|
|
503
|
+
/**
|
|
504
|
+
* 离开批的终局标记(subagent-sync-collect 设计 §3.1.3,U1 foundation 契约)。
|
|
505
|
+
* 两出口统一落标:① 批闭合 flush 写账成功后;② E9 dispose 逐条转 async 写账后
|
|
506
|
+
* (均 appendEntry 持久化,U3/U5 写点)。undefined = 未离开批 / 旧记录零迁移。
|
|
507
|
+
* 消费方:U5 E1 重建扫描只收「collectMode=sync 且无本标记」的成员(防双重通知)。
|
|
508
|
+
*/
|
|
509
|
+
batchFinalized?: boolean;
|
|
495
510
|
/** 完整执行内容,按 turn 组织。createRecord 初始化为 [空 turn]。 */
|
|
496
511
|
turns: Turn[];
|
|
497
512
|
/** turn 计数(= turns.filter(closed).length,冗余存储供投影直接读)。 */
|
|
@@ -676,6 +691,17 @@ export interface ExecuteOptions {
|
|
|
676
691
|
* undefined/false = 一次性模式(默认,行为完全不变)。service.execute 透传到 createRecordForMode。
|
|
677
692
|
*/
|
|
678
693
|
conversation?: boolean;
|
|
694
|
+
/**
|
|
695
|
+
* 同步收集模式(subagent-sync-collect 设计 §3.1.3,U1 foundation 契约)。
|
|
696
|
+
* undefined = config collectSync.default(缺省 "async",新 session 生效)。
|
|
697
|
+
* schema 层枚举限 "async"|"sync";运行时宽收 string 与 engine 字段同风格
|
|
698
|
+
* (非法值 ≠ "sync" 按 async 处理)。
|
|
699
|
+
* "sync" + conversation:true 组合在 startHandler E4 校验即拒
|
|
700
|
+
* (immediate throw,不产生半启动 record)。
|
|
701
|
+
* U2 接线点:service.createRecordForMode 读入 createRecord identity.collectMode
|
|
702
|
+
* (U1 打通类型与 startHandler 透传,record 落点归 U2)。
|
|
703
|
+
*/
|
|
704
|
+
collect?: string;
|
|
679
705
|
/**
|
|
680
706
|
* 空闲超时毫秒数(仅 conversation 模式有意义)。覆盖默认 5min idle timeout。
|
|
681
707
|
* 优先级:参数 > env XYZ_SUBAGENT_IDLE_TIMEOUT_MS > 默认 300000ms。
|
|
@@ -764,6 +790,13 @@ export interface BgResponse {
|
|
|
764
790
|
* 值语义由 U2(execution/notify-ledger.ts)兑现。
|
|
765
791
|
*/
|
|
766
792
|
notifyContract: "ledger+at-least-once";
|
|
793
|
+
/**
|
|
794
|
+
* 同步收集登记回显段(subagent-sync-collect 设计 §3.1.1 交互样例,U1 foundation)。
|
|
795
|
+
* 仅 resolved 模式为 sync 时附带(async 响应字节零变化,G3):mode = 生效模式;
|
|
796
|
+
* pendingSyncCount = 当前未闭合批的 sync 成员总数(含本条;跨轮派发续累不重置,
|
|
797
|
+
* 与 D2 隐式批一致)。
|
|
798
|
+
*/
|
|
799
|
+
collect?: { mode: "sync"; pendingSyncCount: number };
|
|
767
800
|
}
|
|
768
801
|
|
|
769
802
|
/** list 的内层响应(挂在 SubagentToolResult.listResponse)。 */
|
|
@@ -902,12 +935,37 @@ export interface SubagentRecord {
|
|
|
902
935
|
* subagent-engine-history);缺省 = pi(走 JSONL 直读链)。
|
|
903
936
|
*/
|
|
904
937
|
engineHandle?: { sessionRef: Record<string, string>; journalPath?: string; poolKey: string };
|
|
938
|
+
/**
|
|
939
|
+
* 同步收集模式标记(与 ExecutionRecord.collectMode 同源投影/重建,U1 foundation)。
|
|
940
|
+
* 缺省(存量 record)= async 投影,消费方零迁移。
|
|
941
|
+
*/
|
|
942
|
+
collectMode?: "sync";
|
|
943
|
+
/**
|
|
944
|
+
* 离开批终局标记(与 ExecutionRecord.batchFinalized 同源投影/重建,U1 foundation)。
|
|
945
|
+
* 缺省 = 未离开批;U5 E1 重建扫描据此排除已离场成员。
|
|
946
|
+
*/
|
|
947
|
+
batchFinalized?: boolean;
|
|
905
948
|
}
|
|
906
949
|
|
|
907
950
|
// ============================================================
|
|
908
951
|
// 配置(global + session)
|
|
909
952
|
// ============================================================
|
|
910
953
|
|
|
954
|
+
/**
|
|
955
|
+
* 同步收集(sync collect)配置节类型(subagent-sync-collect 设计 §3.1.3,U1 foundation)。
|
|
956
|
+
* 权威默认值在 config.ts DEFAULT_COLLECT_SYNC;坏值 sanitize 回默认不炸启动(E5,
|
|
957
|
+
* 与 maxConcurrent 同判)。类型定义于 types.ts(避免 config → types 反向依赖成环),
|
|
958
|
+
* config.ts re-export。
|
|
959
|
+
*/
|
|
960
|
+
export interface CollectSyncConfig {
|
|
961
|
+
/** start 未显式传 collect 时的缺省模式。新 session 生效(与 engine 配置时机一致)。 */
|
|
962
|
+
default: "async" | "sync";
|
|
963
|
+
/** 批通知单条目结果正文预算(字符):超出截断并接 session_read 指针行。flush 时热读。 */
|
|
964
|
+
perItemChars: number;
|
|
965
|
+
/** 批通知结果正文总量预算(字符):Σ 超限时统一收紧 effectivePerItem(U4 算法)。flush 时热读。 */
|
|
966
|
+
totalChars: number;
|
|
967
|
+
}
|
|
968
|
+
|
|
911
969
|
/**
|
|
912
970
|
* 全局配置(~/.pi/agent/subagents/config.json)。
|
|
913
971
|
*
|
|
@@ -925,6 +983,11 @@ export interface SubagentsGlobalConfig {
|
|
|
925
983
|
defaultEngine?: string;
|
|
926
984
|
/** 引擎路由策略(D9①):strict=true 时一切 probe 失败直接报错(不 fallback)。 */
|
|
927
985
|
engineRouting?: { strict: boolean };
|
|
986
|
+
/**
|
|
987
|
+
* 同步收集配置节(subagent-sync-collect 设计 §3.1.3,U1 foundation)。
|
|
988
|
+
* 整节缺省 = DEFAULT_COLLECT_SYNC(config.ts);逐字段 sanitize 回默认(E5)。
|
|
989
|
+
*/
|
|
990
|
+
collectSync?: CollectSyncConfig;
|
|
928
991
|
}
|
|
929
992
|
|
|
930
993
|
// ============================================================
|
package/src/index.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
// 0.4.0 = 首个公开发布的收敛收口面(0.3.0 为 2026-08-30 裁决的跳号占位,永不单独
|
|
25
25
|
// 发布;+ minor changeset 收口面落本号);与 package.json version 的一致性由
|
|
26
26
|
// src/__tests__/smoke.test.ts 动态守护,改版本须两处同步。
|
|
27
|
-
export const CORE_PACKAGE_VERSION = "0.
|
|
27
|
+
export const CORE_PACKAGE_VERSION = "0.6.0";
|
|
28
28
|
|
|
29
29
|
// ── 宿主端口接线面(core/)────────────────────────────────────
|
|
30
30
|
// HostServices:dataRoot / log / discoveryRoots 端口 + configureCore 注入;
|
|
@@ -102,7 +102,7 @@ beforeEach(async () => {
|
|
|
102
102
|
|
|
103
103
|
afterEach(async () => {
|
|
104
104
|
vi.useRealTimers();
|
|
105
|
-
if (ws) await rm(ws.root, { recursive: true, force: true });
|
|
105
|
+
if (ws) await rm(ws.root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
/** 过滤掉可能从真实 homedir 泄漏进来的 user-agents 文件,只保留临时工作区内结果。 */
|
|
@@ -39,7 +39,7 @@ beforeEach(() => {
|
|
|
39
39
|
afterEach(() => {
|
|
40
40
|
vi.useRealTimers();
|
|
41
41
|
resetCoreForTests();
|
|
42
|
-
rmSync(dataRoot, { recursive: true, force: true });
|
|
42
|
+
rmSync(dataRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
/** 构造可持久化的 WorkflowRun(对齐 file-run-store.test.ts makeRun 模式)。 */
|
|
@@ -67,7 +67,7 @@ beforeEach(() => {
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
afterEach(() => {
|
|
70
|
-
rmSync(sandboxDir, { recursive: true, force: true });
|
|
70
|
+
rmSync(sandboxDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
/** cwd 植入件:若任一脚本回退 process.cwd() 加载依赖,本文件被 require 即抛标记错误。 */
|
|
@@ -168,7 +168,7 @@ describe("generateWorkflowScript 校验闸(文案逐字对齐 pi 现版)", (
|
|
|
168
168
|
);
|
|
169
169
|
expect(existsSync(join(tmpRoot, "esm-wf.js"))).toBe(false);
|
|
170
170
|
} finally {
|
|
171
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
171
|
+
rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
172
172
|
}
|
|
173
173
|
});
|
|
174
174
|
|
|
@@ -216,7 +216,7 @@ describe("generateWorkflowScript 校验闸(文案逐字对齐 pi 现版)", (
|
|
|
216
216
|
}
|
|
217
217
|
expect(existsSync(join(tmpRoot, "bad-wf.js"))).toBe(false);
|
|
218
218
|
} finally {
|
|
219
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
219
|
+
rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
220
220
|
}
|
|
221
221
|
});
|
|
222
222
|
|
|
@@ -247,7 +247,7 @@ describe("generateWorkflowScript 合法样本落 tmp", () => {
|
|
|
247
247
|
expect(existsSync(r.path)).toBe(true);
|
|
248
248
|
expect(readFileSync(r.path, "utf-8")).toBe(PI_META_VALID);
|
|
249
249
|
} finally {
|
|
250
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
250
|
+
rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
251
251
|
}
|
|
252
252
|
});
|
|
253
253
|
|
|
@@ -259,7 +259,7 @@ describe("generateWorkflowScript 合法样本落 tmp", () => {
|
|
|
259
259
|
if (!r.ok) throw new Error(r.error);
|
|
260
260
|
expect(existsSync(r.path)).toBe(true);
|
|
261
261
|
} finally {
|
|
262
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
262
|
+
rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
263
263
|
}
|
|
264
264
|
});
|
|
265
265
|
|
|
@@ -274,7 +274,7 @@ describe("generateWorkflowScript 合法样本落 tmp", () => {
|
|
|
274
274
|
expect(existsSync(r.path)).toBe(true);
|
|
275
275
|
} finally {
|
|
276
276
|
cwdSpy.mockRestore();
|
|
277
|
-
rmSync(fakeCwd, { recursive: true, force: true });
|
|
277
|
+
rmSync(fakeCwd, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
278
278
|
}
|
|
279
279
|
});
|
|
280
280
|
});
|
|
@@ -73,8 +73,8 @@ beforeEach(() => {
|
|
|
73
73
|
afterEach(() => {
|
|
74
74
|
vi.restoreAllMocks();
|
|
75
75
|
resetCoreForTests();
|
|
76
|
-
rmSync(projRoot, { recursive: true, force: true });
|
|
77
|
-
rmSync(homeRoot, { recursive: true, force: true });
|
|
76
|
+
rmSync(projRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
77
|
+
rmSync(homeRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
/** mkdir -p(目录存在即 resolveSkillPath 命中——检查的是目录而非 SKILL.md)。 */
|
|
@@ -43,7 +43,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
43
43
|
expect(existsSync(join(tmpDir, "alpha.js"))).toBe(false);
|
|
44
44
|
expect(readFileSync(join(savedDir, "alpha.js"), "utf-8")).toBe("// alpha body");
|
|
45
45
|
} finally {
|
|
46
|
-
rmSync(root, { recursive: true, force: true });
|
|
46
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
49
|
|
|
@@ -56,7 +56,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
56
56
|
expect(existsSync(join(savedDir, "alpha.js"))).toBe(false);
|
|
57
57
|
expect(existsSync(join(savedDir, "beta.js"))).toBe(true);
|
|
58
58
|
} finally {
|
|
59
|
-
rmSync(root, { recursive: true, force: true });
|
|
59
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
62
|
|
|
@@ -72,7 +72,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
72
72
|
// 原文件不动
|
|
73
73
|
expect(existsSync(join(tmpDir, "alpha.js"))).toBe(true);
|
|
74
74
|
} finally {
|
|
75
|
-
rmSync(root, { recursive: true, force: true });
|
|
75
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
78
|
|
|
@@ -83,7 +83,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
83
83
|
"Temporary workflow 'ghost' not found",
|
|
84
84
|
);
|
|
85
85
|
} finally {
|
|
86
|
-
rmSync(root, { recursive: true, force: true });
|
|
86
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
89
|
});
|
|
@@ -104,7 +104,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
104
104
|
expect(existsSync(join(tmpDir, "dup.js"))).toBe(false);
|
|
105
105
|
expect(existsSync(join(savedDir, "dup.js"))).toBe(true);
|
|
106
106
|
} finally {
|
|
107
|
-
rmSync(root, { recursive: true, force: true });
|
|
107
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
108
108
|
}
|
|
109
109
|
});
|
|
110
110
|
|
|
@@ -117,7 +117,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
117
117
|
expect(msg).toBe(`Deleted workflow 'gamma' (${join(savedDir, "gamma.js")})`);
|
|
118
118
|
expect(existsSync(join(savedDir, "gamma.js"))).toBe(false);
|
|
119
119
|
} finally {
|
|
120
|
-
rmSync(root, { recursive: true, force: true });
|
|
120
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
123
|
|
|
@@ -130,7 +130,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
130
130
|
).toThrow("Cannot delete 'busy': workflow is currently running. Abort it first.");
|
|
131
131
|
expect(existsSync(join(tmpDir, "busy.js"))).toBe(true);
|
|
132
132
|
} finally {
|
|
133
|
-
rmSync(root, { recursive: true, force: true });
|
|
133
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
136
|
|
|
@@ -141,7 +141,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
141
141
|
"Workflow file 'void' not found",
|
|
142
142
|
);
|
|
143
143
|
} finally {
|
|
144
|
-
rmSync(root, { recursive: true, force: true });
|
|
144
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
145
145
|
}
|
|
146
146
|
});
|
|
147
147
|
});
|
|
@@ -164,7 +164,7 @@ describe("缺省目录 = pi 布局(向后兼容回归)", () => {
|
|
|
164
164
|
expect(existsSync(join(fakeCwd, ".pi", "workflows", "pi-wf.js"))).toBe(true);
|
|
165
165
|
} finally {
|
|
166
166
|
cwdSpy.mockRestore();
|
|
167
|
-
rmSync(fakeCwd, { recursive: true, force: true });
|
|
167
|
+
rmSync(fakeCwd, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
168
168
|
}
|
|
169
169
|
});
|
|
170
170
|
|
|
@@ -180,7 +180,7 @@ describe("缺省目录 = pi 布局(向后兼容回归)", () => {
|
|
|
180
180
|
expect(existsSync(join(savedDir, "saved-only.js"))).toBe(false);
|
|
181
181
|
} finally {
|
|
182
182
|
cwdSpy.mockRestore();
|
|
183
|
-
rmSync(fakeCwd, { recursive: true, force: true });
|
|
183
|
+
rmSync(fakeCwd, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
184
184
|
}
|
|
185
185
|
});
|
|
186
186
|
});
|
|
@@ -59,7 +59,7 @@ describe("loadWorkflowScriptByPath / WorkflowScript 导出形态(U1)", () =>
|
|
|
59
59
|
afterEach(async () => {
|
|
60
60
|
invalidateCache();
|
|
61
61
|
for (const dir of tempDirs) {
|
|
62
|
-
await rm(dir, { recursive: true, force: true });
|
|
62
|
+
await rm(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
|
|
@@ -74,7 +74,7 @@ describe("C2 W2①: async 链 realpath 去重", () => {
|
|
|
74
74
|
ws = tmpWorkspace();
|
|
75
75
|
});
|
|
76
76
|
afterEach(() => {
|
|
77
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
77
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
it("多链同文件(a.md 本体 + b.md symlink → a.md)清单只留 1 条", async () => {
|
|
@@ -171,7 +171,7 @@ describe("C2 W2④: hostRoots 同标签多根语义", () => {
|
|
|
171
171
|
agentDir = path.join(ws, ".fake-agent");
|
|
172
172
|
});
|
|
173
173
|
afterEach(() => {
|
|
174
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
174
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
175
175
|
});
|
|
176
176
|
|
|
177
177
|
it("同标签两条 user-pi 根都被扫描(非靠后者整体覆盖)", async () => {
|
|
@@ -300,7 +300,7 @@ describe("C2 W2②: project-host 槽位序位", () => {
|
|
|
300
300
|
hostRoot = path.join(ws, ".zcode", "agents");
|
|
301
301
|
});
|
|
302
302
|
afterEach(() => {
|
|
303
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
303
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
304
304
|
});
|
|
305
305
|
|
|
306
306
|
it("project-host 同名被 project-agents 遮蔽(project-agents 是项目级最高逃生门)", async () => {
|
|
@@ -364,7 +364,7 @@ describe("C2 红线 3: 单层扫描维持", () => {
|
|
|
364
364
|
agentDir = path.join(ws, ".fake-agent");
|
|
365
365
|
});
|
|
366
366
|
afterEach(() => {
|
|
367
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
367
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
368
368
|
});
|
|
369
369
|
|
|
370
370
|
it("子目录不递归(nested/deep.md 不入清单)", async () => {
|
|
@@ -410,7 +410,7 @@ describe("C2 回归红线: pi 单条目形态快照", () => {
|
|
|
410
410
|
agentDir = path.join(ws, ".fake-agent");
|
|
411
411
|
});
|
|
412
412
|
afterEach(() => {
|
|
413
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
413
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
414
414
|
});
|
|
415
415
|
|
|
416
416
|
it("与 pi 真实 agentDir 同构 fixture——source 标签与胜出路径逐项稳定", async () => {
|