Skip to content

Commit 19438b3

Browse files
author
王璨
committed
fix: replace __DEFERRED_HINT__ placeholder in system prompt during initialize and after MCP connect
fix(system-prompt): clarify Tool Use Rules — parallel execution, file tool preference, discoverable tools
1 parent 7cfc35d commit 19438b3

12 files changed

Lines changed: 239 additions & 4 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-06-09
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
## Context
2+
3+
系统提示词的 `## Rules` 子章节(`# Tool Use` 下)定义了 Agent 的工具调用行为规则。当前 5 条规则,三个缺口:
4+
5+
1. "execute them one by one" — 与系统支持同一响应中多个 tool call 的实际能力冲突
6+
2. 没有明确文件工具(write_file/edit/read_file)优先于 bash — Agent 可能滥用 sed/cat 操作项目文件
7+
3. 没有要求使用 Skill 前必须 `skill` 激活 — Skill 列表列出但 Agent 可能跳过激活直接干活
8+
9+
约束:改动仅限于系统提示词文本,不涉及任何代码、API、或模块逻辑变更。
10+
11+
## Goals / Non-Goals
12+
13+
**Goals:**
14+
- 将并行化规则写入 Rules,消除 "one by one" 与实际能力的矛盾
15+
- 明确文件工具 > bash 的优先级,减少用 bash 操作文件的风险
16+
- 将 Skill 激活纳入强制性规则
17+
18+
**Non-Goals:**
19+
- 不改变 Tool Use 的章节结构(仍是 `## Rules` + `## Tool Search`
20+
- 不改变 Skills 章节
21+
- 不改变非 Rules 部分的任何内容
22+
- 不引入新的工具或 API
23+
24+
## Decisions
25+
26+
### 并行化表述:独立批量 vs 严格逐个
27+
28+
| 方案 | 描述 |
29+
|------|------|
30+
| A: "execute them one by one" | 当前,强制串行 |
31+
| B: "parallelize independent calls, sequence dependent ones" | **采用** |
32+
33+
理由:方案 B 匹配系统实际能力。一条读文件和另一条读文件无依赖 → 同轮发出。读后编辑有依赖 → 分轮。用「batch in a single response」「sequence across separate responses」明确语义。
34+
35+
### 文件工具偏好:明确列举 vs 笼统说"用安全工具"
36+
37+
| 方案 | 描述 |
38+
|------|------|
39+
| A: "prefer safe file tools" | 太模糊,Agent 不知道哪些是安全的 |
40+
| B: 明确列举 write_file / edit / read_file / grep,禁止 sed / cat / awk | **采用** |
41+
42+
理由:方案 B 给白名单也让 Agent 知道具体禁止什么。同时明确 bash 保留用途(tests, builds, git, package management),避免过度禁止。
43+
44+
### Skill 激活规则位置:放在 Rules vs 放在 Skills 章节
45+
46+
| 方案 | 描述 |
47+
|------|------|
48+
| A: 放在 `## Rules` | 作为强制性行为规则 |
49+
| B: 放在 `# Skills``## Using Skills` | 放在使用说明区 |
50+
51+
理由:采用方案 A。`## Rules` 是行为契约,Skill 激活是一项行为约束(「必须先激活再执行」),放在 Rules 比其他 Agent 更容易遵守。
52+
53+
## Risks / Trade-offs
54+
55+
- [风险] 并行化规则可能被过度解读,Agent 可能强行并行有隐式依赖的调用 → 缓解:措辞强调 "no mutual dependency"
56+
- [风险] 过度限制 bash 可能让 Agent 在需要快速文件操作时效率下降 → 缓解:明确保留 bash 的合法用途列表,写上 "not sed, cat, or awk on project files" 而非 "never use bash for files"
57+
- [风险] Skill 激活规则可能被忽略(Agent 有时不读完整 Rules)→ 缓解:放在 Rules 前列,紧接在并行化和文件工具偏好之后
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## Why
2+
3+
系统提示词 `## Rules` 子章节存在三条规则缺失:未说明独立 tool call 可并行执行("execute them one by one" 与实际能力矛盾)、未明确文件工具优先于 bash、未要求使用 Skill 前先激活。修正这三个缺口,可减少无效轮次、提升文件操作安全性、保障 Skill 执行质量。
4+
5+
## What Changes
6+
7+
- 将「execute them one by one」替换为并行化规则:独立调用批量发出,有依赖的调用串行
8+
- 新增:prefer write_file / edit / read_file over bash,bash 仅用于构建/测试/git/包管理,禁止用 sed/cat/awk 操作项目文件
9+
- 新增:任务涉及 Skill 领域时,必须先调用 `skill` 工具加载其完整指令再执行
10+
11+
## Capabilities
12+
13+
### Modified Capabilities
14+
- `system-prompt-structure`: Tool Use → Rules 子章节的内容规则变更 — 三条规则替换/新增,不影响章节结构和标题层级
15+
16+
## Impact
17+
18+
- 受影响文件:系统提示词中 `## Rules` 部分(5 条规则 → 8 条规则)
19+
- 无 API 变更、无代码变更、无依赖变更
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## MODIFIED Requirements
2+
3+
### Requirement: Tool Use section
4+
`# Tool Use` 章节 SHALL 包含 `## Rules``## Tool Search` 两个二级子章节。`## Rules` SHALL 包含以下强制性规则:
5+
6+
1. 收到创建/修改/删除文件的请求时,必须立即调用对应工具(write_file 等),不得仅描述计划
7+
2. 行动先于解释:先执行再简要说明
8+
3. 并行化:无相互依赖的 tool call 应在同一响应中批量发出;有依赖的调用跨响应串行
9+
4. 文件工具偏好:对项目文件操作优先使用 read_file / write_file / edit / grep;bash 仅用于构建、测试、git、包管理等实际 shell 指令,禁止对项目文件使用 sed、cat、awk
10+
5. Skill 激活:若任务属于 "Available Skills" 中某个 Skill 的领域,必须先调用 `skill` 工具加载其完整指令再继续
11+
6. 以用户语言回复,简洁直接
12+
7. 写代码时产出完整可运行实现,不得留占位符或 TODO
13+
14+
#### Scenario: Tool Use subsections present
15+
- **WHEN** 定位到 `# Tool Use` 章节
16+
- **THEN** 其下包含 `## Rules` 子章节(包含上述 7 条规则)
17+
- **AND** 其下包含 `## Tool Search` 子章节(描述工具发现机制)
18+
19+
#### Scenario: Rules include parallel execution policy
20+
- **WHEN** 读取 `## Rules` 子章节
21+
- **THEN** 包含并行化规则:独立 tool call 在同一响应中批量发出
22+
- **AND** 包含串行规则:有数据依赖的调用跨响应分开发出
23+
24+
#### Scenario: Rules include file tool preference
25+
- **WHEN** 读取 `## Rules` 子章节
26+
- **THEN** 明确优先使用文件原生工具(read_file, write_file, edit, grep)操作项目文件
27+
- **AND** 明确禁止用 bash 执行 sed、cat、awk 操作项目文件
28+
- **AND** 明确 bash 保留用途:tests, builds, git, package management
29+
30+
#### Scenario: Rules include skill activation gate
31+
- **WHEN** 读取 `## Rules` 子章节
32+
- **THEN** 包含规则:任务涉及 Skill 领域时,必须先调用 `skill` 工具加载指令再执行
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## 1. Locate and read system prompt source
2+
3+
- [x] 1.1 定位系统提示词源文件中 `## Rules` 子章节的精确位置和当前内容
4+
5+
## 2. Update Rules content
6+
7+
- [x] 2.1 将 "execute them one by one" 替换为并行化规则:独立调用批量发出,有依赖的串行
8+
- [x] 2.2 新增文件工具偏好规则:prefer write_file/edit/read_file/grep,bash 禁用于 sed/cat/awk
9+
- [x] 2.3 新增 Skill 激活规则:任务涉及 Skill 时先 `skill` 加载再执行
10+
11+
## 3. Update spec
12+
13+
- [x] 3.1 将 system-prompt-structure 的 "Tool Use section" requirement 更新为包含新规则内容的版本(应用 specs/ 下的 delta)
14+
- [x] 3.2 验证 spec 中所有 scenario 的 WHEN/THEN 格式正确(4 个井号 `####`
15+
16+
## 4. Verification
17+
18+
- [x] 4.1 确认 Rules 共 7 条规则、顺序正确
19+
- [x] 4.2 确认非 Rules 部分未被修改
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-06-09
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## Context
2+
3+
`Harness.initialize()` 构建 system prompt 时,`__DEFERRED_HINT__` 占位符在传给 Agent 前未被替换。同文件 `reloadProject()` 方法(line 722-723)已正确处理:
4+
5+
```ts
6+
this.baseSystemPrompt = this.buildSystemPrompt(memories, skillSection);
7+
this.agent.state.systemPrompt = this.baseSystemPrompt.replace("__DEFERRED_HINT__", this.toolRegistry.buildDeferredToolsHint());
8+
```
9+
10+
`initialize()` 中遗漏了 `.replace()` 调用:
11+
12+
```ts
13+
this.baseSystemPrompt = this.buildSystemPrompt(memories, skillSection);
14+
const systemPrompt = this.baseSystemPrompt; // ← 缺替换
15+
```
16+
17+
## Goals / Non-Goals
18+
19+
**Goals:**
20+
-`initialize()` 中初始 system prompt 的 `__DEFERRED_HINT__` 被正确替换
21+
-`reloadProject()` 保持一致的替换模式
22+
23+
**Non-Goals:**
24+
- 不改变 `transformContext` 中的替换逻辑(它已正确工作)
25+
- 不改变 `baseSystemPrompt` 的构建方式
26+
27+
## Decisions
28+
29+
**单一抉择:在 line 111 补齐 `.replace()`**
30+
31+
```ts
32+
const systemPrompt = this.baseSystemPrompt.replace("__DEFERRED_HINT__", this.toolRegistry.buildDeferredToolsHint());
33+
```
34+
35+
理由:与 `reloadProject()` 保持完全一致的替换模式,`buildDeferredToolsHint()` 在无 deferred tools 时返回空字符串,语义正确。
36+
37+
## Risks / Trade-offs
38+
39+
无风险。`buildDeferredToolsHint()``initialize()` 调用时 `ToolRegistry` 已完成 `register(makeDiscoveryDriver(...))`,返回结果与 `transformContext` 中一致。
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Why
2+
3+
`__DEFERRED_HINT__` 占位符在 `Harness.initialize()` 中构建初始 system prompt 时未被替换,导致 `--debug` dump 文件和 Agent 初始 state 中出现原始占位符文本。虽然运行时 `transformContext` 会在首次对话前替换它,但调试输出和状态初始化的语义不正确。
4+
5+
## What Changes
6+
7+
- `Harness.initialize()``systemPrompt` 的赋值增加 `.replace("__DEFERRED_HINT__", ...)` 调用,与 `reloadProject()` 方法保持一致的替换模式
8+
9+
## Capabilities
10+
11+
### New Capabilities
12+
13+
(无)
14+
15+
### Modified Capabilities
16+
17+
(无 — 纯 bug 修复,不涉及 spec 级别的需求变更)
18+
19+
## Impact
20+
21+
- 仅影响 `src/core/harness.ts` 第 111 行
22+
- 无 API 变更,无破坏性变更
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!-- 此 change 不涉及能力级别的需求变更,无需 spec。 -->
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## 1. 修复
2+
3+
- [x] 1.1 在 `Harness.initialize()` 中,将 `const systemPrompt = this.baseSystemPrompt;` 改为 `const systemPrompt = this.baseSystemPrompt.replace("__DEFERRED_HINT__", this.toolRegistry.buildDeferredToolsHint());`
4+
- [x] 1.2 在 `Harness.run()` MCP 连接后,补充 `agent.state.systemPrompt` 的 deferred hint 更新 + `dumpDebugPrompt()` 调用
5+
6+
## 2. 验证
7+
8+
- [x] 2.1 `npm run typecheck` 通过
9+
- [x] 2.2 `npm start -- --debug` 确认 dump/system-prompt.md 中不再出现 `__DEFERRED_HINT__`,且 Deferred Tools 类别正确出现 MCP 工具列表

0 commit comments

Comments
 (0)