@davidorex/pi-project-workflows 0.3.0 → 0.3.2
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/package.json +9 -5
- package/skills/pi-behavior-monitors/SKILL.md +692 -0
- package/skills/pi-behavior-monitors/references/bundled-resources.md +29 -0
- package/skills/pi-project/SKILL.md +231 -0
- package/skills/pi-project/references/bundled-resources.md +26 -0
- package/skills/pi-project-workflows/SKILL.md +42 -0
- package/skills/pi-workflows/SKILL.md +185 -0
- package/skills/pi-workflows/references/bundled-resources.md +87 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@davidorex/pi-project-workflows",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Pi extensions for structured project state, workflow orchestration, and behavior monitoring — single install for all three",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "David Ryan",
|
|
@@ -15,18 +15,22 @@
|
|
|
15
15
|
"homepage": "https://github.com/davidorex/pi-project-workflows",
|
|
16
16
|
"files": [
|
|
17
17
|
"*.ts",
|
|
18
|
-
"*.md"
|
|
18
|
+
"*.md",
|
|
19
|
+
"skills/"
|
|
19
20
|
],
|
|
20
21
|
"pi": {
|
|
21
22
|
"extensions": [
|
|
22
23
|
"./project-extension.ts",
|
|
23
24
|
"./workflows-extension.ts",
|
|
24
25
|
"./monitors-extension.ts"
|
|
26
|
+
],
|
|
27
|
+
"skills": [
|
|
28
|
+
"./skills"
|
|
25
29
|
]
|
|
26
30
|
},
|
|
27
31
|
"dependencies": {
|
|
28
|
-
"@davidorex/pi-project": "^0.3.
|
|
29
|
-
"@davidorex/pi-workflows": "^0.3.
|
|
30
|
-
"@davidorex/pi-behavior-monitors": "^0.3.
|
|
32
|
+
"@davidorex/pi-project": "^0.3.2",
|
|
33
|
+
"@davidorex/pi-workflows": "^0.3.2",
|
|
34
|
+
"@davidorex/pi-behavior-monitors": "^0.3.2"
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pi-behavior-monitors
|
|
3
|
+
description: >
|
|
4
|
+
Behavior monitors that watch agent activity and steer corrections when issues
|
|
5
|
+
are detected. Monitors are JSON files (.monitor.json) in .pi/monitors/ with
|
|
6
|
+
classify, patterns, actions, and scope blocks. Patterns and instructions are
|
|
7
|
+
JSON arrays. Use when creating, editing, debugging, or understanding behavior
|
|
8
|
+
monitors.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<tools_reference>
|
|
12
|
+
<tool name="monitors-status">
|
|
13
|
+
List all behavior monitors with their current state.
|
|
14
|
+
|
|
15
|
+
*List all behavior monitors with their current state*
|
|
16
|
+
|
|
17
|
+
</tool>
|
|
18
|
+
|
|
19
|
+
<tool name="monitors-inspect">
|
|
20
|
+
Inspect a monitor — config, state, pattern count, rule count.
|
|
21
|
+
|
|
22
|
+
*Inspect a monitor — config, state, pattern count, rule count*
|
|
23
|
+
|
|
24
|
+
| Parameter | Type | Required | Description |
|
|
25
|
+
|-----------|------|----------|-------------|
|
|
26
|
+
| `monitor` | string | yes | Monitor name |
|
|
27
|
+
</tool>
|
|
28
|
+
|
|
29
|
+
<tool name="monitors-control">
|
|
30
|
+
Control monitors — enable, disable, dismiss, or reset.
|
|
31
|
+
|
|
32
|
+
*Control monitors — enable, disable, dismiss, or reset*
|
|
33
|
+
|
|
34
|
+
| Parameter | Type | Required | Description |
|
|
35
|
+
|-----------|------|----------|-------------|
|
|
36
|
+
| `action` | unknown | yes | |
|
|
37
|
+
| `monitor` | string | no | Monitor name (required for dismiss/reset) |
|
|
38
|
+
</tool>
|
|
39
|
+
|
|
40
|
+
<tool name="monitors-rules">
|
|
41
|
+
Manage monitor rules — list, add, remove, or replace calibration rules.
|
|
42
|
+
|
|
43
|
+
*Manage monitor rules — list, add, remove, or replace calibration rules*
|
|
44
|
+
|
|
45
|
+
| Parameter | Type | Required | Description |
|
|
46
|
+
|-----------|------|----------|-------------|
|
|
47
|
+
| `monitor` | string | yes | Monitor name |
|
|
48
|
+
| `action` | unknown | yes | |
|
|
49
|
+
| `text` | string | no | Rule text (for add/replace) |
|
|
50
|
+
| `index` | number | no | Rule index, 1-based (for remove/replace) |
|
|
51
|
+
</tool>
|
|
52
|
+
|
|
53
|
+
<tool name="monitors-patterns">
|
|
54
|
+
List patterns for a behavior monitor.
|
|
55
|
+
|
|
56
|
+
*List patterns for a behavior monitor*
|
|
57
|
+
|
|
58
|
+
| Parameter | Type | Required | Description |
|
|
59
|
+
|-----------|------|----------|-------------|
|
|
60
|
+
| `monitor` | string | yes | Monitor name |
|
|
61
|
+
</tool>
|
|
62
|
+
|
|
63
|
+
</tools_reference>
|
|
64
|
+
|
|
65
|
+
<commands_reference>
|
|
66
|
+
<command name="/monitors">
|
|
67
|
+
Manage behavior monitors
|
|
68
|
+
|
|
69
|
+
Subcommands: `on`, `off`, `fragility`, `response-style`
|
|
70
|
+
</command>
|
|
71
|
+
|
|
72
|
+
</commands_reference>
|
|
73
|
+
|
|
74
|
+
<events>
|
|
75
|
+
`session_start`, `session_switch`, `agent_end`, `turn_start`, `message_end`
|
|
76
|
+
</events>
|
|
77
|
+
|
|
78
|
+
<bundled_resources>
|
|
79
|
+
2 schemas, 20 examples bundled.
|
|
80
|
+
See references/bundled-resources.md for full inventory.
|
|
81
|
+
</bundled_resources>
|
|
82
|
+
|
|
83
|
+
<monitor_vocabulary>
|
|
84
|
+
|
|
85
|
+
**Context Collectors:**
|
|
86
|
+
|
|
87
|
+
| Collector | Placeholder | Description | Limits |
|
|
88
|
+
|-----------|-------------|-------------|--------|
|
|
89
|
+
| `user_text` | `{user_text}` / `{{ user_text }}` | Most recent user message text | — |
|
|
90
|
+
| `assistant_text` | `{assistant_text}` / `{{ assistant_text }}` | Most recent assistant message text | — |
|
|
91
|
+
| `tool_results` | `{tool_results}` / `{{ tool_results }}` | Tool results with tool name and error status | Last 5, truncated 2000 chars |
|
|
92
|
+
| `tool_calls` | `{tool_calls}` / `{{ tool_calls }}` | Tool calls and results interleaved | Last 20, truncated 2000 chars |
|
|
93
|
+
| `custom_messages` | `{custom_messages}` / `{{ custom_messages }}` | Custom extension messages since last user message | — |
|
|
94
|
+
| `project_vision` | `{project_vision}` / `{{ project_vision }}` | .project/project.json vision, core_value, name | — |
|
|
95
|
+
| `project_conventions` | `{project_conventions}` / `{{ project_conventions }}` | .project/conformance-reference.json principle names | — |
|
|
96
|
+
| `git_status` | `{git_status}` / `{{ git_status }}` | Output of git status --porcelain | 5s timeout |
|
|
97
|
+
|
|
98
|
+
Any string is accepted in `classify.context`. Unknown collector names produce empty string.
|
|
99
|
+
|
|
100
|
+
Built-in placeholders (always available, not in `classify.context`):
|
|
101
|
+
- `{{ patterns }}` — patterns JSON as numbered list
|
|
102
|
+
- `{{ instructions }}` — instructions JSON as bulleted list with "follow strictly" preamble
|
|
103
|
+
- `{{ iteration }}` — consecutive steer count (0-indexed)
|
|
104
|
+
|
|
105
|
+
**When Conditions:**
|
|
106
|
+
|
|
107
|
+
- `always` — Fire every time the event occurs
|
|
108
|
+
- `has_tool_results` — Fire only if tool results present since last user message
|
|
109
|
+
- `has_file_writes` — Fire only if write or edit tool called since last user message
|
|
110
|
+
- `has_bash` — Fire only if bash tool called since last user message
|
|
111
|
+
- `every(N)` — Fire every Nth activation (counter resets when user text changes)
|
|
112
|
+
- `tool(name)` — Fire only if specific named tool called since last user message
|
|
113
|
+
|
|
114
|
+
**Events:** `message_end`, `turn_end`, `agent_end`, `command`
|
|
115
|
+
|
|
116
|
+
**Verdict Types:** `clean`, `flag`, `new`
|
|
117
|
+
|
|
118
|
+
**Scope Targets:** `main`, `subagent`, `all`, `workflow`
|
|
119
|
+
|
|
120
|
+
</monitor_vocabulary>
|
|
121
|
+
|
|
122
|
+
<objective>
|
|
123
|
+
Monitors are autonomous watchdogs that observe agent activity, classify it against a
|
|
124
|
+
JSON pattern library using a side-channel LLM call, and either steer corrections or
|
|
125
|
+
write structured findings to JSON files for downstream consumption.
|
|
126
|
+
</objective>
|
|
127
|
+
|
|
128
|
+
<monitor_locations>
|
|
129
|
+
Monitors are discovered from two locations, checked in order:
|
|
130
|
+
|
|
131
|
+
1. **Project**: `.pi/monitors/*.monitor.json` (walks up from cwd to find `.pi/`)
|
|
132
|
+
2. **Global**: `~/.pi/agent/monitors/*.monitor.json` (via `getAgentDir()`)
|
|
133
|
+
|
|
134
|
+
Project monitors take precedence — if a project monitor has the same `name` as a global
|
|
135
|
+
one, the global monitor is ignored. The extension silently exits if zero monitors are
|
|
136
|
+
discovered after checking both locations.
|
|
137
|
+
</monitor_locations>
|
|
138
|
+
|
|
139
|
+
<seeding>
|
|
140
|
+
On first run in a project, the extension seeds bundled example monitors into
|
|
141
|
+
`.pi/monitors/` if ALL of the following are true:
|
|
142
|
+
|
|
143
|
+
- `discoverMonitors()` finds zero monitors (neither project nor global)
|
|
144
|
+
- The `examples/` directory exists in the extension package
|
|
145
|
+
- The target `.pi/monitors/` directory contains no `.monitor.json` files
|
|
146
|
+
|
|
147
|
+
Seeding copies all `.json` files from `examples/` (monitor definitions, patterns, and
|
|
148
|
+
instructions files) into `.pi/monitors/`. It skips files that already exist at the
|
|
149
|
+
destination. The user is notified: "Edit or delete them to customize."
|
|
150
|
+
|
|
151
|
+
To customize seeded monitors, edit the copies in `.pi/monitors/` directly. To remove a
|
|
152
|
+
bundled monitor, delete its three files (`.monitor.json`, `.patterns.json`,
|
|
153
|
+
`.instructions.json`). Seeding never re-runs once any monitors exist.
|
|
154
|
+
</seeding>
|
|
155
|
+
|
|
156
|
+
<file_structure>
|
|
157
|
+
Each monitor is a set of files sharing a name prefix:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
.pi/monitors/
|
|
161
|
+
├── fragility.monitor.json # Monitor definition (classify + patterns + actions + scope)
|
|
162
|
+
├── fragility.patterns.json # Known patterns (JSON array, grows automatically)
|
|
163
|
+
├── fragility.instructions.json # User corrections (JSON array, optional)
|
|
164
|
+
├── fragility/
|
|
165
|
+
│ └── classify.md # Nunjucks template for classification prompt (optional)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The instructions file is optional. If omitted, the extension defaults the path to
|
|
169
|
+
`${name}.instructions.json` and treats a missing file as an empty array.
|
|
170
|
+
|
|
171
|
+
The classify template is optional. When `classify.promptTemplate` is set in the monitor
|
|
172
|
+
definition, the template is resolved through a three-tier search: `.pi/monitors/` (project),
|
|
173
|
+
`~/.pi/agent/monitors/` (user), then the package `examples/` directory. A user overrides a
|
|
174
|
+
bundled template by placing a file at the same relative path in `.pi/monitors/`.
|
|
175
|
+
</file_structure>
|
|
176
|
+
|
|
177
|
+
<monitor_definition>
|
|
178
|
+
A `.monitor.json` file conforms to `schemas/monitor.schema.json`:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"name": "my-monitor",
|
|
183
|
+
"description": "What this monitor watches for",
|
|
184
|
+
"event": "message_end",
|
|
185
|
+
"when": "has_tool_results",
|
|
186
|
+
"scope": {
|
|
187
|
+
"target": "main",
|
|
188
|
+
"filter": { "agent_type": ["audit-fixer"] }
|
|
189
|
+
},
|
|
190
|
+
"classify": {
|
|
191
|
+
"model": "claude-sonnet-4-20250514",
|
|
192
|
+
"context": ["tool_results", "assistant_text"],
|
|
193
|
+
"excludes": ["other-monitor"],
|
|
194
|
+
"promptTemplate": "my-monitor/classify.md",
|
|
195
|
+
"prompt": "Inline fallback if template not found. {tool_results} {assistant_text} {patterns} {instructions}\n\nReply CLEAN, FLAG:<desc>, or NEW:<pattern>|<desc>."
|
|
196
|
+
},
|
|
197
|
+
"patterns": {
|
|
198
|
+
"path": "my-monitor.patterns.json",
|
|
199
|
+
"learn": true
|
|
200
|
+
},
|
|
201
|
+
"instructions": {
|
|
202
|
+
"path": "my-monitor.instructions.json"
|
|
203
|
+
},
|
|
204
|
+
"actions": {
|
|
205
|
+
"on_flag": {
|
|
206
|
+
"steer": "Fix the issue.",
|
|
207
|
+
"write": {
|
|
208
|
+
"path": ".workflow/gaps.json",
|
|
209
|
+
"merge": "append",
|
|
210
|
+
"array_field": "gaps",
|
|
211
|
+
"template": {
|
|
212
|
+
"id": "monitor-{finding_id}",
|
|
213
|
+
"description": "{description}",
|
|
214
|
+
"status": "open",
|
|
215
|
+
"category": "monitor",
|
|
216
|
+
"source": "monitor"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
"on_new": {
|
|
221
|
+
"steer": "Fix the issue.",
|
|
222
|
+
"learn_pattern": true,
|
|
223
|
+
"write": { "...": "same as on_flag" }
|
|
224
|
+
},
|
|
225
|
+
"on_clean": null
|
|
226
|
+
},
|
|
227
|
+
"ceiling": 5,
|
|
228
|
+
"escalate": "ask"
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
</monitor_definition>
|
|
232
|
+
|
|
233
|
+
<fields>
|
|
234
|
+
|
|
235
|
+
**Top-level fields:**
|
|
236
|
+
|
|
237
|
+
| Field | Default | Description |
|
|
238
|
+
|-------|---------|-------------|
|
|
239
|
+
| `name` | (required) | Monitor identifier. Must be unique across project and global. |
|
|
240
|
+
| `description` | `""` | Human-readable description. Also used as command description for `event: command` monitors. |
|
|
241
|
+
| `event` | `message_end` | When to fire: `message_end`, `turn_end`, `agent_end`, or `command`. |
|
|
242
|
+
| `when` | `always` | Activation condition (see below). |
|
|
243
|
+
| `ceiling` | `5` | Max consecutive steers before escalation. |
|
|
244
|
+
| `escalate` | `ask` | At ceiling: `ask` (confirm with user) or `dismiss` (silence for session). |
|
|
245
|
+
|
|
246
|
+
**Scope block:**
|
|
247
|
+
|
|
248
|
+
| Field | Default | Description |
|
|
249
|
+
|-------|---------|-------------|
|
|
250
|
+
| `scope.target` | `main` | What to observe: `main`, `subagent`, `all`, `workflow`. |
|
|
251
|
+
| `scope.filter.agent_type` | — | Only monitor agents with these names. |
|
|
252
|
+
| `scope.filter.step_name` | — | Glob pattern for workflow step names. |
|
|
253
|
+
| `scope.filter.workflow` | — | Glob pattern for workflow names. |
|
|
254
|
+
|
|
255
|
+
Steering (injecting messages into the conversation) only fires for `main` scope.
|
|
256
|
+
Non-main scopes can still write findings to JSON files.
|
|
257
|
+
|
|
258
|
+
**Classify block:**
|
|
259
|
+
|
|
260
|
+
| Field | Default | Description |
|
|
261
|
+
|-------|---------|-------------|
|
|
262
|
+
| `classify.model` | `claude-sonnet-4-20250514` | Model for classification. Plain model ID uses `anthropic` provider. Use `provider/model` for other providers. |
|
|
263
|
+
| `classify.context` | `["tool_results", "assistant_text"]` | Context collector names. Any string accepted — unknown collectors produce empty string. |
|
|
264
|
+
| `classify.excludes` | `[]` | Monitor names — skip activation if any of these already steered this turn. |
|
|
265
|
+
| `classify.promptTemplate` | — | Path to `.md` Nunjucks template file. Searched in `.pi/monitors/`, `~/.pi/agent/monitors/`, then package `examples/`. Takes precedence over `prompt`. |
|
|
266
|
+
| `classify.prompt` | — | Inline classification prompt with `{placeholder}` substitution. Used when `promptTemplate` is absent. One of `promptTemplate` or `prompt` is required. |
|
|
267
|
+
|
|
268
|
+
**Actions block** — per verdict (`on_flag`, `on_new`, `on_clean`):
|
|
269
|
+
|
|
270
|
+
| Field | Description |
|
|
271
|
+
|-------|-------------|
|
|
272
|
+
| `steer` | Message to inject into conversation. `null` = no steering. Only effective for `scope.target: "main"`. |
|
|
273
|
+
| `write.path` | JSON file to write findings to. Relative paths resolve from `process.cwd()`, not from the monitor directory. |
|
|
274
|
+
| `write.merge` | `append` (add to array) or `upsert` (update by matching `id` field). |
|
|
275
|
+
| `write.array_field` | Which field in target JSON holds the array (e.g. `"gaps"`, `"findings"`). |
|
|
276
|
+
| `write.template` | Template mapping with `{finding_id}`, `{description}`, `{severity}`, `{monitor_name}`, `{timestamp}`. |
|
|
277
|
+
| `write.schema` | Optional schema path for documentation. Not enforced at runtime. |
|
|
278
|
+
| `learn_pattern` | If true, add new pattern to patterns file on `new` verdict. |
|
|
279
|
+
|
|
280
|
+
`on_clean` can be configured with a `write` action to log clean verdicts. Setting it to
|
|
281
|
+
`null` means no action on clean (the default behavior).
|
|
282
|
+
</fields>
|
|
283
|
+
|
|
284
|
+
<!-- when_conditions and context_collectors tables are generated from code registries — see Monitor Vocabulary section in SKILL.md -->
|
|
285
|
+
|
|
286
|
+
<patterns_file>
|
|
287
|
+
JSON array conforming to `schemas/monitor-pattern.schema.json`:
|
|
288
|
+
|
|
289
|
+
```json
|
|
290
|
+
[
|
|
291
|
+
{
|
|
292
|
+
"id": "empty-catch",
|
|
293
|
+
"description": "Silently catching exceptions with empty catch blocks",
|
|
294
|
+
"severity": "error",
|
|
295
|
+
"category": "error-handling",
|
|
296
|
+
"examples": ["try { ... } catch {}"],
|
|
297
|
+
"source": "bundled"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"id": "learned-pattern-abc",
|
|
301
|
+
"description": "Learned pattern from runtime detection",
|
|
302
|
+
"severity": "warning",
|
|
303
|
+
"source": "learned",
|
|
304
|
+
"learned_at": "2026-03-15T02:30:00.000Z"
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
| Field | Required | Description |
|
|
310
|
+
|-------|----------|-------------|
|
|
311
|
+
| `id` | yes | Stable identifier for dedup. Auto-generated for learned patterns: lowercased, non-alphanumeric replaced with hyphens, truncated to 60 chars. |
|
|
312
|
+
| `description` | yes | What this pattern detects. Used for dedup (exact match) when learning. |
|
|
313
|
+
| `severity` | no | `"error"`, `"warning"`, or `"info"`. Defaults to `"warning"` in prompt formatting. |
|
|
314
|
+
| `category` | no | Grouping key (e.g. `"error-handling"`, `"avoidance"`, `"deferral"`). |
|
|
315
|
+
| `examples` | no | Example manifestations. Stored but not surfaced in classification prompts. |
|
|
316
|
+
| `source` | no | `"bundled"`, `"learned"`, or `"user"`. Learned patterns are tagged `"learned"`. |
|
|
317
|
+
| `learned_at` | no | ISO timestamp for learned patterns. |
|
|
318
|
+
|
|
319
|
+
Patterns grow automatically when `learn_pattern: true` and a `NEW:` verdict is returned.
|
|
320
|
+
Dedup is by exact `description` match — duplicates are silently skipped.
|
|
321
|
+
|
|
322
|
+
**Critical**: If the patterns array is empty (file missing, empty array, or unparseable),
|
|
323
|
+
classification is skipped entirely for that activation. A monitor with no patterns does nothing.
|
|
324
|
+
</patterns_file>
|
|
325
|
+
|
|
326
|
+
<instructions_file>
|
|
327
|
+
JSON array of user rules (called "instructions" on disk, "rules" in the command surface):
|
|
328
|
+
|
|
329
|
+
```json
|
|
330
|
+
[
|
|
331
|
+
{ "text": "grep exit code 1 is not an error", "added_at": "2026-03-15T02:30:00.000Z" },
|
|
332
|
+
{ "text": "catch-and-log in event handlers is correct for non-critical extensions", "added_at": "2026-03-15T03:00:00.000Z" }
|
|
333
|
+
]
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Manage via `/monitors <name> rules` (list), `/monitors <name> rules add <text>` (add),
|
|
337
|
+
`/monitors <name> rules remove <n>` (remove by number), `/monitors <name> rules replace <n> <text>`
|
|
338
|
+
(replace by number). The LLM can also edit the `.instructions.json` file directly.
|
|
339
|
+
|
|
340
|
+
Rules are injected into the classification prompt under a preamble
|
|
341
|
+
"Operating instructions from the user (follow these strictly):" — only if the array is
|
|
342
|
+
non-empty. An empty array or missing file produces no rules block in the prompt.
|
|
343
|
+
</instructions_file>
|
|
344
|
+
|
|
345
|
+
<prompt_templates>
|
|
346
|
+
Monitors support two prompt rendering modes:
|
|
347
|
+
|
|
348
|
+
**Inline prompts** (`classify.prompt`) — simple `{placeholder}` string replacement. Good for
|
|
349
|
+
single-paragraph classifiers. All context collectors and built-in placeholders are available
|
|
350
|
+
as `{name}`.
|
|
351
|
+
|
|
352
|
+
**Nunjucks templates** (`classify.promptTemplate`) — `.md` files with full Nunjucks syntax:
|
|
353
|
+
conditionals (`{% if %}`), loops (`{% for %}`), template inheritance, filters. Used when
|
|
354
|
+
the classify prompt needs conditional sections (e.g., iteration-aware acknowledgment).
|
|
355
|
+
|
|
356
|
+
Template variables use `{{ name }}` syntax. All context collectors and built-in placeholders
|
|
357
|
+
are available: `{{ patterns }}`, `{{ instructions }}`, `{{ iteration }}`, plus any collectors
|
|
358
|
+
listed in `classify.context`.
|
|
359
|
+
|
|
360
|
+
When both `promptTemplate` and `prompt` are set, the template is tried first. If the template
|
|
361
|
+
file is not found or fails to render, the inline prompt is used as fallback.
|
|
362
|
+
|
|
363
|
+
**Iteration-aware acknowledgment pattern** — templates should include this block to support
|
|
364
|
+
monitor-agent dialogue (the agent acknowledging a steer and stating a plan):
|
|
365
|
+
|
|
366
|
+
```markdown
|
|
367
|
+
{% if iteration > 0 %}
|
|
368
|
+
NOTE: You have steered {{ iteration }} time(s) already this session.
|
|
369
|
+
The agent's latest response is below. If the agent explicitly acknowledged
|
|
370
|
+
the issue and stated a concrete plan to address it (not just "noted" but
|
|
371
|
+
a specific action), reply CLEAN to allow the agent to follow through.
|
|
372
|
+
Re-flag only if the agent ignored or deflected the steer.
|
|
373
|
+
|
|
374
|
+
Agent response:
|
|
375
|
+
{{ assistant_text }}
|
|
376
|
+
{% endif %}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
This requires `assistant_text` in the `classify.context` array. When the classifier sees
|
|
380
|
+
genuine acknowledgment, it replies CLEAN, which resets `whileCount` to 0 and gives the agent
|
|
381
|
+
a fresh turn without re-flagging.
|
|
382
|
+
|
|
383
|
+
**Template search order** (first match wins):
|
|
384
|
+
1. `.pi/monitors/<template-path>` — project-level override
|
|
385
|
+
2. `~/.pi/agent/monitors/<template-path>` — user-level
|
|
386
|
+
3. Package `examples/<template-path>` — builtin
|
|
387
|
+
|
|
388
|
+
All four bundled monitors ship with Nunjucks templates in `examples/<name>/classify.md`.
|
|
389
|
+
</prompt_templates>
|
|
390
|
+
|
|
391
|
+
<verdict_format>
|
|
392
|
+
The classification LLM must respond with one of:
|
|
393
|
+
|
|
394
|
+
- `CLEAN` — no issue detected. Resets consecutive steer counter to 0.
|
|
395
|
+
- `FLAG:<description>` — known pattern matched. Triggers `on_flag` action.
|
|
396
|
+
- `NEW:<pattern>|<description>` — novel issue. The text before `|` becomes the learned pattern description; the text after `|` becomes the finding description. If no `|` is present, the full text after `NEW:` is used for both. Triggers `on_new` action.
|
|
397
|
+
|
|
398
|
+
Any response that does not start with `CLEAN`, `FLAG:`, or `NEW:` is treated as `CLEAN`.
|
|
399
|
+
|
|
400
|
+
Classification calls use `maxTokens: 150`.
|
|
401
|
+
</verdict_format>
|
|
402
|
+
|
|
403
|
+
<runtime_behavior>
|
|
404
|
+
|
|
405
|
+
**Dedup**: A monitor will not re-classify the same user text. Once a user message has been
|
|
406
|
+
classified, the monitor skips until the user text changes. This prevents redundant
|
|
407
|
+
side-channel LLM calls within the same user turn.
|
|
408
|
+
|
|
409
|
+
**Ceiling and escalation**: After `ceiling` consecutive steers (flag/new verdicts without
|
|
410
|
+
an intervening clean), the monitor escalates. With `escalate: "ask"`, the user is prompted
|
|
411
|
+
to continue or dismiss. With `escalate: "dismiss"`, the monitor is silently dismissed for
|
|
412
|
+
the session. A `CLEAN` verdict resets the consecutive steer counter.
|
|
413
|
+
|
|
414
|
+
**Turn exclusion**: The `excludes` array prevents double-steering. If monitor A steers in
|
|
415
|
+
a turn, and monitor B has `"excludes": ["A"]`, monitor B skips that turn. Exclusion tracking
|
|
416
|
+
resets at `turn_start`.
|
|
417
|
+
|
|
418
|
+
**Buffered steer delivery**: Monitors on `message_end` or `turn_end` buffer their steer
|
|
419
|
+
messages and deliver them at `agent_end`. This is because pi's async event queue processes
|
|
420
|
+
extension handlers after the agent loop has already checked for steering messages. The
|
|
421
|
+
buffer is drained at `agent_end` — only the first buffered steer fires per agent run; the
|
|
422
|
+
corrected response re-triggers monitors naturally for any remaining issues. Monitors on
|
|
423
|
+
`agent_end` or `command` events deliver steers immediately (they already run post-loop).
|
|
424
|
+
|
|
425
|
+
**Abort**: Classification calls are aborted when the agent ends (via `agent_end` event).
|
|
426
|
+
Aborted classifications produce no verdict and no action.
|
|
427
|
+
|
|
428
|
+
**Write action**: Relative `write.path` values resolve from `process.cwd()`, not from the
|
|
429
|
+
monitor directory. Parent directories are created automatically. If the target file doesn't
|
|
430
|
+
exist or is unparseable, a fresh object is created. The `upsert` merge strategy matches on
|
|
431
|
+
the `id` field of array entries.
|
|
432
|
+
</runtime_behavior>
|
|
433
|
+
|
|
434
|
+
<commands>
|
|
435
|
+
All monitor management is through the `/monitors` command. Subcommands are
|
|
436
|
+
discoverable via pi's TUI autocomplete — typing `/monitors ` shows available
|
|
437
|
+
monitor names and global commands; selecting a monitor shows its verbs.
|
|
438
|
+
|
|
439
|
+
| Command | Description |
|
|
440
|
+
|---------|-------------|
|
|
441
|
+
| `/monitors` | List all monitors with global on/off state and per-monitor status |
|
|
442
|
+
| `/monitors on` | Enable all monitoring (session default) |
|
|
443
|
+
| `/monitors off` | Pause all monitoring for this session |
|
|
444
|
+
| `/monitors <name>` | Inspect a monitor: description, event, state, rule count, pattern count |
|
|
445
|
+
| `/monitors <name> rules` | List current rules (numbered) |
|
|
446
|
+
| `/monitors <name> rules add <text>` | Add a rule to calibrate the classifier |
|
|
447
|
+
| `/monitors <name> rules remove <n>` | Remove a rule by number |
|
|
448
|
+
| `/monitors <name> rules replace <n> <text>` | Replace a rule by number |
|
|
449
|
+
| `/monitors <name> patterns` | List current patterns (numbered, with severity and source) |
|
|
450
|
+
| `/monitors <name> dismiss` | Dismiss a monitor for this session |
|
|
451
|
+
| `/monitors <name> reset` | Reset a monitor's state and un-dismiss it |
|
|
452
|
+
|
|
453
|
+
Monitors with `event: "command"` also register `/<name>` as a programmatic trigger
|
|
454
|
+
for other extensions or workflows to invoke classification directly.
|
|
455
|
+
</commands>
|
|
456
|
+
|
|
457
|
+
<bundled_monitors>
|
|
458
|
+
Four example monitors ship in `examples/` and are seeded on first run. Each has a
|
|
459
|
+
Nunjucks classify template in `examples/<name>/classify.md` with iteration-aware
|
|
460
|
+
acknowledgment support:
|
|
461
|
+
|
|
462
|
+
**fragility** (`message_end`, `when: has_tool_results`)
|
|
463
|
+
Watches for unaddressed fragilities after tool use — errors, warnings, or broken state the
|
|
464
|
+
agent noticed but chose not to fix. Steers with "Fix the issue you left behind." Writes
|
|
465
|
+
findings to `.workflow/gaps.json` under `category: "fragility"`. Excludes: none. Ceiling: 5.
|
|
466
|
+
12 bundled patterns across categories: avoidance (dismiss-preexisting, not-my-change,
|
|
467
|
+
blame-environment, workaround-over-root-cause, elaborate-workaround-for-fixable),
|
|
468
|
+
error-handling (empty-catch, happy-path-only, early-return-on-unexpected,
|
|
469
|
+
undocumented-delegation, silent-fallback), deferral (todo-instead-of-fix,
|
|
470
|
+
prose-without-action).
|
|
471
|
+
|
|
472
|
+
**hedge** (`turn_end`, `when: always`)
|
|
473
|
+
Detects when the assistant deviates from what the user actually said — substituting
|
|
474
|
+
questions, projecting intent, or deflecting instead of answering. Steers with "Address
|
|
475
|
+
what the user actually said." Does not write to files (steer-only). Excludes: `["fragility"]`
|
|
476
|
+
(skips if fragility already steered this turn). Ceiling: 3.
|
|
477
|
+
8 bundled patterns across categories: substitution (rephrase-question, reinterpret-words),
|
|
478
|
+
projection (assume-intent, attribute-position), augmentation (add-questions),
|
|
479
|
+
deflection (ask-permission, qualify-yesno, counter-question).
|
|
480
|
+
|
|
481
|
+
**work-quality** (`command`, `when: always`)
|
|
482
|
+
On-demand work quality analysis invoked via `/work-quality`. Analyzes user request, tool
|
|
483
|
+
calls, and assistant response for quality issues. Writes findings to `.workflow/gaps.json`
|
|
484
|
+
under `category: "work-quality"`. Ceiling: 3.
|
|
485
|
+
11 bundled patterns across categories: methodology (trial-and-error, symptom-fix,
|
|
486
|
+
double-edit, edit-without-read, insanity-retry, no-plan), verification (no-verify),
|
|
487
|
+
scope (excessive-changes, wrong-problem), quality (copy-paste), cleanup (debug-artifacts).
|
|
488
|
+
|
|
489
|
+
**commit-hygiene** (`agent_end`, `when: has_file_writes`)
|
|
490
|
+
Fires when the agent finishes a turn that included file writes. Checks tool call history
|
|
491
|
+
for git commit commands. If no commit occurred, steers to commit. If committed with a
|
|
492
|
+
generic or certainty-language message, steers to improve. Does not write findings — commits
|
|
493
|
+
are their own artifact. Ceiling: 3.
|
|
494
|
+
6 bundled patterns across categories: missing-commit (no-commit), message-quality
|
|
495
|
+
(generic-message, certainty-language, no-context), commit-safety (amend-not-new, force-push).
|
|
496
|
+
</bundled_monitors>
|
|
497
|
+
|
|
498
|
+
<disabling_monitors>
|
|
499
|
+
**Session-level** (temporary):
|
|
500
|
+
- `/monitors off` — pauses all monitoring for the current session
|
|
501
|
+
- `/monitors <name> dismiss` — silences a single monitor for the session
|
|
502
|
+
- `/monitors <name> reset` — un-dismisses and resets a monitor's state
|
|
503
|
+
|
|
504
|
+
**Permanent**:
|
|
505
|
+
- Delete its `.monitor.json` file (and optionally its `.patterns.json` and `.instructions.json`)
|
|
506
|
+
- Or empty its patterns array — a monitor with zero patterns skips classification entirely
|
|
507
|
+
- To disable all monitoring: remove all `.monitor.json` files from `.pi/monitors/` and
|
|
508
|
+
`~/.pi/agent/monitors/`. The extension exits silently when zero monitors are discovered.
|
|
509
|
+
|
|
510
|
+
Monitors also auto-silence at their ceiling. With `escalate: "ask"`, the user is prompted
|
|
511
|
+
to continue or dismiss. With `escalate: "dismiss"`, the monitor silences automatically.
|
|
512
|
+
</disabling_monitors>
|
|
513
|
+
|
|
514
|
+
<creating_monitors>
|
|
515
|
+
When the user asks to create a monitor — either from a described behavior ("flag responses
|
|
516
|
+
that end with questions") or from a discovered need during conversation ("that response
|
|
517
|
+
did X wrong, make a monitor for it") — follow this workflow:
|
|
518
|
+
|
|
519
|
+
**Step 1: Determine the detection target.** What specific behavior in the assistant's output
|
|
520
|
+
should trigger a flag? Translate the user's description into concrete, observable patterns.
|
|
521
|
+
|
|
522
|
+
**Step 2: Choose event and when.** Match the detection target to the right trigger:
|
|
523
|
+
- Response content issues (trailing questions, lazy options, tone) → `turn_end`, `when: always`
|
|
524
|
+
- Tool use issues (no commit, no test, bad edits) → `agent_end`, `when: has_file_writes` or `has_tool_results`
|
|
525
|
+
- Post-action fragility (ignoring errors) → `message_end`, `when: has_tool_results`
|
|
526
|
+
- On-demand analysis → `command`, `when: always`
|
|
527
|
+
|
|
528
|
+
**Step 3: Choose context collectors.** What data does the classifier need to see?
|
|
529
|
+
- Checking the assistant's final response text → `assistant_text`
|
|
530
|
+
- Checking what the user asked (to compare against response) → `user_text`
|
|
531
|
+
- Checking what tools were called → `tool_calls`
|
|
532
|
+
- Checking tool outputs for errors/warnings → `tool_results`
|
|
533
|
+
- Checking git state → `git_status`
|
|
534
|
+
- Include `assistant_text` if you want iteration-aware acknowledgment (recommended).
|
|
535
|
+
|
|
536
|
+
**Step 4: Write the patterns file.** Each pattern is a specific, observable anti-pattern.
|
|
537
|
+
Write descriptions that a classifier LLM can match against the collected context. Start with
|
|
538
|
+
3-8 seed patterns. Set `learn: true` so the monitor grows its pattern library from `NEW:`
|
|
539
|
+
verdicts at runtime.
|
|
540
|
+
|
|
541
|
+
**Step 5: Write the classify template.** Use a Nunjucks `.md` file for anything beyond
|
|
542
|
+
trivial classification. The template must:
|
|
543
|
+
- Present the collected context to the classifier
|
|
544
|
+
- List the patterns to check against
|
|
545
|
+
- Include the verdict format instructions (CLEAN/FLAG/NEW)
|
|
546
|
+
- Include the iteration-aware acknowledgment block if `assistant_text` is collected
|
|
547
|
+
|
|
548
|
+
**Step 6: Write the monitor definition.** Wire everything together in the `.monitor.json`.
|
|
549
|
+
|
|
550
|
+
**Step 7: Create empty instructions file.** Write `[]` so the user can add calibration
|
|
551
|
+
rules via `/monitors <name> rules add <text>`.
|
|
552
|
+
|
|
553
|
+
**Step 8: Activate.** After creating the files, tell the user to run `/reload 3` to
|
|
554
|
+
reload extensions and activate the new monitor without restarting the session.
|
|
555
|
+
|
|
556
|
+
### Example: response-mandates monitor
|
|
557
|
+
|
|
558
|
+
User says: "create a monitor that flags responses ending with questions and responses
|
|
559
|
+
that present lazy deferral options."
|
|
560
|
+
|
|
561
|
+
**Files to create:**
|
|
562
|
+
|
|
563
|
+
1. `.pi/monitors/response-mandates.monitor.json`:
|
|
564
|
+
|
|
565
|
+
```json
|
|
566
|
+
{
|
|
567
|
+
"name": "response-mandates",
|
|
568
|
+
"description": "Flags responses that violate communication mandates: trailing questions, lazy deferral options, non-optimal solutions",
|
|
569
|
+
"event": "turn_end",
|
|
570
|
+
"when": "always",
|
|
571
|
+
"scope": { "target": "main" },
|
|
572
|
+
"classify": {
|
|
573
|
+
"model": "claude-sonnet-4-20250514",
|
|
574
|
+
"context": ["assistant_text", "user_text"],
|
|
575
|
+
"excludes": ["fragility"],
|
|
576
|
+
"promptTemplate": "response-mandates/classify.md"
|
|
577
|
+
},
|
|
578
|
+
"patterns": { "path": "response-mandates.patterns.json", "learn": true },
|
|
579
|
+
"instructions": { "path": "response-mandates.instructions.json" },
|
|
580
|
+
"actions": {
|
|
581
|
+
"on_flag": { "steer": "Rewrite your response: report findings and state actions — do not end with a question or present options that defer proper work." },
|
|
582
|
+
"on_new": { "steer": "Rewrite your response: report findings and state actions — do not end with a question or present options that defer proper work.", "learn_pattern": true },
|
|
583
|
+
"on_clean": null
|
|
584
|
+
},
|
|
585
|
+
"ceiling": 3,
|
|
586
|
+
"escalate": "ask"
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
2. `.pi/monitors/response-mandates/classify.md`:
|
|
591
|
+
|
|
592
|
+
```markdown
|
|
593
|
+
The user said:
|
|
594
|
+
"{{ user_text }}"
|
|
595
|
+
|
|
596
|
+
The assistant's response:
|
|
597
|
+
"{{ assistant_text }}"
|
|
598
|
+
|
|
599
|
+
{{ instructions }}
|
|
600
|
+
|
|
601
|
+
Check the assistant's response against these anti-patterns:
|
|
602
|
+
{{ patterns }}
|
|
603
|
+
|
|
604
|
+
Specifically check:
|
|
605
|
+
1. Does the response end with a question to the user? The final sentence or paragraph
|
|
606
|
+
should not be a question unless the user explicitly asked to be consulted. Rhetorical
|
|
607
|
+
questions, permission-seeking ("shall I...?", "would you like...?"), and steering
|
|
608
|
+
questions ("what do you think?") are all violations.
|
|
609
|
+
2. Does the response present options where one or more options leave known issues
|
|
610
|
+
unaddressed? If a problem has been identified, every option presented must address it.
|
|
611
|
+
Options that defer proper work to a vague future ("we could address this later",
|
|
612
|
+
"for now we can...") are violations.
|
|
613
|
+
3. Does the response propose a non-durable solution when a durable one is known? Workarounds,
|
|
614
|
+
temporary fixes, and partial solutions when the root cause is understood are violations.
|
|
615
|
+
|
|
616
|
+
{% if iteration > 0 %}
|
|
617
|
+
NOTE: You have steered {{ iteration }} time(s) already this session.
|
|
618
|
+
If the agent explicitly acknowledged the mandate violation and rewrote its response
|
|
619
|
+
without the violation, reply CLEAN. Re-flag only if the violation persists.
|
|
620
|
+
|
|
621
|
+
Agent response:
|
|
622
|
+
{{ assistant_text }}
|
|
623
|
+
{% endif %}
|
|
624
|
+
|
|
625
|
+
Reply CLEAN if the response follows all mandates.
|
|
626
|
+
Reply FLAG:<description> if a known pattern was matched.
|
|
627
|
+
Reply NEW:<pattern>|<description> if a violation not covered by existing patterns was detected.
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
3. `.pi/monitors/response-mandates.patterns.json`:
|
|
631
|
+
|
|
632
|
+
```json
|
|
633
|
+
[
|
|
634
|
+
{ "id": "trailing-question", "description": "Response ends with a question to the user instead of reporting and acting", "severity": "error", "category": "communication", "source": "bundled" },
|
|
635
|
+
{ "id": "permission-seeking", "description": "Asks permission before acting when the user has already given direction", "severity": "warning", "category": "communication", "source": "bundled" },
|
|
636
|
+
{ "id": "steering-question", "description": "Ends with 'what do you think?', 'does that sound right?', or similar steering questions", "severity": "error", "category": "communication", "source": "bundled" },
|
|
637
|
+
{ "id": "lazy-deferral", "description": "Presents options that defer known issues to a vague future ('we can address later', 'for now')", "severity": "error", "category": "anti-laziness", "source": "bundled" },
|
|
638
|
+
{ "id": "fragility-tolerant-option", "description": "Offers an option that leaves identified fragility unaddressed", "severity": "error", "category": "anti-laziness", "source": "bundled" },
|
|
639
|
+
{ "id": "workaround-over-fix", "description": "Proposes workaround when root cause is understood and fixable", "severity": "warning", "category": "anti-laziness", "source": "bundled" }
|
|
640
|
+
]
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
4. `.pi/monitors/response-mandates.instructions.json`:
|
|
644
|
+
|
|
645
|
+
```json
|
|
646
|
+
[]
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
After creating all files, tell the user: "Monitor created. Run `/reload 3` to activate
|
|
650
|
+
it in this session."
|
|
651
|
+
</creating_monitors>
|
|
652
|
+
|
|
653
|
+
<modifying_monitors>
|
|
654
|
+
**Adding patterns** — When the user identifies a new anti-pattern during conversation
|
|
655
|
+
("that kind of response should also be flagged"), add it to the patterns JSON file.
|
|
656
|
+
Each pattern needs `id`, `description`, `severity`, and `source: "user"`.
|
|
657
|
+
|
|
658
|
+
**Adding rules** — Use the `monitors-rules` tool or `/monitors <name> rules add <text>`
|
|
659
|
+
to add calibration rules. Rules fine-tune the classifier without changing patterns.
|
|
660
|
+
Example: "responses that end with 'let me know' are not questions."
|
|
661
|
+
|
|
662
|
+
**Changing the classify prompt** — Edit the Nunjucks template file or the inline prompt.
|
|
663
|
+
For template-based monitors, edit the `.md` file. For inline monitors, edit the `prompt`
|
|
664
|
+
field in the `.monitor.json`.
|
|
665
|
+
|
|
666
|
+
**Upgrading inline to template** — When a monitor needs conditionals (iteration-aware
|
|
667
|
+
acknowledgment, optional context sections), create a `<name>/classify.md` template file
|
|
668
|
+
in `.pi/monitors/` and add `"promptTemplate": "<name>/classify.md"` to the classify block.
|
|
669
|
+
The inline `prompt` remains as fallback.
|
|
670
|
+
|
|
671
|
+
**Adjusting sensitivity** — Lower the `ceiling` to escalate sooner if the monitor is
|
|
672
|
+
over-firing. Raise it to give the agent more chances. Set `escalate: "dismiss"` to
|
|
673
|
+
auto-silence without prompting.
|
|
674
|
+
|
|
675
|
+
After any file changes, tell the user to run `/reload 3` to pick up the changes.
|
|
676
|
+
</modifying_monitors>
|
|
677
|
+
|
|
678
|
+
<success_criteria>
|
|
679
|
+
- Monitor `.monitor.json` validates against `schemas/monitor.schema.json`
|
|
680
|
+
- Patterns `.patterns.json` validates against `schemas/monitor-pattern.schema.json`
|
|
681
|
+
- Patterns array is non-empty (empty patterns = monitor does nothing)
|
|
682
|
+
- Classification prompt (template or inline) includes `{{ patterns }}` / `{patterns}` and verdict format instructions (CLEAN/FLAG/NEW)
|
|
683
|
+
- If using `promptTemplate`, the `.md` file exists at the declared path relative to one of the template search directories
|
|
684
|
+
- If using templates, `assistant_text` is in `classify.context` for iteration-aware acknowledgment
|
|
685
|
+
- Actions specify `steer` for `scope.target: "main"` monitors, `write` for findings output
|
|
686
|
+
- `write.path` is set relative to project cwd, not monitor directory
|
|
687
|
+
- `excludes` lists monitors that should not double-steer in the same turn
|
|
688
|
+
- Instructions file exists (even if empty `[]`) to enable `/monitors <name> rules add <text>` calibration
|
|
689
|
+
- After creating or modifying monitor files, remind user to run `/reload 3`
|
|
690
|
+
</success_criteria>
|
|
691
|
+
|
|
692
|
+
*Generated from source by `scripts/generate-skills.js` — do not edit by hand.*
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Bundled Resources
|
|
2
|
+
|
|
3
|
+
## schemas/ (2 files)
|
|
4
|
+
|
|
5
|
+
- `schemas/monitor-pattern.schema.json`
|
|
6
|
+
- `schemas/monitor.schema.json`
|
|
7
|
+
|
|
8
|
+
## examples/ (20 files)
|
|
9
|
+
|
|
10
|
+
- `examples/commit-hygiene/classify.md`
|
|
11
|
+
- `examples/commit-hygiene.instructions.json`
|
|
12
|
+
- `examples/commit-hygiene.monitor.json`
|
|
13
|
+
- `examples/commit-hygiene.patterns.json`
|
|
14
|
+
- `examples/fragility/classify.md`
|
|
15
|
+
- `examples/fragility.instructions.json`
|
|
16
|
+
- `examples/fragility.monitor.json`
|
|
17
|
+
- `examples/fragility.patterns.json`
|
|
18
|
+
- `examples/hedge/classify.md`
|
|
19
|
+
- `examples/hedge.instructions.json`
|
|
20
|
+
- `examples/hedge.monitor.json`
|
|
21
|
+
- `examples/hedge.patterns.json`
|
|
22
|
+
- `examples/unauthorized-action/classify.md`
|
|
23
|
+
- `examples/unauthorized-action.instructions.json`
|
|
24
|
+
- `examples/unauthorized-action.monitor.json`
|
|
25
|
+
- `examples/unauthorized-action.patterns.json`
|
|
26
|
+
- `examples/work-quality/classify.md`
|
|
27
|
+
- `examples/work-quality.instructions.json`
|
|
28
|
+
- `examples/work-quality.monitor.json`
|
|
29
|
+
- `examples/work-quality.patterns.json`
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pi-project
|
|
3
|
+
description: >
|
|
4
|
+
Schema-driven project state management with typed JSON blocks, schema
|
|
5
|
+
validation, planning lifecycle, and cross-block referential integrity. Use when
|
|
6
|
+
managing .project/ blocks, scaffolding project structure, validating project
|
|
7
|
+
state, or adding work items.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<tools_reference>
|
|
11
|
+
<tool name="append-block-item">
|
|
12
|
+
Append an item to an array in a project block file. Schema validation is automatic.
|
|
13
|
+
|
|
14
|
+
*Append items to project blocks (gaps, decisions, or any user-defined block)*
|
|
15
|
+
|
|
16
|
+
| Parameter | Type | Required | Description |
|
|
17
|
+
|-----------|------|----------|-------------|
|
|
18
|
+
| `block` | string | yes | Block name (e.g., 'gaps', 'decisions') |
|
|
19
|
+
| `arrayKey` | string | yes | Array key in the block (e.g., 'gaps', 'decisions') |
|
|
20
|
+
| `item` | unknown | yes | Item object to append — must conform to block schema |
|
|
21
|
+
</tool>
|
|
22
|
+
|
|
23
|
+
<tool name="update-block-item">
|
|
24
|
+
Update fields on an item in a project block array. Finds by predicate field match.
|
|
25
|
+
|
|
26
|
+
*Update items in project blocks — change status, add details, mark resolved*
|
|
27
|
+
|
|
28
|
+
| Parameter | Type | Required | Description |
|
|
29
|
+
|-----------|------|----------|-------------|
|
|
30
|
+
| `block` | string | yes | Block name (e.g., 'gaps', 'decisions') |
|
|
31
|
+
| `arrayKey` | string | yes | Array key in the block |
|
|
32
|
+
| `match` | object | yes | Fields to match (e.g., { id: 'gap-123' }) |
|
|
33
|
+
| `updates` | object | yes | Fields to update (e.g., { status: 'resolved' }) |
|
|
34
|
+
</tool>
|
|
35
|
+
|
|
36
|
+
<tool name="read-block">
|
|
37
|
+
Read a project block file as structured JSON.
|
|
38
|
+
|
|
39
|
+
*Read a project block as structured JSON*
|
|
40
|
+
|
|
41
|
+
| Parameter | Type | Required | Description |
|
|
42
|
+
|-----------|------|----------|-------------|
|
|
43
|
+
| `block` | string | yes | Block name (e.g., 'gaps', 'tasks', 'requirements') |
|
|
44
|
+
</tool>
|
|
45
|
+
|
|
46
|
+
<tool name="write-block">
|
|
47
|
+
Write or replace an entire project block with schema validation.
|
|
48
|
+
|
|
49
|
+
*Write or replace a project block with schema validation*
|
|
50
|
+
|
|
51
|
+
| Parameter | Type | Required | Description |
|
|
52
|
+
|-----------|------|----------|-------------|
|
|
53
|
+
| `block` | string | yes | Block name (e.g., 'project', 'architecture') |
|
|
54
|
+
| `data` | unknown | yes | Complete block data — must conform to block schema |
|
|
55
|
+
</tool>
|
|
56
|
+
|
|
57
|
+
<tool name="project-status">
|
|
58
|
+
Get derived project state — source metrics, block summaries, planning lifecycle status.
|
|
59
|
+
|
|
60
|
+
*Get project state — source metrics, block summaries, planning lifecycle status*
|
|
61
|
+
|
|
62
|
+
</tool>
|
|
63
|
+
|
|
64
|
+
<tool name="project-validate">
|
|
65
|
+
Validate cross-block referential integrity — check that IDs referenced across blocks exist.
|
|
66
|
+
|
|
67
|
+
*Validate cross-block referential integrity*
|
|
68
|
+
|
|
69
|
+
</tool>
|
|
70
|
+
|
|
71
|
+
<tool name="project-init">
|
|
72
|
+
Initialize .project/ directory with default schemas and empty block files.
|
|
73
|
+
|
|
74
|
+
*Initialize .project/ directory with default schemas and blocks*
|
|
75
|
+
|
|
76
|
+
</tool>
|
|
77
|
+
|
|
78
|
+
</tools_reference>
|
|
79
|
+
|
|
80
|
+
<commands_reference>
|
|
81
|
+
<command name="/project">
|
|
82
|
+
Project state management
|
|
83
|
+
|
|
84
|
+
Subcommands: `init`, `status`, `add-work`, `validate`
|
|
85
|
+
</command>
|
|
86
|
+
|
|
87
|
+
</commands_reference>
|
|
88
|
+
|
|
89
|
+
<events>
|
|
90
|
+
`session_start`
|
|
91
|
+
</events>
|
|
92
|
+
|
|
93
|
+
<bundled_resources>
|
|
94
|
+
22 defaults bundled.
|
|
95
|
+
See references/bundled-resources.md for full inventory.
|
|
96
|
+
</bundled_resources>
|
|
97
|
+
|
|
98
|
+
<planning_vocabulary>
|
|
99
|
+
|
|
100
|
+
**Block Types:**
|
|
101
|
+
|
|
102
|
+
| Block | Title | Array Key | Item Fields |
|
|
103
|
+
|-------|-------|-----------|-------------|
|
|
104
|
+
| `architecture` | Architecture | `modules` | name, file, responsibility, dependencies? (array), lines? (integer) |
|
|
105
|
+
| `audit` | audit | `checks` | id, description, status (string (pass|fail|warn|skip)), category?, details? |
|
|
106
|
+
| `conformance-reference` | conformance-reference | `principles` | id, name, description?, rules (array) |
|
|
107
|
+
| `decisions` | Decisions | `decisions` | id, decision, rationale, phase? (string|integer), status (string (decided|tentative|revisit|superseded)), context? |
|
|
108
|
+
| `domain` | Domain Knowledge | `entries` | id, title, content, category (string (research|reference|domain-rule|prior-art|constraint)), source?, confidence? (string (high|medium|low)), related_requirements? (array), tags? (array) |
|
|
109
|
+
| `gaps` | Gaps | `gaps` | id, description, status (string (open|resolved|deferred)), category (string (missing|incomplete|defect|improvement|technical-debt|question)), priority (string (low|medium|high|critical)), phase? (string|integer), resolved_by?, source? (string (human|agent|monitor|workflow)), details? |
|
|
110
|
+
| `handoff` | Handoff | `current_tasks` | |
|
|
111
|
+
| `phase` | Phase | `success_criteria` | criterion, verify_method (string (command|inspect|test)) |
|
|
112
|
+
| `project` | Project Identity | `target_users` | |
|
|
113
|
+
| `rationale` | Design Rationale | `rationales` | id, title, narrative, related_decisions? (array), phase? (string|integer), context? |
|
|
114
|
+
| `requirements` | Requirements | `requirements` | id, description, type (string (functional|non-functional|constraint|integration)), status (string (proposed|accepted|deferred|implemented|verified)), priority (string (must|should|could|wont)), acceptance_criteria? (array), source? (string (human|agent|analysis)), traces_to? (array), depends_on? (array) |
|
|
115
|
+
| `tasks` | Tasks | `tasks` | id, description, status (string (planned|in-progress|completed|blocked|cancelled)), phase? (string|integer), files? (array), acceptance_criteria? (array), depends_on? (array), assigned_agent?, verification?, notes? |
|
|
116
|
+
| `verification` | Verification | `verifications` | id, target, target_type (string (task|phase|requirement)), status (string (passed|failed|partial|skipped)), method (string (command|inspect|test)), evidence?, timestamp?, criteria_results? (array) |
|
|
117
|
+
|
|
118
|
+
**Status Enums:**
|
|
119
|
+
|
|
120
|
+
| Block | Field | Values |
|
|
121
|
+
|-------|-------|--------|
|
|
122
|
+
| `audit` | `status` | pass, fail, warn, skip |
|
|
123
|
+
| `audit` | `severity` | error, warning, info |
|
|
124
|
+
| `decisions` | `status` | decided, tentative, revisit, superseded |
|
|
125
|
+
| `domain` | `category` | research, reference, domain-rule, prior-art, constraint |
|
|
126
|
+
| `domain` | `confidence` | high, medium, low |
|
|
127
|
+
| `gaps` | `status` | open, resolved, deferred |
|
|
128
|
+
| `gaps` | `category` | missing, incomplete, defect, improvement, technical-debt, question |
|
|
129
|
+
| `gaps` | `priority` | low, medium, high, critical |
|
|
130
|
+
| `gaps` | `source` | human, agent, monitor, workflow |
|
|
131
|
+
| `phase` | `status` | planned, in-progress, completed |
|
|
132
|
+
| `phase` | `verify_method` | command, inspect, test |
|
|
133
|
+
| `phase` | `status` | planned, in-progress, completed |
|
|
134
|
+
| `project` | `status` | inception, planning, development, maintenance, complete |
|
|
135
|
+
| `requirements` | `type` | functional, non-functional, constraint, integration |
|
|
136
|
+
| `requirements` | `status` | proposed, accepted, deferred, implemented, verified |
|
|
137
|
+
| `requirements` | `priority` | must, should, could, wont |
|
|
138
|
+
| `requirements` | `source` | human, agent, analysis |
|
|
139
|
+
| `tasks` | `status` | planned, in-progress, completed, blocked, cancelled |
|
|
140
|
+
| `verification` | `target_type` | task, phase, requirement |
|
|
141
|
+
| `verification` | `status` | passed, failed, partial, skipped |
|
|
142
|
+
| `verification` | `method` | command, inspect, test |
|
|
143
|
+
|
|
144
|
+
</planning_vocabulary>
|
|
145
|
+
|
|
146
|
+
<objective>
|
|
147
|
+
pi-project manages structured project state in `.project/` — a directory of JSON block files validated against schemas.
|
|
148
|
+
</objective>
|
|
149
|
+
|
|
150
|
+
<block_files>
|
|
151
|
+
Blocks are JSON files in `.project/` (e.g., `gaps.json`, `decisions.json`). Each block has a corresponding schema in `.project/schemas/`. When you write to a block via the tools, the data is validated against its schema before persisting. Writes are atomic (tmp file + rename).
|
|
152
|
+
</block_files>
|
|
153
|
+
|
|
154
|
+
<schema_validation>
|
|
155
|
+
Every block write validates against `.project/schemas/<blockname>.schema.json`. If the schema file doesn't exist, writes proceed without validation. Validation errors include the specific JSON Schema violations.
|
|
156
|
+
</schema_validation>
|
|
157
|
+
|
|
158
|
+
<project_init>
|
|
159
|
+
`/project init` scaffolds the `.project/` directory with default schemas and empty block files from the package's `defaults/` directory. Idempotent — skips files that already exist.
|
|
160
|
+
</project_init>
|
|
161
|
+
|
|
162
|
+
<project_status>
|
|
163
|
+
`/project status` derives project state dynamically from the filesystem:
|
|
164
|
+
- Source file count and line count (`.ts` files excluding tests)
|
|
165
|
+
- Test count and test file count
|
|
166
|
+
- Schema count, block count, phase count
|
|
167
|
+
- Block summaries with array item counts and status distributions
|
|
168
|
+
- Requirements summary (total, by status, by priority) — from requirements.json
|
|
169
|
+
- Tasks summary (total, by status) — from tasks.json
|
|
170
|
+
- Domain entry count — from domain.json
|
|
171
|
+
- Verification summary (total, passed, failed) — from verification.json
|
|
172
|
+
- Handoff presence — whether handoff.json exists
|
|
173
|
+
- Recent git commits
|
|
174
|
+
- Current phase detection
|
|
175
|
+
</project_status>
|
|
176
|
+
|
|
177
|
+
<project_add_work>
|
|
178
|
+
`/project add-work` discovers appendable blocks (blocks with array schemas), reads their schemas, and sends a structured instruction to the LLM to extract items from the conversation into the typed blocks. This is a follow-up message that triggers the LLM to use the `append-block-item` tool.
|
|
179
|
+
</project_add_work>
|
|
180
|
+
|
|
181
|
+
<duplicate_detection>
|
|
182
|
+
`append-block-item` checks for duplicate items by `id` field before appending. If an item with the same `id` already exists in the target array, it returns a message instead of appending.
|
|
183
|
+
</duplicate_detection>
|
|
184
|
+
|
|
185
|
+
<project_validate>
|
|
186
|
+
`/project validate` checks cross-block referential integrity:
|
|
187
|
+
- task.phase references a valid phase
|
|
188
|
+
- task.depends_on references valid task IDs
|
|
189
|
+
- decision.phase references a valid phase
|
|
190
|
+
- gap.resolved_by references a valid ID
|
|
191
|
+
- requirement.traces_to references valid phase/task IDs
|
|
192
|
+
- requirement.depends_on references valid requirement IDs
|
|
193
|
+
- verification.target references a valid target ID
|
|
194
|
+
- rationale.related_decisions references valid decision IDs
|
|
195
|
+
|
|
196
|
+
Returns errors (broken dependency references) and warnings (unresolved cross-references).
|
|
197
|
+
</project_validate>
|
|
198
|
+
|
|
199
|
+
<planning_lifecycle>
|
|
200
|
+
The default schemas support a full planning lifecycle:
|
|
201
|
+
- **project.json** — identity, vision, goals, constraints, scope, status
|
|
202
|
+
- **domain.json** — research findings, reference material, domain rules
|
|
203
|
+
- **requirements.json** — functional/non-functional requirements with MoSCoW priority and lifecycle states
|
|
204
|
+
- **architecture.json** — modules, patterns, boundaries
|
|
205
|
+
- **phases/** — ordered delivery units with goals, success criteria, inputs/outputs
|
|
206
|
+
- **tasks.json** — standalone task registry with status lifecycle and phase linkage
|
|
207
|
+
- **decisions.json** — choices with rationale and phase association
|
|
208
|
+
- **gaps.json** — open items with priority, category, and resolution tracking
|
|
209
|
+
- **rationale.json** — design rationale with decision cross-references
|
|
210
|
+
- **handoff.json** — session context snapshot (created on-demand, not by /project init)
|
|
211
|
+
- **verification.json** — completion evidence per task/phase/requirement
|
|
212
|
+
- **conformance-reference.json** — executable code conventions with principles, rules, check methods (grep/command/ast/inspect), and check patterns. Ships empty, populated per-project by agents or users.
|
|
213
|
+
- **audit** (schema only, no default block) — structured audit results produced by running conformance checks.
|
|
214
|
+
|
|
215
|
+
All schemas are user-customizable. Edit `.project/schemas/*.schema.json` to add fields, change enums, or restructure blocks without modifying code.
|
|
216
|
+
</planning_lifecycle>
|
|
217
|
+
|
|
218
|
+
<update_check>
|
|
219
|
+
On `session_start`, checks npm registry for newer versions of `@davidorex/pi-project-workflows` and notifies via UI if an update is available. Non-blocking — failures are silently ignored.
|
|
220
|
+
</update_check>
|
|
221
|
+
|
|
222
|
+
<success_criteria>
|
|
223
|
+
- `.project/` directory exists with schemas and block files after `/project init`
|
|
224
|
+
- Block writes validate against schemas — invalid data rejected with specific error
|
|
225
|
+
- `/project status` returns current derived state without errors
|
|
226
|
+
- `/project validate` returns no errors for well-formed cross-block references
|
|
227
|
+
- `append-block-item` rejects duplicate IDs
|
|
228
|
+
- Schema customizations (field additions, enum changes) take effect on next write
|
|
229
|
+
</success_criteria>
|
|
230
|
+
|
|
231
|
+
*Generated from source by `scripts/generate-skills.js` — do not edit by hand.*
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Bundled Resources
|
|
2
|
+
|
|
3
|
+
## defaults/ (22 files)
|
|
4
|
+
|
|
5
|
+
- `defaults/blocks/conformance-reference.json`
|
|
6
|
+
- `defaults/blocks/decisions.json`
|
|
7
|
+
- `defaults/blocks/domain.json`
|
|
8
|
+
- `defaults/blocks/gaps.json`
|
|
9
|
+
- `defaults/blocks/project.json`
|
|
10
|
+
- `defaults/blocks/rationale.json`
|
|
11
|
+
- `defaults/blocks/requirements.json`
|
|
12
|
+
- `defaults/blocks/tasks.json`
|
|
13
|
+
- `defaults/blocks/verification.json`
|
|
14
|
+
- `defaults/schemas/architecture.schema.json`
|
|
15
|
+
- `defaults/schemas/audit.schema.json`
|
|
16
|
+
- `defaults/schemas/conformance-reference.schema.json`
|
|
17
|
+
- `defaults/schemas/decisions.schema.json`
|
|
18
|
+
- `defaults/schemas/domain.schema.json`
|
|
19
|
+
- `defaults/schemas/gaps.schema.json`
|
|
20
|
+
- `defaults/schemas/handoff.schema.json`
|
|
21
|
+
- `defaults/schemas/phase.schema.json`
|
|
22
|
+
- `defaults/schemas/project.schema.json`
|
|
23
|
+
- `defaults/schemas/rationale.schema.json`
|
|
24
|
+
- `defaults/schemas/requirements.schema.json`
|
|
25
|
+
- `defaults/schemas/tasks.schema.json`
|
|
26
|
+
- `defaults/schemas/verification.schema.json`
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pi-project-workflows
|
|
3
|
+
description: >
|
|
4
|
+
Meta-package re-exporting pi-project (schema-driven project state),
|
|
5
|
+
pi-workflows (workflow orchestration), and pi-behavior-monitors (autonomous
|
|
6
|
+
behavior monitoring). Install once to get all three extensions.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<objective>
|
|
10
|
+
This meta-package re-exports all three extensions. Install once to get everything:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
pi install npm:@davidorex/pi-project-workflows
|
|
14
|
+
```
|
|
15
|
+
</objective>
|
|
16
|
+
|
|
17
|
+
<included_extensions>
|
|
18
|
+
<extension name="@davidorex/pi-project">
|
|
19
|
+
Schema-driven project state management for Pi
|
|
20
|
+
|
|
21
|
+
**Tools:** `append-block-item`, `update-block-item`, `read-block`, `write-block`, `project-status`, `project-validate`, `project-init`
|
|
22
|
+
**Commands:** `/project`
|
|
23
|
+
</extension>
|
|
24
|
+
|
|
25
|
+
<extension name="@davidorex/pi-workflows">
|
|
26
|
+
Workflow orchestration extension for Pi
|
|
27
|
+
|
|
28
|
+
**Tools:** `workflow`, `workflow-list`, `workflow-agents`, `workflow-validate`, `workflow-status`, `workflow-init`
|
|
29
|
+
**Commands:** `/workflow`
|
|
30
|
+
**Shortcuts:** ctrl+h (Pause running workflow), ctrl+j (Resume paused workflow)
|
|
31
|
+
</extension>
|
|
32
|
+
|
|
33
|
+
<extension name="@davidorex/pi-behavior-monitors">
|
|
34
|
+
Behavior monitors for pi that watch agent activity and steer corrections
|
|
35
|
+
|
|
36
|
+
**Tools:** `monitors-status`, `monitors-inspect`, `monitors-control`, `monitors-rules`, `monitors-patterns`
|
|
37
|
+
**Commands:** `/monitors`
|
|
38
|
+
</extension>
|
|
39
|
+
|
|
40
|
+
</included_extensions>
|
|
41
|
+
|
|
42
|
+
*Generated from source by `scripts/generate-skills.js` — do not edit by hand.*
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pi-workflows
|
|
3
|
+
description: >
|
|
4
|
+
Orchestrates multi-step agent workflows defined in YAML with DAG-based
|
|
5
|
+
execution, typed data flow, checkpoint/resume, and output validation. Use when
|
|
6
|
+
running workflows, authoring workflow specs, debugging step failures, or
|
|
7
|
+
inspecting agent configurations.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<tools_reference>
|
|
11
|
+
<tool name="workflow">
|
|
12
|
+
Run a named workflow with typed input. Discovers workflows from .workflows/ and ~/.pi/agent/workflows/.
|
|
13
|
+
|
|
14
|
+
*Run a multi-step workflow with typed data flow between agents*
|
|
15
|
+
|
|
16
|
+
| Parameter | Type | Required | Description |
|
|
17
|
+
|-----------|------|----------|-------------|
|
|
18
|
+
| `workflow` | string | yes | Name of the workflow to run |
|
|
19
|
+
| `input` | unknown | no | Input data for the workflow (validated against workflow's input schema) |
|
|
20
|
+
| `fresh` | string | no | Set to 'true' to start a fresh run, ignoring any incomplete prior runs |
|
|
21
|
+
</tool>
|
|
22
|
+
|
|
23
|
+
<tool name="workflow-list">
|
|
24
|
+
List available workflows with names, descriptions, and sources.
|
|
25
|
+
|
|
26
|
+
*List available workflows with names, descriptions, and sources*
|
|
27
|
+
|
|
28
|
+
</tool>
|
|
29
|
+
|
|
30
|
+
<tool name="workflow-agents">
|
|
31
|
+
List available agents with full specs, or inspect a single agent by name. Returns role, description, model, tools, output format/schema, prompt template paths.
|
|
32
|
+
|
|
33
|
+
*List available agents with specs, or inspect a single agent by name*
|
|
34
|
+
|
|
35
|
+
| Parameter | Type | Required | Description |
|
|
36
|
+
|-----------|------|----------|-------------|
|
|
37
|
+
| `name` | string | no | Agent name to inspect (omit to list all) |
|
|
38
|
+
</tool>
|
|
39
|
+
|
|
40
|
+
<tool name="workflow-validate">
|
|
41
|
+
Validate workflow specs — check agents, schemas, step references, and filters.
|
|
42
|
+
|
|
43
|
+
*Validate workflow specs — check agents, schemas, step references, filters*
|
|
44
|
+
|
|
45
|
+
| Parameter | Type | Required | Description |
|
|
46
|
+
|-----------|------|----------|-------------|
|
|
47
|
+
| `name` | string | no | Workflow name to validate (omit to validate all) |
|
|
48
|
+
</tool>
|
|
49
|
+
|
|
50
|
+
<tool name="workflow-status">
|
|
51
|
+
Get workflow vocabulary — step types, filters, available agents, workflows, schemas, templates.
|
|
52
|
+
|
|
53
|
+
*Get workflow vocabulary — step types, filters, available agents, workflows, schemas*
|
|
54
|
+
|
|
55
|
+
</tool>
|
|
56
|
+
|
|
57
|
+
<tool name="workflow-init">
|
|
58
|
+
Initialize .workflows/ directory for workflow run state.
|
|
59
|
+
|
|
60
|
+
*Initialize .workflows/ directory for workflow run state*
|
|
61
|
+
|
|
62
|
+
</tool>
|
|
63
|
+
|
|
64
|
+
</tools_reference>
|
|
65
|
+
|
|
66
|
+
<commands_reference>
|
|
67
|
+
<command name="/workflow">
|
|
68
|
+
List and run workflows
|
|
69
|
+
|
|
70
|
+
Subcommands: `init`, `run`, `list`, `resume`, `validate`, `status`
|
|
71
|
+
</command>
|
|
72
|
+
|
|
73
|
+
</commands_reference>
|
|
74
|
+
|
|
75
|
+
<keyboard_shortcuts>
|
|
76
|
+
- **ctrl+h** — Pause running workflow
|
|
77
|
+
- **ctrl+j** — Resume paused workflow
|
|
78
|
+
</keyboard_shortcuts>
|
|
79
|
+
|
|
80
|
+
<bundled_resources>
|
|
81
|
+
21 agents, 11 schemas, 14 workflows, 28 templates bundled.
|
|
82
|
+
See references/bundled-resources.md for full inventory.
|
|
83
|
+
</bundled_resources>
|
|
84
|
+
|
|
85
|
+
<objective>
|
|
86
|
+
pi-workflows orchestrates multi-step agent workflows defined in YAML. Workflows are DAGs of typed steps with data flow via `${{ }}` expressions.
|
|
87
|
+
</objective>
|
|
88
|
+
|
|
89
|
+
<workflow_discovery>
|
|
90
|
+
Workflows are discovered from three locations (first match wins):
|
|
91
|
+
1. `.workflows/*.workflow.yaml` — project-level
|
|
92
|
+
2. `~/.pi/agent/workflows/*.workflow.yaml` — user-level
|
|
93
|
+
3. Package bundled `workflows/` — built-in
|
|
94
|
+
</workflow_discovery>
|
|
95
|
+
|
|
96
|
+
<step_types>
|
|
97
|
+
| Type | Field | Description |
|
|
98
|
+
|------|-------|-------------|
|
|
99
|
+
| agent | `agent: name` | Dispatch an LLM subprocess via `pi --mode json` |
|
|
100
|
+
| command | `command: "..."` | Run a shell command, capture stdout as output |
|
|
101
|
+
| monitor | `monitor: name` | Run a monitor classification as a verification gate |
|
|
102
|
+
| transform | `transform: { mapping: {...} }` | Pure data transformation via expressions, no LLM |
|
|
103
|
+
| gate | `gate: { check: "..." }` | Shell command exit code as pass/fail boolean |
|
|
104
|
+
| loop | `loop: { maxAttempts, steps }` | Repeat sub-steps until gate breaks or max reached |
|
|
105
|
+
| parallel | `parallel: { a: ..., b: ... }` | Run named sub-steps concurrently |
|
|
106
|
+
| pause | `pause: true` or `pause: "message"` | Pause execution, resumable later |
|
|
107
|
+
| forEach | `forEach: "${{ expr }}"` | Iterate over an array, executing the step per element |
|
|
108
|
+
</step_types>
|
|
109
|
+
|
|
110
|
+
<expression_syntax>
|
|
111
|
+
`${{ expression }}` resolves against scope: `input`, `steps`, `loop`, `forEach`.
|
|
112
|
+
|
|
113
|
+
Access step outputs: `${{ steps.investigate.output.findings }}`
|
|
114
|
+
Filters: `${{ steps.analyze.output | json }}`, `${{ items | length }}`, `${{ name | upper }}`
|
|
115
|
+
|
|
116
|
+
Available filters: length, keys, filter, json, upper, lower, trim, default, first, last, join, split, replace, includes, map, sum, min, max, sort, unique, flatten, zip, group_by, count_by, chunk, pick, omit, entries, from_entries, merge, values, not, and, or.
|
|
117
|
+
</expression_syntax>
|
|
118
|
+
|
|
119
|
+
<agent_resolution>
|
|
120
|
+
Agent specs (`.agent.yaml`) are resolved from three locations (first match wins):
|
|
121
|
+
1. `.pi/agents/<name>.agent.yaml` — project-level
|
|
122
|
+
2. `~/.pi/agent/agents/<name>.agent.yaml` — user-level
|
|
123
|
+
3. Package bundled `agents/<name>.agent.yaml` — built-in
|
|
124
|
+
|
|
125
|
+
Agent specs define: model, thinking level, tools, system prompt (or template), task template, output format/schema.
|
|
126
|
+
</agent_resolution>
|
|
127
|
+
|
|
128
|
+
<execution_model>
|
|
129
|
+
1. Steps are ordered by YAML declaration order
|
|
130
|
+
2. DAG planner infers parallelism from `${{ steps.X }}` references
|
|
131
|
+
3. Steps without explicit dependencies run after their predecessor (conservative sequential)
|
|
132
|
+
4. Each step's result is persisted atomically to `<runDir>/state.json`
|
|
133
|
+
5. TUI progress widget shows real-time step status, cost, and timing
|
|
134
|
+
</execution_model>
|
|
135
|
+
|
|
136
|
+
<checkpoint_resume>
|
|
137
|
+
Incomplete runs (failed or paused) are detected on next invocation. If the workflow spec hasn't changed incompatibly, execution resumes from the last completed step. Failed steps are re-executed. Use `fresh: "true"` to force a new run.
|
|
138
|
+
</checkpoint_resume>
|
|
139
|
+
|
|
140
|
+
<output_validation>
|
|
141
|
+
Steps with `output.schema` validate the agent's JSON output against a JSON Schema file. Validation failure marks the step as failed.
|
|
142
|
+
|
|
143
|
+
Use `block:<name>` to reference project block schemas portably: `output.schema: block:project` resolves to `.project/schemas/project.schema.json` from cwd. Works across monorepo, npm install, and user-customized schemas. Combined with `retry: { maxAttempts: 2 }`, the agent gets the schema validation error injected into its retry prompt and can self-correct.
|
|
144
|
+
</output_validation>
|
|
145
|
+
|
|
146
|
+
<retry>
|
|
147
|
+
Steps with `retry: { maxAttempts: N }` are re-executed on failure. Between retries:
|
|
148
|
+
- Project block files are rolled back to pre-attempt state
|
|
149
|
+
- Prior error messages are injected into the prompt
|
|
150
|
+
- Optional `steeringMessage` provides custom retry guidance
|
|
151
|
+
</retry>
|
|
152
|
+
|
|
153
|
+
<completion_messages>
|
|
154
|
+
After execution, the workflow result is injected into the main LLM conversation. The `completion` field controls this: either a `template` (full `${{ }}` template) or `message` + `include` (message text plus resolved data paths).
|
|
155
|
+
</completion_messages>
|
|
156
|
+
|
|
157
|
+
<artifacts>
|
|
158
|
+
Workflows can write post-completion files via the `artifacts` field. Paths may contain `${{ }}` expressions. Artifacts targeting `.project/*.json` are routed through `writeBlock()` for schema validation.
|
|
159
|
+
|
|
160
|
+
Block artifact write failures are fatal — if the data doesn't conform to the block's schema, the workflow fails. Non-block artifact failures remain non-fatal (warning). On resume, all steps are preserved; only artifact processing re-runs, so fixing the schema issue or agent output and resuming avoids re-running expensive LLM steps.
|
|
161
|
+
</artifacts>
|
|
162
|
+
|
|
163
|
+
<validation>
|
|
164
|
+
`validateWorkflow(spec, cwd)` runs authoring-time checks without executing the workflow:
|
|
165
|
+
|
|
166
|
+
1. **Agent resolution** — all referenced agents exist in the three-tier search
|
|
167
|
+
2. **Monitor resolution** — all referenced monitors exist in .pi/monitors/ or built-in examples
|
|
168
|
+
3. **Schema resolution** — all output schema file paths resolve to existing files
|
|
169
|
+
4. **Step reference validity** — `${{ steps.X }}` expressions reference declared steps
|
|
170
|
+
5. **Step ordering** — referenced steps are declared before the referencing step
|
|
171
|
+
6. **Filter name validity** — `${{ value | filter }}` uses known filter names
|
|
172
|
+
|
|
173
|
+
Returns `{ valid: boolean, issues: ValidationIssue[] }` where each issue has severity, message, and field path. Use `/workflow validate` or `/workflow validate <name>` to run from the command line.
|
|
174
|
+
</validation>
|
|
175
|
+
|
|
176
|
+
<success_criteria>
|
|
177
|
+
- Workflow completes all steps without unhandled failures
|
|
178
|
+
- Step outputs match declared output schemas
|
|
179
|
+
- State is persisted atomically after each step
|
|
180
|
+
- Completion message is delivered to main conversation
|
|
181
|
+
- `/workflow validate` returns no errors for authored specs
|
|
182
|
+
- Checkpoint/resume recovers from the last completed step
|
|
183
|
+
</success_criteria>
|
|
184
|
+
|
|
185
|
+
*Generated from source by `scripts/generate-skills.js` — do not edit by hand.*
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Bundled Resources
|
|
2
|
+
|
|
3
|
+
## agents/ (21 files)
|
|
4
|
+
|
|
5
|
+
- `agents/architecture-designer.agent.yaml`
|
|
6
|
+
- `agents/architecture-inferrer.agent.yaml`
|
|
7
|
+
- `agents/audit-fixer.agent.yaml`
|
|
8
|
+
- `agents/code-explorer.agent.yaml`
|
|
9
|
+
- `agents/decomposer.agent.yaml`
|
|
10
|
+
- `agents/gap-identifier.agent.yaml`
|
|
11
|
+
- `agents/handoff-writer.agent.yaml`
|
|
12
|
+
- `agents/investigator.agent.yaml`
|
|
13
|
+
- `agents/pattern-analyzer.agent.yaml`
|
|
14
|
+
- `agents/phase-author.agent.yaml`
|
|
15
|
+
- `agents/plan-creator.agent.yaml`
|
|
16
|
+
- `agents/plan-decomposer.agent.yaml`
|
|
17
|
+
- `agents/project-definer.agent.yaml`
|
|
18
|
+
- `agents/project-inferrer.agent.yaml`
|
|
19
|
+
- `agents/quality-analyzer.agent.yaml`
|
|
20
|
+
- `agents/requirements-gatherer.agent.yaml`
|
|
21
|
+
- `agents/researcher.agent.yaml`
|
|
22
|
+
- `agents/spec-implementer.agent.yaml`
|
|
23
|
+
- `agents/structure-analyzer.agent.yaml`
|
|
24
|
+
- `agents/synthesizer.agent.yaml`
|
|
25
|
+
- `agents/verifier.agent.yaml`
|
|
26
|
+
|
|
27
|
+
## schemas/ (11 files)
|
|
28
|
+
|
|
29
|
+
- `schemas/decomposition-specs.schema.json`
|
|
30
|
+
- `schemas/execution-results.schema.json`
|
|
31
|
+
- `schemas/investigation-findings.schema.json`
|
|
32
|
+
- `schemas/pattern-analysis.schema.json`
|
|
33
|
+
- `schemas/phase.schema.json`
|
|
34
|
+
- `schemas/plan-breakdown.schema.json`
|
|
35
|
+
- `schemas/quality-analysis.schema.json`
|
|
36
|
+
- `schemas/research-findings.schema.json`
|
|
37
|
+
- `schemas/structure-analysis.schema.json`
|
|
38
|
+
- `schemas/synthesis.schema.json`
|
|
39
|
+
- `schemas/verifier-output.schema.json`
|
|
40
|
+
|
|
41
|
+
## workflows/ (14 files)
|
|
42
|
+
|
|
43
|
+
- `workflows/analyze-existing-project.workflow.yaml`
|
|
44
|
+
- `workflows/create-handoff.workflow.yaml`
|
|
45
|
+
- `workflows/create-phase.workflow.yaml`
|
|
46
|
+
- `workflows/do-gap.workflow.yaml`
|
|
47
|
+
- `workflows/fix-audit.workflow.yaml`
|
|
48
|
+
- `workflows/gap-to-phase.workflow.yaml`
|
|
49
|
+
- `workflows/init-new-project.workflow.yaml`
|
|
50
|
+
- `workflows/parallel-analysis.workflow.yaml`
|
|
51
|
+
- `workflows/parallel-explicit.workflow.yaml`
|
|
52
|
+
- `workflows/pausable-analysis.workflow.yaml`
|
|
53
|
+
- `workflows/plan-from-requirements.workflow.yaml`
|
|
54
|
+
- `workflows/resumable-analysis.workflow.yaml`
|
|
55
|
+
- `workflows/self-implement.workflow.yaml`
|
|
56
|
+
- `workflows/typed-analysis.workflow.yaml`
|
|
57
|
+
|
|
58
|
+
## templates/ (28 files)
|
|
59
|
+
|
|
60
|
+
- `templates/analyzers/base-analyzer.md`
|
|
61
|
+
- `templates/analyzers/macros.md`
|
|
62
|
+
- `templates/analyzers/patterns-task.md`
|
|
63
|
+
- `templates/analyzers/patterns.md`
|
|
64
|
+
- `templates/analyzers/quality-task.md`
|
|
65
|
+
- `templates/analyzers/quality.md`
|
|
66
|
+
- `templates/analyzers/structure-task.md`
|
|
67
|
+
- `templates/analyzers/structure.md`
|
|
68
|
+
- `templates/architecture-designer/task.md`
|
|
69
|
+
- `templates/architecture-inferrer/task.md`
|
|
70
|
+
- `templates/audit-fixer/task.md`
|
|
71
|
+
- `templates/decomposer/task.md`
|
|
72
|
+
- `templates/explorer/system.md`
|
|
73
|
+
- `templates/explorer/task.md`
|
|
74
|
+
- `templates/gap-identifier/task.md`
|
|
75
|
+
- `templates/handoff-writer/task.md`
|
|
76
|
+
- `templates/investigator/task.md`
|
|
77
|
+
- `templates/phase-author/task.md`
|
|
78
|
+
- `templates/plan-creator/task.md`
|
|
79
|
+
- `templates/plan-decomposer/task.md`
|
|
80
|
+
- `templates/project-definer/task.md`
|
|
81
|
+
- `templates/project-inferrer/task.md`
|
|
82
|
+
- `templates/requirements-gatherer/task.md`
|
|
83
|
+
- `templates/researcher/task.md`
|
|
84
|
+
- `templates/spec-implementer/task.md`
|
|
85
|
+
- `templates/synthesizer/system.md`
|
|
86
|
+
- `templates/synthesizer/task.md`
|
|
87
|
+
- `templates/verifier/task.md`
|