pi-shepherd 0.1.1 → 0.2.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 (58) hide show
  1. package/README.en.md +206 -83
  2. package/README.md +209 -88
  3. package/index.ts +262 -229
  4. package/package.json +60 -58
  5. package/rules.json +197 -218
  6. package/shepherd/compaction.ts +76 -0
  7. package/shepherd/conditions.ts +98 -0
  8. package/shepherd/ephemeral.ts +55 -52
  9. package/shepherd/git.ts +64 -0
  10. package/shepherd/index.ts +14 -0
  11. package/shepherd/line-count.ts +86 -86
  12. package/shepherd/message-end.ts +120 -0
  13. package/shepherd/rules-editor.ts +250 -135
  14. package/shepherd/rules-tool-helpers.ts +119 -0
  15. package/shepherd/rules-tool-list.ts +124 -0
  16. package/shepherd/rules-tool.ts +182 -99
  17. package/shepherd/rules-validate.ts +89 -44
  18. package/shepherd/rules.ts +366 -283
  19. package/shepherd/tool-event-types.ts +27 -14
  20. package/shepherd/tool-hooks.ts +165 -176
  21. package/shepherd/worktree-check.ts +130 -130
  22. package/tsconfig.json +21 -14
  23. package/node_modules/@pi-atelier/shared-utils/README.en.md +0 -182
  24. package/node_modules/@pi-atelier/shared-utils/README.md +0 -182
  25. package/node_modules/@pi-atelier/shared-utils/package.json +0 -51
  26. package/node_modules/@pi-atelier/shared-utils/src/__tests__/agents.test.ts +0 -120
  27. package/node_modules/@pi-atelier/shared-utils/src/__tests__/ephemeral.test.ts +0 -100
  28. package/node_modules/@pi-atelier/shared-utils/src/__tests__/file-lock.test.ts +0 -152
  29. package/node_modules/@pi-atelier/shared-utils/src/__tests__/filter-match.test.ts +0 -187
  30. package/node_modules/@pi-atelier/shared-utils/src/__tests__/memory-parser.test.ts +0 -170
  31. package/node_modules/@pi-atelier/shared-utils/src/__tests__/paths.test.ts +0 -126
  32. package/node_modules/@pi-atelier/shared-utils/src/__tests__/project-config-edge.test.ts +0 -138
  33. package/node_modules/@pi-atelier/shared-utils/src/__tests__/project-config.test.ts +0 -257
  34. package/node_modules/@pi-atelier/shared-utils/src/__tests__/project-tools-mcp.test.ts +0 -189
  35. package/node_modules/@pi-atelier/shared-utils/src/__tests__/project-tools.test.ts +0 -204
  36. package/node_modules/@pi-atelier/shared-utils/src/__tests__/settings-backup-advanced.test.ts +0 -269
  37. package/node_modules/@pi-atelier/shared-utils/src/__tests__/settings-backup-array.test.ts +0 -267
  38. package/node_modules/@pi-atelier/shared-utils/src/__tests__/settings-backup.test.ts +0 -520
  39. package/node_modules/@pi-atelier/shared-utils/src/__tests__/settings-read.test.ts +0 -116
  40. package/node_modules/@pi-atelier/shared-utils/src/__tests__/settings-write.test.ts +0 -119
  41. package/node_modules/@pi-atelier/shared-utils/src/__tests__/tool-output.test.ts +0 -145
  42. package/node_modules/@pi-atelier/shared-utils/src/agents.ts +0 -39
  43. package/node_modules/@pi-atelier/shared-utils/src/ephemeral.ts +0 -42
  44. package/node_modules/@pi-atelier/shared-utils/src/file-lock.ts +0 -62
  45. package/node_modules/@pi-atelier/shared-utils/src/filter-match.ts +0 -100
  46. package/node_modules/@pi-atelier/shared-utils/src/index.ts +0 -71
  47. package/node_modules/@pi-atelier/shared-utils/src/memory-parser.ts +0 -96
  48. package/node_modules/@pi-atelier/shared-utils/src/paths.ts +0 -23
  49. package/node_modules/@pi-atelier/shared-utils/src/project-config.ts +0 -241
  50. package/node_modules/@pi-atelier/shared-utils/src/project-tools.ts +0 -191
  51. package/node_modules/@pi-atelier/shared-utils/src/settings-array.ts +0 -73
  52. package/node_modules/@pi-atelier/shared-utils/src/settings-backup-rollback.ts +0 -104
  53. package/node_modules/@pi-atelier/shared-utils/src/settings-backup-utils.ts +0 -75
  54. package/node_modules/@pi-atelier/shared-utils/src/settings-backup.ts +0 -172
  55. package/node_modules/@pi-atelier/shared-utils/src/settings.ts +0 -104
  56. package/node_modules/@pi-atelier/shared-utils/src/tool-output.ts +0 -149
  57. package/node_modules/@pi-atelier/shared-utils/tsconfig.json +0 -9
  58. package/node_modules/@pi-atelier/shared-utils/vitest.config.ts +0 -24
