@pi-unipi/workflow 0.1.5 → 0.1.7

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/commands.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
9
- import { readFileSync, readdirSync, existsSync } from "fs";
9
+ import { readFileSync, readdirSync, existsSync, statSync } from "fs";
10
10
  import { join, basename } from "path";
11
11
  import { UNIPI_PREFIX, WORKFLOW_COMMANDS, getToolsForCommand, getSandboxLevel, type SandboxLevel } from "@pi-unipi/core";
12
12
 
@@ -41,13 +41,17 @@ function suggestSpecFiles(prefix: string): { value: string; label: string; descr
41
41
  if (!existsSync(specsDir)) return [];
42
42
 
43
43
  try {
44
- const files = readdirSync(specsDir).filter((f) => f.endsWith(".md"));
44
+ const search = prefix?.trim().split(/\s+/).pop() ?? "";
45
+ const files = readdirSync(specsDir)
46
+ .filter((f) => f.endsWith(".md"))
47
+ .map((f) => ({ name: f, time: statSync(join(specsDir, f)).mtimeMs }))
48
+ .sort((a, b) => b.time - a.time);
45
49
  return files
46
- .filter((f) => !prefix || f.includes(prefix))
50
+ .filter((f) => !search || f.name.includes(search))
47
51
  .map((f) => ({
48
- value: `specs:${f}`,
49
- label: basename(f, ".md"),
50
- description: `Spec: ${f}`,
52
+ value: `specs:${f.name}`,
53
+ label: basename(f.name, ".md"),
54
+ description: `Spec: ${f.name}`,
51
55
  }));
52
56
  } catch {
53
57
  return [];
@@ -62,13 +66,17 @@ function suggestPlanFiles(prefix: string): { value: string; label: string; descr
62
66
  if (!existsSync(plansDir)) return [];
63
67
 
64
68
  try {
65
- const files = readdirSync(plansDir).filter((f) => f.endsWith(".md"));
69
+ const search = prefix?.trim().split(/\s+/).pop() ?? "";
70
+ const files = readdirSync(plansDir)
71
+ .filter((f) => f.endsWith(".md"))
72
+ .map((f) => ({ name: f, time: statSync(join(plansDir, f)).mtimeMs }))
73
+ .sort((a, b) => b.time - a.time);
66
74
  return files
67
- .filter((f) => !prefix || f.includes(prefix))
75
+ .filter((f) => !search || f.name.includes(search))
68
76
  .map((f) => ({
69
- value: `plan:${f}`,
70
- label: basename(f, ".md"),
71
- description: `Plan: ${f}`,
77
+ value: `plan:${f.name}`,
78
+ label: basename(f.name, ".md"),
79
+ description: `Plan: ${f.name}`,
72
80
  }));
73
81
  } catch {
74
82
  return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/workflow",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Structured development workflow commands for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -111,6 +111,20 @@ specs:
111
111
  - **Steps** are bite-sized — agent can follow without guessing
112
112
  - Order tasks by dependency (foundational work first)
113
113
 
114
+ ### Task Status Lifecycle
115
+
116
+ Tasks use prefixes to track progress:
117
+
118
+ | Status | Meaning |
119
+ |--------|----------|
120
+ | `unstarted:` | Not started |
121
+ | `in-progress:` | Being worked on |
122
+ | `completed:` | Done and verified |
123
+ | `failed:` | Attempted but failed, needs investigation |
124
+ | `awaiting_user:` | Needs user action (test, approve, provide input) |
125
+ | `blocked:` | Waiting on dependency or external factor |
126
+ | `skipped:` | Intentionally not doing (deferred, out of scope) |
127
+
114
128
  ---
115
129
 
116
130
  ## Phase 4: Update Brainstorm Checkboxes
@@ -46,9 +46,13 @@ For each task in plan:
46
46
  1. Read acceptance criteria
47
47
  2. Verify against actual implementation
48
48
  3. Determine status:
49
- - **Done** — all criteria met
49
+ - **Done** — all criteria met → `completed:`
50
50
  - **Partially Done X/Y** — some steps complete, others not
51
- - **Unstarted** — nothing done
51
+ - **Unstarted** — nothing done → `unstarted:`
52
+ - **Failed** — attempted but broken → `failed:`
53
+ - **Awaiting User** — needs user action → `awaiting_user:`
54
+ - **Blocked** — waiting on dependency → `blocked:`
55
+ - **Skipped** — intentionally not done → `skipped:`
52
56
 
53
57
  If `string(greedy)` scope provided, only check matching tasks.
54
58
 
@@ -59,7 +59,7 @@ If args not provided, ask user interactively:
59
59
  1. Read plan file(s)
60
60
  2. Review critically — identify questions or concerns
61
61
  3. If concerns: raise with user before starting
62
- 4. Identify task status: `unstarted:` (pending), `in-progress:` (started), `completed:` (done)
62
+ 4. Identify task status: `unstarted:` (pending), `in-progress:` (started), `completed:` (done), `failed:` (needs investigation), `awaiting_user:` (needs user action), `blocked:` (waiting on dependency), `skipped:` (deferred)
63
63
 
64
64
  **Exit:** Plan reviewed, ready to execute.
65
65
 
@@ -67,14 +67,36 @@ If args not provided, ask user interactively:
67
67
 
68
68
  ## Phase 3: Execute Tasks
69
69
 
70
- For each `unstarted:` task in order:
70
+ For each task in order, skip `completed:`, `skipped:`, and `awaiting_user:` tasks:
71
71
 
72
+ ### If `unstarted:`
72
73
  1. Change `unstarted:` to `in-progress:` in plan
73
74
  2. Follow each step exactly (plan has bite-sized steps)
74
75
  3. Run verifications as specified in acceptance criteria
75
76
  4. Change `in-progress:` to `completed:` when complete
76
77
  5. Update plan file with progress
77
78
 
79
+ ### If `in-progress:`
80
+ 1. Continue from where it left off
81
+ 2. Follow remaining steps
82
+ 3. Change to `completed:` when done
83
+
84
+ ### If `failed:`
85
+ 1. Read failure notes
86
+ 2. Investigate root cause
87
+ 3. Fix and re-verify
88
+ 4. Change to `completed:` when fixed, or keep `failed:` if still broken
89
+
90
+ ### If `awaiting_user:`
91
+ 1. Remind user what's needed
92
+ 2. Wait for user response
93
+ 3. Resume when user provides input
94
+
95
+ ### If `blocked:`
96
+ 1. Check if blocker is resolved
97
+ 2. If resolved → change to `unstarted:` and continue
98
+ 3. If still blocked → skip and move to next task
99
+
78
100
  ### When to Stop and Ask
79
101
 
80
102
  **STOP immediately when:**