@zhushanwen/pi-subagent-workflow 9.4.1 → 9.5.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.
@@ -5,16 +5,18 @@
5
5
  // 闸。schema pattern(^/)经 pi agent-loop 运行时强校验已是强制(PS-20:
6
6
  // agent-loop.js:403-404 → validation.js:247-273),工具层守卫定位 = defense-in-depth
7
7
  // + schema 表达力缺口——`..` 穿越语义超出 pattern 能力(^/ 放行 "/a/../b"),
8
- // 守卫在 executeSubagent start 分支 immediate throw(与 action 枚举守卫同风格)。
8
+ // 守卫在 executeSubagentStart immediate throw(与 action 枚举守卫同风格)。
9
9
  //
10
10
  // 本文件锁住:
11
11
  // 1. skillPath / cwd 含 `..` 穿越段 → 同步 reject,service.execute 零触达
12
12
  // 2. skillPath / cwd 相对路径 → 同步 reject
13
13
  // 3. 合法绝对路径放行 → 参数原样透传 service.execute(守卫零误伤对照)
14
14
  //
15
- // harness([u-5b / A-V3] 改写):registerSubagentTool 后捕获 execute 回调直接调用。
15
+ // harness([u-5b / A-V3] 改写):registerSubagentTool 后按名捕获 subagent_start 的
16
+ // execute 回调直接调用(D3 拆分:registerSubagentTool 注册三工具,start 守卫在
17
+ // subagent_start 的 execute)。
16
18
  // SubagentService 经单例访问器槽注入 fake(setSubagentService,globalThis 槽——
17
- // executeSubagent 内 getSubagentService() 读同一槽,「守卫拒绝时 service.execute
19
+ // executeSubagentStart 内 getSubagentService() 读同一槽,「守卫拒绝时 service.execute
18
20
  // 零触达」的承重断言不依赖整类 mock);pi-ai/typebox 桩改共享桩
19
21
  // (src/__tests__/mocks/runtime-stubs.ts,async 工厂 + 动态 import,消费约定见
20
22
  // 桩 module 头注)。
@@ -59,22 +61,24 @@ function resetServiceSlot(): void {
59
61
 
60
62
  type ExecuteCb = (...args: unknown[]) => Promise<unknown>;
61
63
 
62
- /** 注册 tool 并捕获 execute 回调(sdk-contract 同款)。 */
63
- function captureExecute(): ExecuteCb {
64
+ /** 注册工具组并按名捕获 subagent_start 的 execute 回调。 */
65
+ function captureStartExecute(): ExecuteCb {
64
66
  let captured: ExecuteCb | undefined;
65
67
  const pi = mockExtensionApi({
66
68
  registerTool: (tool: unknown) => {
67
- captured = (tool as { execute: ExecuteCb }).execute;
69
+ if ((tool as { name?: string }).name === "subagent_start") {
70
+ captured = (tool as { execute: ExecuteCb }).execute;
71
+ }
68
72
  },
69
73
  });
70
74
  registerSubagentTool(pi);
71
- if (!captured) throw new Error("subagent tool not registered");
75
+ if (!captured) throw new Error("subagent_start tool not registered");
72
76
  return captured;
73
77
  }
74
78
 
75
- /** 合法 start 入参基线(守卫测试只变动 skillPath/cwd 字段)。 */
79
+ /** 合法 start 入参基线(守卫测试只变动 skillPath/cwd 字段;start 工具无 action 字段)。 */
76
80
  function baseParams(over: Record<string, unknown> = {}): Record<string, unknown> {
77
- return { action: "start", task: "guard task", slug: "path-guard", ...over };
81
+ return { task: "guard task", slug: "path-guard", ...over };
78
82
  }
79
83
 
80
84
  /** 合法 execute 返回值 stub(放行路径 adapter 包装用)。 */
@@ -87,15 +91,15 @@ function stubHandle() {
87
91
  };
88
92
  }
89
93
 
90
- describe("subagent tool 路径守卫(skillPath/cwd:绝对路径 + 禁 .. 穿越)", () => {
94
+ describe("subagent_start 路径守卫(skillPath/cwd:绝对路径 + 禁 .. 穿越)", () => {
91
95
  let execute: ExecuteCb;
92
96
 
93
97
  beforeEach(() => {
94
98
  vi.clearAllMocks();
95
99
  mockServiceExecute.mockResolvedValue(stubHandle());
96
- // 经真实单例访问器注入 fake service(executeSubagent 内 getSubagentService 读同槽)
100
+ // 经真实单例访问器注入 fake service(executeSubagentStart 内 getSubagentService 读同槽)
97
101
  setSubagentService({ execute: mockServiceExecute, getCollectSyncDefault: () => "async" } as never);
98
- execute = captureExecute();
102
+ execute = captureStartExecute();
99
103
  });
100
104
 
101
105
  afterEach(() => {