pi-shepherd 0.1.2 → 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.
package/README.en.md CHANGED
@@ -1,19 +1,23 @@
1
- [中文文档](README.md) | English
1
+ [中文文档](README.md) | [English](#)
2
+
3
+ > 📖 **[pi-atelier Guide](https://catlain.github.io/pi-atelier/)** — Learn the pi-atelier ecosystem from scratch
2
4
 
3
5
  # pi-shepherd
4
6
 
5
- [Source Code](https://github.com/catlain/pi-shepherd) | [npm](https://www.npmjs.com/package/pi-shepherd)
7
+ [Repository](https://github.com/catlain/pi-shepherd) | [npm](https://www.npmjs.com/package/pi-shepherd)
8
+
9
+ A **rule-driven behavior guardian** for [pi-coding-agent](https://github.com/earendil-works/pi-coding-agent) — automatically intercepts, notifies, or rewrites operations at key points in the AI workflow: tool calls, AI responses, and session lifecycle events.
6
10
 
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.
11
+ ## What Problem Does It Solve
8
12
 
9
- ## What It Does
13
+ AI coding assistants tend to drift during long sessions:
10
14
 
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:
15
+ - **Tool misuse**: Using grep for symbol searches (should use code-graph), using bash cat to read files (should use read)
16
+ - **Forgot to wrap up**: Not running tests after edits, not committing git, not updating docs
17
+ - **Coding standard violations**: Using spaces in TypeScript (should use tabs), using tabs in Python (should use spaces)
18
+ - **Repeating mistakes**: Same error recurring without checking existing pitfall records
12
19
 
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
20
+ pi-shepherd provides a **configurable rules engine** that automatically intervenes at these key points, turning best practices into automated guardrails.
17
21
 
18
22
  ## Installation
19
23
 
@@ -21,116 +25,233 @@ AI agents can go off the rails — generate too much code, forget to commit, ign
21
25
  pi install git:github.com/catlain/pi-shepherd
22
26
  ```
23
27
 
24
- ## How It Works
28
+ ## Core Concepts
29
+
30
+ ### Hooks
31
+
32
+ Shepherd inserts hooks at 6 key points in the AI workflow:
33
+
34
+ | Hook | When | Typical Use |
35
+ |------|------|-------------|
36
+ | `tool_call` | Before tool execution | Block inappropriate calls, rewrite commands |
37
+ | `tool_result` | After tool execution | Check results, trigger follow-up actions |
38
+ | `agent_end` | When AI voluntarily stops | Remind to commit git, update memory |
39
+ | `message_end` | After each AI response | Detect problematic patterns in responses |
40
+ | `session_shutdown` | When session shuts down | Resource cleanup |
41
+
42
+ ### Actions
43
+
44
+ 4 actions available when a rule matches:
25
45
 
26
- pi-shepherd uses a **rules engine** that evaluates configurable patterns against tool calls and results:
46
+ | Action | Effect |
47
+ |--------|--------|
48
+ | `block` | Prevent tool execution, return reason |
49
+ | `notify` | Show reminder, AI can choose to ignore |
50
+ | `steer` | Inject into next turn, forcing AI to respond |
51
+ | `rewrite` | Rewrite tool parameters then continue |
27
52
 
53
+ ### Condition Matching
54
+
55
+ **Single condition** (simple cases):
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
+ **Multiple conditions** (precise control):
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
+ Multiple `conditions` are **AND** by default (all must match). Use `conditionLogic: "or"` for OR.
71
+
72
+ **Built-in conditions** (no regex needed):
35
73
 
36
- Rules are defined in `rules.json` (or the `shepherd` section of settings):
74
+ | builtin | Checks |
75
+ |---------|--------|
76
+ | `git_dirty` | Has uncommitted changes in tracked files |
77
+ | `git_untracked` | Has untracked files |
78
+ | `has_edits` | edit/write was called this turn |
79
+ | `always` | Always matches |
80
+
81
+ ### Stateful Rules
82
+
83
+ Track tool call statistics via the `state` field for patterns like "remind after N errors":
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": "Remind to check memory after repeated errors",
88
+ "hook": "tool_result",
89
+ "action": "steer",
90
+ "state": { "countKind": "errors", "gte": 5 },
91
+ "reason": "Tool keeps failing — check memory files for known pitfalls"
92
+ }
93
+ ```
94
+
95
+ Three counting modes:
96
+ - `calls`: Tool invocation count
97
+ - `errors`: Consecutive error count
98
+ - `chars`: Tool result character count
99
+
100
+ Use `resetOn` to reset counters when a specific tool succeeds (e.g., clear error count after tests pass).
101
+
102
+ ## Rule Format
103
+
104
+ Complete rule fields:
105
+
106
+ ```json
107
+ {
108
+ "comment": "Rule description (required, also serves as unique ID)",
109
+ "hook": "tool_call",
110
+ "tool": "bash",
111
+ "action": "block",
112
+ "reason": "Message shown to 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
+ **Required fields**: `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
+ **Optional fields**:
129
+ - `enabled`: `false` to disable (default `true`, can be omitted)
130
+ - `subagent`: `false` to skip in subagent sessions
131
+ - `requiresTools`: Only trigger when all listed tools are available
132
+ - `requireSuccess`: `true` to skip `isError` tool_results
133
+ - `stopReason`: For `agent_end` only, limit to specific end reasons
65
134
 
66
- ## Built-in Rules
135
+ ## Rule Locations
67
136
 
68
- pi-shepherd ships with default rules for common anti-patterns:
137
+ **Global rules**: `~/.pi/agent/extensions/shepherd/rules.json` (applies to all projects)
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
+ **Project rules**: `{cwd}/.pi/extensions/shepherd-rules.json` (current project only)
140
+ Or `{cwd}/.pi/extensions/shepherd-rules-*.json` (multiple files)
74
141
 
75
- ## Configuration
142
+ Project and global rules are merged. Project rules can supplement or override global rules.
143
+
144
+ ## Managing Rules
145
+
146
+ Use the `shepherd_rules` tool for safe editing (auto-validates, backs up, and verifies):
147
+
148
+ ```
149
+ # List all rules
150
+ shepherd_rules(action: "list")
151
+
152
+ # Add a rule
153
+ shepherd_rules(action: "add", rule: { comment: "...", hook: "...", ... })
154
+
155
+ # Update a rule
156
+ shepherd_rules(action: "update", index: 2, changes: { enabled: false })
157
+
158
+ # Delete a rule
159
+ shepherd_rules(action: "delete", index: 3)
160
+ ```
161
+
162
+ ## Practical Examples
163
+
164
+ ### 1. Auto-run tests after editing Python
76
165
 
77
166
  ```json
78
167
  {
79
- "shepherd": {
80
- "enabled": true,
81
- "rulesDir": "~/.pi/agent/shepherd-rules"
82
- }
168
+ "comment": "Run tests after Python edit",
169
+ "hook": "tool_result",
170
+ "tool": "edit",
171
+ "action": "notify",
172
+ "conditions": [{ "field": "path", "pattern": "\\.py$" }],
173
+ "reason": "Python file edited — please run ruff check and unit tests"
83
174
  }
84
175
  ```
85
176
 
86
- ## Use Cases
177
+ ### 2. Check git status before session ends
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": "Check git before session end",
182
+ "hook": "agent_end",
183
+ "action": "notify",
184
+ "conditions": [
185
+ { "builtin": "git_dirty" },
186
+ { "builtin": "git_untracked" }
187
+ ],
188
+ "conditionLogic": "or",
189
+ "reason": "Git has uncommitted changes — please confirm if commit + push is needed"
190
+ }
191
+ ```
95
192
 
96
- ## Best Practices
193
+ ### 3. Redirect grep to code-graph for code search
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": "Recommend code-graph over grep",
198
+ "hook": "tool_result",
199
+ "tool": "grep",
200
+ "action": "notify",
201
+ "pattern": ".",
202
+ "reason": "Use code-graph for code search: semantic_code_search (fuzzy), get_ast_node (exact), find_references (refs)",
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. Block attribution guessing in AI responses
108
208
 
109
- ## Limitations
209
+ ```json
210
+ {
211
+ "comment": "Block attribution guessing",
212
+ "hook": "message_end",
213
+ "action": "steer",
214
+ "pattern": "(probably|might be|guess|likely).*(jiti|cache|toolchain)",
215
+ "reason": "Don't guess root causes — check your code logic first, search for best practices, verify before concluding"
216
+ }
217
+ ```
218
+
219
+ ### 5. Block direct settings.json editing
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": "Block direct settings.json editing",
224
+ "hook": "tool_call",
225
+ "tool": "edit|write",
226
+ "action": "block",
227
+ "conditions": [{ "field": "path", "pattern": "settings\\.json$" }],
228
+ "reason": "Directly editing settings.json caused config loss before — use settings_patch tool instead"
229
+ }
230
+ ```
117
231
 
118
232
  ## Architecture
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 # Entry: register all hooks
237
+ ├── shepherd/
238
+ │ ├── rules.ts # Rule types + load/compile/match
239
+ │ ├── conditions.ts # Condition types + builtin matching
240
+ │ ├── state-tracker.ts # Stateful rule state tracker
241
+ │ ├── tool-hooks.ts # tool_call / tool_result hook handlers
242
+ │ ├── message-end.ts # message_end hook handler
243
+ │ ├── rules-tool.ts # shepherd_rules tool registration
244
+ │ ├── rules-editor.ts # Safe rule file editing (backup+validate)
245
+ │ ├── rules-validate.ts # Rule format validation
246
+ │ ├── ephemeral.ts # Warning buffer (pushWarning)
247
+ │ ├── git.ts # Git status check utilities
248
+ │ └── worktree-check.ts # Worktree environment detection
249
+ ├── rules.json # Default global rules
250
+ └── tests/ # Tests
130
251
  ```
131
252
 
132
253
  **Dependencies**:
133
- - `@pi-atelier/shared-utils` (bundled) — settings management
254
+ - `@pi-atelier/shared-utils` — Config API, tool output formatting
134
255
  - `@earendil-works/pi-coding-agent` — ExtensionAPI (peer)
135
256
 
136
257
  ## License