package/README.md CHANGED
@@ -1,137 +1,258 @@
1
- [English](README.en.md) | 程序中文文档
1
+ [English](README.en.md) | [中文文档](#)
2
2
 
3
- > 📖 **[pi-atelier 实战指南](https://catlain.github.io/pi-atelier/)** — 从零教会你使用 pi-atelier 扩展生态,让 AI 编程助手从「会写代码」进化到「会管理项目」
3
+ > 📖 **[pi-atelier 实战指南](https://catlain.github.io/pi-atelier/)** — 从零教会你使用 pi-atelier 扩展生态
4
4
 
5
5
  # pi-shepherd
6
6
 
7
- Line count guard and behavior rules extension for [pi-coding-agent](https://github.com/earendil-works/pi-coding-agent) — rule-driven hooks for tool calls, agent end, and session events.
7
+ [源码仓库](https://github.com/catlain/pi-shepherd) | [npm](https://www.npmjs.com/package/pi-shepherd)
8
8
 
9
- ## What It Does
9
+ pi-coding-agent 的 **规则驱动行为守护系统** — 在工具调用、AI 回复、会话结束等关键节点,自动拦截、提醒或改写操作。
10
10
 
11
- AI agents can go off the rails — generate too much code, forget to commit, ignore coding standards, or produce outputs that are too large. pi-shepherd acts as a **guardrail system** that monitors and enforces behavioral rules:
11
+ ## 解决什么问题
12
12
 
13
- - **Tool call interception** — Inspect and modify tool calls before execution (e.g., enforce line limits)
14
- - **Tool result inspection** — Check tool results after execution (e.g., flag overly large outputs)
15
- - **Agent end hooks** — Enforce commit/message rules when the agent finishes
16
- - **Session lifecycle** — Reset state between sessions
13
+ AI 编程助手在长时间会话中容易跑偏:
17
14
 
18
- ## Installation
15
+ - **工具滥用**:用 grep 搜符号名(应该用 code-graph)、用 bash cat 读文件(应该用 read)
16
+ - **忘记收尾**:改完代码不跑测试、不提交 git、不更新文档
17
+ - **编码规范违反**:TypeScript 用空格缩进(应该用 Tab)、Python 用 Tab(应该用空格)
18
+ - **重复犯错**:同一个错误反复出现,不知道翻看已有的踩坑记录
19
+
20
+ pi-shepherd 通过**可配置的规则引擎**,在这些关键节点自动介入,把最佳实践变成自动化的守护机制。
21
+
22
+ ## 安装
19
23
 
20
24
  ```bash
21
25
  pi install git:github.com/catlain/pi-shepherd
22
26
  ```
23
27
 
24
- ## How It Works
28
+ ## 核心概念
29
+
30
+ ### 钩子(Hook)
31
+
32
+ Shepherd 在 AI 工作流的 6 个关键节点插入钩子:
33
+
34
+ | 钩子 | 触发时机 | 典型用途 |
35
+ |------|---------|---------|
36
+ | `tool_call` | 工具即将执行前 | 拦截不当调用、改写命令 |
37
+ | `tool_result` | 工具执行完成后 | 检查结果、触发后续动作 |
38
+ | `agent_end` | AI 主动结束时 | 提醒提交 git、更新记忆 |
39
+ | `message_end` | AI 每条回复完成后 | 检测回复中的问题模式 |
40
+ | `session_shutdown` | 会话关闭时 | 清理资源 |
41
+
42
+ ### 动作(Action)
43
+
44
+ 规则匹配后可以执行 4 种动作:
25
45
 
26
- pi-shepherd uses a **rules engine** that evaluates configurable patterns against tool calls and results:
46
+ | 动作 | 效果 |
47
+ |------|------|
48
+ | `block` | 阻止工具执行,返回原因 |
49
+ | `notify` | 弹出提醒,AI 可以选择忽略 |
50
+ | `steer` | 注入下一轮对话,强制 AI 响应 |
51
+ | `rewrite` | 改写工具参数后继续执行 |
27
52
 
53
+ ### 条件匹配
54
+
55
+ **单条件模式**(简单场景):
56
+ ```json
57
+ { "pattern": "\\bcat\\b", "flags": "" }
28
58
  ```
29
- Tool Call → Rules Engine → Pass/Block/Modify
30
- Tool Result → Rules Engine → Pass/Flag/Truncate
31
- Agent End → Rules Engine → Enforce (commit, summarize, etc.)
59
+
60
+ **多条件模式**(精确控制):
61
+ ```json
62
+ {
63
+ "conditions": [
64
+ { "field": "path", "pattern": "\\.ts$" },
65
+ { "field": "text", "pattern": "\\n [\\S ]" }
66
+ ]
67
+ }
32
68
  ```
33
69
 
34
- ### Rules Format
70
+ 多个 `conditions` 默认是 **AND** 关系(全部满足才触发),可通过 `conditionLogic: "or"` 改为 OR。
71
+
72
+ **内置条件**(不需要正则):
35
73
 
36
- Rules are defined in `rules.json` (or the `shepherd` section of settings):
74
+ | builtin | 检查内容 |
75
+ |---------|---------|
76
+ | `git_dirty` | 有已跟踪文件的未提交改动 |
77
+ | `git_untracked` | 有未跟踪文件 |
78
+ | `has_edits` | 本轮调用过 edit/write |
79
+ | `always` | 始终匹配 |
80
+
81
+ ### 有状态规则
82
+
83
+ 通过 `state` 字段追踪工具调用统计,实现「N 次错误后提醒」等模式:
37
84
 
38
85
  ```json
39
- [
40
- {
41
- "name": "block-grep-for-code-graph",
42
- "pattern": "^grep\\s+.*\\b[A-Z][a-zA-Z]+\\(",
43
- "type": "tool_call",
44
- "action": "block",
45
- "message": "Use code-graph search_symbols instead of grep for symbol names"
46
- },
47
- {
48
- "name": "warn-large-edit",
49
- "pattern": "edit",
50
- "type": "tool_result",
51
- "maxLines": 500,
52
- "action": "warn",
53
- "message": "Edit result is large, consider breaking into smaller changes"
54
- }
55
- ]
86
+ {
87
+ "comment": "连续出错后提醒翻记忆",
88
+ "hook": "tool_result",
89
+ "action": "steer",
90
+ "state": { "countKind": "errors", "gte": 5 },
91
+ "reason": "工具反复出错,请检查记忆文件是否有踩坑记录"
92
+ }
93
+ ```
94
+
95
+ 支持三种计数方式:
96
+ - `calls`:工具调用次数
97
+ - `errors`:连续错误次数
98
+ - `chars`:工具返回的字符量
99
+
100
+ 配合 `resetOn` 可以在某个工具成功后重置计数(如测试通过后清零错误计数)。
101
+
102
+ ## 规则格式
103
+
104
+ 完整的规则字段:
105
+
106
+ ```json
107
+ {
108
+ "comment": "规则描述(必填,同时作为唯一标识)",
109
+ "hook": "tool_call",
110
+ "tool": "bash",
111
+ "action": "block",
112
+ "reason": "给 AI 看的提示信息",
113
+ "pattern": "\\bcat\\b",
114
+ "conditions": [{ "field": "path", "pattern": "\\.ts$" }],
115
+ "conditionLogic": "and",
116
+ "enabled": true,
117
+ "state": { "countKind": "errors", "gte": 3 },
118
+ "resetOn": ["bash"],
119
+ "subagent": false,
120
+ "requiresTools": ["code_graph_semantic_code_search"],
121
+ "requireSuccess": true,
122
+ "stopReason": ["stop"]
123
+ }
56
124
  ```
57
125
 
58
- ### Rule Types
126
+ **必填字段**:`comment`、`reason`
59
127
 
60
- | Type | When Evaluated | Actions |
61
- |------|---------------|---------|
62
- | `tool_call` | Before tool execution | `pass`, `block`, `modify` |
63
- | `tool_result` | After tool execution | `pass`, `warn`, `truncate` |
64
- | `agent_end` | When agent finishes | `enforce` |
128
+ **可选字段说明**:
129
+ - `enabled`:`false` 禁用规则(默认 `true`,可省略)
130
+ - `subagent`:`false` 表示子代理中跳过此规则
131
+ - `requiresTools`:只有这些工具都可用时才触发
132
+ - `requireSuccess`:`true` 表示跳过 isError 的 tool_result
133
+ - `stopReason`:`agent_end` 专用,限制只在特定结束原因时触发
65
134
 
66
- ## Built-in Rules
135
+ ## 规则存放位置
67
136
 
68
- pi-shepherd ships with default rules for common anti-patterns:
137
+ **全局规则**:`~/.pi/agent/extensions/shepherd/rules.json`(所有项目生效)
69
138
 
70
- - Redirect `grep` to `code-graph` for symbol searches
71
- - Warn on overly large tool results
72
- - Enforce git commit on agent end
73
- - Block redundant file reads
139
+ **项目规则**:`{cwd}/.pi/extensions/shepherd-rules.json`(仅当前项目生效)
140
+ 或 `{cwd}/.pi/extensions/shepherd-rules-*.json`(多文件)
74
141
 
75
- ## Configuration
142
+ 项目规则和全局规则合并执行,项目规则可以补充或覆盖全局规则。
143
+
144
+ ## 管理规则
145
+
146
+ 使用 `shepherd_rules` 工具安全编辑规则(自动校验格式、备份、回滚):
147
+
148
+ ```
149
+ # 列出所有规则
150
+ shepherd_rules(action: "list")
151
+
152
+ # 添加规则
153
+ shepherd_rules(action: "add", rule: { comment: "...", hook: "...", ... })
154
+
155
+ # 更新规则
156
+ shepherd_rules(action: "update", index: 2, changes: { enabled: false })
157
+
158
+ # 删除规则
159
+ shepherd_rules(action: "delete", index: 3)
160
+ ```
161
+
162
+ ## 实战示例
163
+
164
+ ### 1. 编辑 Python 后自动跑测试
76
165
 
77
166
  ```json
78
167
  {
79
- "shepherd": {
80
- "enabled": true,
81
- "rulesDir": "~/.pi/agent/shepherd-rules"
82
- }
168
+ "comment": "编辑 Python 后跑测试",
169
+ "hook": "tool_result",
170
+ "tool": "edit",
171
+ "action": "notify",
172
+ "conditions": [{ "field": "path", "pattern": "\\.py$" }],
173
+ "reason": "编辑了 Python 文件,请运行 ruff check 和单元测试"
83
174
  }
84
175
  ```
85
176
 
86
- ## Use Cases
177
+ ### 2. 会话结束前检查 git
87
178
 
88
- | Scenario | Rule Type | Action |
89
- |----------|-----------|--------|
90
- | **Enforce coding standards** | `tool_call` | Block tools that don't follow conventions |
91
- | **Prevent context bloat** | `tool_result` | Truncate large results |
92
- | **Git discipline** | `agent_end` | Force commit at session end |
93
- | **Redirect to better tools** | `tool_call` | Block grep, suggest code-graph |
94
- | **Custom team rules** | All types | Project-specific guardrails |
179
+ ```json
180
+ {
181
+ "comment": "会话结束检查 git",
182
+ "hook": "agent_end",
183
+ "action": "notify",
184
+ "conditions": [
185
+ { "builtin": "git_dirty" },
186
+ { "builtin": "git_untracked" }
187
+ ],
188
+ "conditionLogic": "or",
189
+ "reason": "Git 有未提交改动,请确认是否需要 commit + push"
190
+ }
191
+ ```
95
192
 
96
- ## Best Practices
193
+ ### 3. 拦截 grep 搜代码,推荐 code-graph
97
194
 
98
- ### ✅ Recommended
99
- - Start with built-in rules, then add project-specific ones
100
- - Use `warn` before `block` — give the agent a chance to learn
101
- - Keep rule patterns simple and specific — regex is evaluated on every tool call
102
- - Put project rules in `.pi/shepherd-rules/` for version control
195
+ ```json
196
+ {
197
+ "comment": "推荐 code-graph 替代 grep",
198
+ "hook": "tool_result",
199
+ "tool": "grep",
200
+ "action": "notify",
201
+ "pattern": ".",
202
+ "reason": "搜代码推荐用 code-graph:semantic_code_search(模糊)、get_ast_node(精确)、find_references(引用)",
203
+ "requiresTools": ["code_graph_semantic_code_search"]
204
+ }
205
+ ```
103
206
 
104
- ### ❌ Not Recommended
105
- - Don't use overly broad patterns — they'll match too many calls and slow things down
106
- - Don't create contradictory rules (block + allow the same pattern)
107
- - Don't rely on shepherd for security — it's a guide, not a sandbox
207
+ ### 4. 拦截 AI 回复中的归因猜测
108
208
 
109
- ## Limitations
209
+ ```json
210
+ {
211
+ "comment": "禁止归因猜测",
212
+ "hook": "message_end",
213
+ "action": "steer",
214
+ "pattern": "(可能是|猜测|大概|也许是).*(jiti|缓存|工具链)",
215
+ "reason": "不要猜测根因——先查自己的代码逻辑,搜索最佳实践,验证后再下结论"
216
+ }
217
+ ```
218
+
219
+ ### 5. 禁止直接编辑 settings.json
110
220
 
111
- | Limitation | Detail |
112
- |------------|--------|
113
- | Regex only | Patterns use regex, not semantic understanding |
114
- | No async rules | Rules must evaluate synchronously |
115
- | Agent can bypass | Determined agents can ignore warnings |
116
- | No persistence | Rule state resets between sessions |
221
+ ```json
222
+ {
223
+ "comment": "禁止直接编辑 settings.json",
224
+ "hook": "tool_call",
225
+ "tool": "edit|write",
226
+ "action": "block",
227
+ "conditions": [{ "field": "path", "pattern": "settings\\.json$" }],
228
+ "reason": "直接编辑 settings.json 曾导致配置丢失,必须使用 settings_patch 工具"
229
+ }
230
+ ```
117
231
 
118
- ## Architecture
232
+ ## 架构
119
233
 
120
234
  ```
121
235
  pi-shepherd/
122
- ├── index.ts # Entry: register hooks + rules engine
123
- ├── rules-engine.ts # Pattern matching + action dispatch
124
- ├── rules/ # Built-in rule definitions
125
- │ ├── grep.ts # Redirect grep → code-graph
126
- │ ├── line-limit.ts # Warn on large outputs
127
- │ └── agent-end.ts # Enforce git commit
128
- ├── types.ts # Rule type definitions
129
- └── package.json
236
+ ├── index.ts # 入口:注册所有钩子
237
+ ├── shepherd/
238
+ │ ├── rules.ts # 规则类型定义 + 加载/编译/匹配
239
+ │ ├── conditions.ts # Condition 类型 + builtin 条件匹配
240
+ │ ├── state-tracker.ts # 有状态规则的状态追踪器
241
+ │ ├── tool-hooks.ts # tool_call / tool_result 钩子处理
242
+ │ ├── message-end.ts # message_end 钩子处理
243
+ │ ├── rules-tool.ts # shepherd_rules 工具注册
244
+ │ ├── rules-editor.ts # 规则文件安全编辑(备份+校验)
245
+ │ ├── rules-validate.ts # 规则格式校验
246
+ │ ├── ephemeral.ts # 提示缓冲区(pushWarning)
247
+ │ ├── git.ts # git 状态检查工具函数
248
+ │ └── worktree-check.ts # worktree 环境检测
249
+ ├── rules.json # 默认全局规则
250
+ └── tests/ # 测试
130
251
  ```
131
252
 
132
- **Dependencies**:
133
- - `@pi-atelier/shared-utils` (bundled) — settings management
134
- - `@earendil-works/pi-coding-agent` — ExtensionAPI (peer)
253
+ **依赖**:
254
+ - `@pi-atelier/shared-utils` — 配置 API、工具输出格式化
255
+ - `@earendil-works/pi-coding-agent` — ExtensionAPI(peer)
135
256
 
136
257
  ## License
137
258