@pi-unipi/workflow 0.1.8 → 0.1.9
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.md +47 -5
- package/commands.ts +138 -8
- package/package.json +1 -1
- package/skills/auto/SKILL.md +340 -41
- package/skills/chore-create/SKILL.md +313 -0
- package/skills/chore-execute/SKILL.md +312 -0
- package/skills/debug/SKILL.md +224 -0
- package/skills/fix/SKILL.md +210 -0
- package/skills/quick-fix/SKILL.md +133 -0
- package/skills/quick-work/SKILL.md +3 -3
- package/skills/research/SKILL.md +251 -0
- package/skills/scan-issues/SKILL.md +14 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Structured development workflow commands for Pi coding agent.
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
19 slash commands that guide work from idea to completion. Each command maps to a skill that instructs the agent on what to do.
|
|
8
8
|
|
|
9
9
|
## Commands
|
|
10
10
|
|
|
@@ -22,7 +22,13 @@ Structured development workflow commands for Pi coding agent.
|
|
|
22
22
|
| `/unipi:quick-work` | Fast single-task execution | `<string>` |
|
|
23
23
|
| `/unipi:gather-context` | Research codebase, prepare for brainstorm | `<string>` |
|
|
24
24
|
| `/unipi:document` | Generate documentation | `<string>` |
|
|
25
|
-
| `/unipi:scan-issues` | Find bugs, anti-patterns, security issues | `<string>` |
|
|
25
|
+
| `/unipi:scan-issues` | Find bugs, anti-patterns, security issues (passive scan) | `<string>` |
|
|
26
|
+
| `/unipi:debug` | Active bug investigation, root-cause analysis | `<string>` |
|
|
27
|
+
| `/unipi:fix` | Fix bugs using debug reports | `debug:<path> <string>` |
|
|
28
|
+
| `/unipi:quick-fix` | Fast bug fix without debug report | `<string>` |
|
|
29
|
+
| `/unipi:research` | Read-only research with bash access | `<string>` |
|
|
30
|
+
| `/unipi:chore-create` | Create reusable chore definition | `<string>` |
|
|
31
|
+
| `/unipi:chore-execute` | Execute a saved chore | `chore:<path> <string>` |
|
|
26
32
|
|
|
27
33
|
## Workflow
|
|
28
34
|
|
|
@@ -71,10 +77,36 @@ brainstorm → plan → work → review-work → consolidate
|
|
|
71
77
|
# Generate documentation
|
|
72
78
|
/unipi:document the auth module
|
|
73
79
|
|
|
74
|
-
#
|
|
80
|
+
# Deep research with bash access
|
|
81
|
+
/unipi:research TypeScript 5.0 migration path
|
|
82
|
+
|
|
83
|
+
# Find issues (passive scan)
|
|
75
84
|
/unipi:scan-issues focus on security
|
|
76
85
|
```
|
|
77
86
|
|
|
87
|
+
### Bug Fixing
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Debug and fix a bug (full flow)
|
|
91
|
+
/unipi:debug TypeError in auth middleware
|
|
92
|
+
/unipi:fix debug:2026-04-28-auth-typeerror-debug
|
|
93
|
+
|
|
94
|
+
# Quick fix for simple bugs
|
|
95
|
+
/unipi:quick-fix fix null check in user validation
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Chores
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Create reusable chores
|
|
102
|
+
/unipi:chore-create push to github main
|
|
103
|
+
/unipi:chore-create publish package to npm
|
|
104
|
+
|
|
105
|
+
# Execute saved chores
|
|
106
|
+
/unipi:chore-execute chore:push-github-main
|
|
107
|
+
/unipi:chore-execute chore:publish-npm
|
|
108
|
+
```
|
|
109
|
+
|
|
78
110
|
### Worktree Management
|
|
79
111
|
|
|
80
112
|
```bash
|
|
@@ -96,9 +128,13 @@ brainstorm → plan → work → review-work → consolidate
|
|
|
96
128
|
│ ├── specs/ ← brainstorm output (design specs)
|
|
97
129
|
│ ├── plans/ ← plan output (implementation plans)
|
|
98
130
|
│ ├── generated/ ← document output (docs, guides)
|
|
99
|
-
│
|
|
131
|
+
│ ├── reviews/ ← review remarks (in plan docs)
|
|
132
|
+
│ ├── debug/ ← debug reports
|
|
133
|
+
│ ├── fix/ ← fix reports
|
|
134
|
+
│ ├── quick-work/ ← quick-work summaries
|
|
135
|
+
│ └── chore/ ← reusable chore definitions
|
|
100
136
|
├── memory/ ← consolidate memory
|
|
101
|
-
├──
|
|
137
|
+
├── ralph/ ← ralph loop state
|
|
102
138
|
└── worktrees/ ← git worktrees
|
|
103
139
|
├── feat/auth/
|
|
104
140
|
└── fix/login-bug/
|
|
@@ -110,6 +146,12 @@ brainstorm → plan → work → review-work → consolidate
|
|
|
110
146
|
- **@pi-unipi/memory** — memory hooks for consolidate (optional)
|
|
111
147
|
- **@pi-unipi/subagents** — parallel research for gather-context, scan-issues (optional)
|
|
112
148
|
- **@pi-unipi/ralph** — loop integration for long-running tasks (optional)
|
|
149
|
+
- **@pi-unipi/ask-user** — structured user input for all skills (optional)
|
|
150
|
+
- **@pi-unipi/mcp** — MCP server tools for all skills (optional)
|
|
151
|
+
- **@pi-unipi/web-api** — web research for research-type skills (optional)
|
|
152
|
+
- **@pi-unipi/compactor** — compactor tools for main agent (optional)
|
|
153
|
+
|
|
154
|
+
See [docs/coexist-triggers.md](docs/coexist-triggers.md) for detailed integration behavior.
|
|
113
155
|
|
|
114
156
|
## Installation
|
|
115
157
|
|
package/commands.ts
CHANGED
|
@@ -83,22 +83,100 @@ function suggestPlanFiles(prefix: string): { value: string; label: string; descr
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Suggest debug files from .unipi/docs/debug/ for fix command.
|
|
88
|
+
*/
|
|
89
|
+
function suggestDebugFiles(prefix: string): { value: string; label: string; description: string }[] {
|
|
90
|
+
const debugDir = join(process.cwd(), ".unipi", "docs", "debug");
|
|
91
|
+
if (!existsSync(debugDir)) return [];
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const search = prefix?.trim().split(/\s+/).pop() ?? "";
|
|
95
|
+
const files = readdirSync(debugDir)
|
|
96
|
+
.filter((f) => f.endsWith(".md"))
|
|
97
|
+
.map((f) => ({ name: f, time: statSync(join(debugDir, f)).mtimeMs }))
|
|
98
|
+
.sort((a, b) => b.time - a.time);
|
|
99
|
+
return files
|
|
100
|
+
.filter((f) => !search || f.name.includes(search))
|
|
101
|
+
.map((f) => ({
|
|
102
|
+
value: `debug:${f.name}`,
|
|
103
|
+
label: basename(f.name, ".md"),
|
|
104
|
+
description: `Debug: ${f.name}`,
|
|
105
|
+
}));
|
|
106
|
+
} catch {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Suggest chore files from .unipi/docs/chore/ for chore-execute command.
|
|
113
|
+
*/
|
|
114
|
+
function suggestChoreFiles(prefix: string): { value: string; label: string; description: string }[] {
|
|
115
|
+
const choreDir = join(process.cwd(), ".unipi", "docs", "chore");
|
|
116
|
+
if (!existsSync(choreDir)) return [];
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const search = prefix?.trim().split(/\s+/).pop() ?? "";
|
|
120
|
+
const files = readdirSync(choreDir)
|
|
121
|
+
.filter((f) => f.endsWith(".md"))
|
|
122
|
+
.map((f) => ({ name: f, time: statSync(join(choreDir, f)).mtimeMs }))
|
|
123
|
+
.sort((a, b) => b.time - a.time);
|
|
124
|
+
return files
|
|
125
|
+
.filter((f) => !search || f.name.includes(search))
|
|
126
|
+
.map((f) => ({
|
|
127
|
+
value: `chore:${f.name}`,
|
|
128
|
+
label: basename(f.name, ".md"),
|
|
129
|
+
description: `Chore: ${f.name}`,
|
|
130
|
+
}));
|
|
131
|
+
} catch {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
86
136
|
/**
|
|
87
137
|
* Suggest existing worktree names for merge/list commands.
|
|
138
|
+
* Recursively scans for actual git worktrees (directories containing .git files).
|
|
88
139
|
*/
|
|
89
140
|
function suggestWorktrees(): { value: string; label: string; description: string }[] {
|
|
90
141
|
const worktreesDir = join(process.cwd(), ".unipi", "worktrees");
|
|
91
142
|
if (!existsSync(worktreesDir)) return [];
|
|
92
143
|
|
|
93
144
|
try {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
145
|
+
const results: { value: string; label: string; description: string }[] = [];
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Recursively find worktree directories (those containing a .git file).
|
|
149
|
+
* A worktree's .git file contains: gitdir: /path/to/.git/worktrees/<branch>
|
|
150
|
+
*/
|
|
151
|
+
function findWorktrees(dir: string, relativePath: string): void {
|
|
152
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
153
|
+
for (const entry of entries) {
|
|
154
|
+
const fullPath = join(dir, entry.name);
|
|
155
|
+
const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
156
|
+
|
|
157
|
+
if (entry.name === ".git" && entry.isFile()) {
|
|
158
|
+
// This is a worktree — extract branch name from gitdir path
|
|
159
|
+
try {
|
|
160
|
+
const gitContent = readFileSync(fullPath, "utf-8").trim();
|
|
161
|
+
const match = gitContent.match(/gitdir:\s+.+?\/([^/]+)$/);
|
|
162
|
+
const branchName = match?.[1] ?? entry.name;
|
|
163
|
+
results.push({
|
|
164
|
+
value: branchName,
|
|
165
|
+
label: branchName,
|
|
166
|
+
description: `Worktree: ${relPath}`,
|
|
167
|
+
});
|
|
168
|
+
} catch {
|
|
169
|
+
// Can't read .git file — skip
|
|
170
|
+
}
|
|
171
|
+
} else if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git") {
|
|
172
|
+
// Recurse into subdirectories (but not into nested .git or node_modules)
|
|
173
|
+
findWorktrees(fullPath, relPath);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
findWorktrees(worktreesDir, "");
|
|
179
|
+
return results;
|
|
102
180
|
} catch {
|
|
103
181
|
return [];
|
|
104
182
|
}
|
|
@@ -199,6 +277,48 @@ const COMMANDS: WorkflowCommand[] = [
|
|
|
199
277
|
skillName: "auto",
|
|
200
278
|
argumentHint: "<description> plan:<file> specs:<file>",
|
|
201
279
|
},
|
|
280
|
+
{
|
|
281
|
+
name: WORKFLOW_COMMANDS.DEBUG,
|
|
282
|
+
description:
|
|
283
|
+
"Active bug investigation — reproduce, diagnose, root-cause analysis",
|
|
284
|
+
skillName: "debug",
|
|
285
|
+
argumentHint: "<bug description or error>",
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: WORKFLOW_COMMANDS.FIX,
|
|
289
|
+
description:
|
|
290
|
+
"Fix bugs using debug reports — autocomplete for debug files",
|
|
291
|
+
skillName: "fix",
|
|
292
|
+
argumentHint: "debug:<file> <scope>",
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: WORKFLOW_COMMANDS.QUICK_FIX,
|
|
296
|
+
description:
|
|
297
|
+
"Fast bug fix without debug report — one shot",
|
|
298
|
+
skillName: "quick-fix",
|
|
299
|
+
argumentHint: "<bug description>",
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: WORKFLOW_COMMANDS.RESEARCH,
|
|
303
|
+
description:
|
|
304
|
+
"Read-only research with bash access — deep codebase investigation",
|
|
305
|
+
skillName: "research",
|
|
306
|
+
argumentHint: "<topic or question>",
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
name: WORKFLOW_COMMANDS.CHORE_CREATE,
|
|
310
|
+
description:
|
|
311
|
+
"Create reusable chore definition for repeatable tasks",
|
|
312
|
+
skillName: "chore-create",
|
|
313
|
+
argumentHint: "<chore description>",
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: WORKFLOW_COMMANDS.CHORE_EXECUTE,
|
|
317
|
+
description:
|
|
318
|
+
"Execute a saved chore — deploy, publish, push, etc.",
|
|
319
|
+
skillName: "chore-execute",
|
|
320
|
+
argumentHint: "chore:<file> <overrides>",
|
|
321
|
+
},
|
|
202
322
|
];
|
|
203
323
|
|
|
204
324
|
/**
|
|
@@ -246,6 +366,16 @@ export function registerWorkflowCommands(
|
|
|
246
366
|
items = suggestPlanFiles(prefix);
|
|
247
367
|
}
|
|
248
368
|
|
|
369
|
+
// Fix command: suggest debug files
|
|
370
|
+
if (cmd.name === WORKFLOW_COMMANDS.FIX) {
|
|
371
|
+
items = suggestDebugFiles(prefix);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Chore-execute command: suggest chore files
|
|
375
|
+
if (cmd.name === WORKFLOW_COMMANDS.CHORE_EXECUTE) {
|
|
376
|
+
items = suggestChoreFiles(prefix);
|
|
377
|
+
}
|
|
378
|
+
|
|
249
379
|
// Defensive: filter out any items with non-string value
|
|
250
380
|
if (items) {
|
|
251
381
|
return items.filter((item) => typeof item.value === "string");
|