@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 CHANGED
@@ -4,7 +4,7 @@ Structured development workflow commands for Pi coding agent.
4
4
 
5
5
  ## Overview
6
6
 
7
- 13 slash commands that guide work from idea to completion. Each command maps to a skill that instructs the agent on what to do.
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
- # Find issues
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
- └── reviews/ ← review remarks (in plan docs)
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
- ├── quick-work/ quick-work summaries
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 dirs = readdirSync(worktreesDir, { withFileTypes: true })
95
- .filter((d) => d.isDirectory())
96
- .map((d) => d.name);
97
- return dirs.map((d) => ({
98
- value: d,
99
- label: d,
100
- description: `Worktree: ${d}`,
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");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/workflow",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Structured development workflow commands for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",