@pi-unipi/workflow 0.1.17 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/commands.ts CHANGED
@@ -388,7 +388,7 @@ export function registerWorkflowCommands(
388
388
  // Apply sandbox — save current tools, set command's tools
389
389
  const currentTools = options.getActiveTools();
390
390
  options.saveTools(currentTools);
391
- const sandboxTools = getToolsForCommand(cmd.name);
391
+ const sandboxTools = getToolsForCommand(cmd.name, currentTools);
392
392
  const sandboxLevel = getSandboxLevel(cmd.name);
393
393
  options.setActiveTools([...sandboxTools], sandboxLevel);
394
394
 
package/index.ts CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  getPackageVersion,
17
17
  initUnipiDirs,
18
18
  type SandboxLevel,
19
- getToolsForLevel,
19
+ getBlockedToolsForLevel,
20
20
  } from "@pi-unipi/core";
21
21
  import { registerWorkflowCommands } from "./commands.js";
22
22
 
@@ -35,6 +35,9 @@ let sandboxActive = false;
35
35
  /** Current sandbox level (null = no sandbox) */
36
36
  let currentSandboxLevel: SandboxLevel | null = null;
37
37
 
38
+ /** Current active tools after sandbox filtering */
39
+ let currentSandboxTools: string[] | null = null;
40
+
38
41
  export default function (pi: ExtensionAPI) {
39
42
  // Register skills directory with pi's resource loader
40
43
  const skillsDir = new URL("./skills", import.meta.url).pathname;
@@ -52,6 +55,7 @@ export default function (pi: ExtensionAPI) {
52
55
  pi.setActiveTools(tools);
53
56
  sandboxActive = true;
54
57
  currentSandboxLevel = level;
58
+ currentSandboxTools = tools;
55
59
  },
56
60
  saveTools: (tools: string[]) => {
57
61
  savedTools = tools;
@@ -62,7 +66,7 @@ export default function (pi: ExtensionAPI) {
62
66
  pi.on("tool_call", async (event, _ctx) => {
63
67
  if (!sandboxActive || !currentSandboxLevel) return;
64
68
 
65
- const allowed = getToolsForLevel(currentSandboxLevel);
69
+ const allowed = currentSandboxTools ?? [];
66
70
  if (!allowed.includes(event.toolName)) {
67
71
  return {
68
72
  block: true,
@@ -75,11 +79,13 @@ export default function (pi: ExtensionAPI) {
75
79
  pi.on("before_agent_start", async (event, _ctx) => {
76
80
  if (!sandboxActive || !currentSandboxLevel) return;
77
81
 
78
- const allowed = getToolsForLevel(currentSandboxLevel);
79
- const blocked = ["read", "write", "edit", "bash", "grep", "find", "ls"]
80
- .filter((t) => !allowed.includes(t));
82
+ const allowed = currentSandboxTools ?? pi.getActiveTools();
83
+ const blocked = getBlockedToolsForLevel(currentSandboxLevel);
81
84
 
82
- const base = `\n\n<sandbox>\nSandbox mode: ${currentSandboxLevel}.\nAvailable tools: ${allowed.join(", ")}.\nBlocked tools: ${blocked.join(", ")} — removed from your tool list.`;
85
+ const blockedLine = blocked.length > 0
86
+ ? `\nBlocked tools: ${blocked.join(", ")} — removed from your tool list.`
87
+ : "\nNo tools were blocked by this sandbox.";
88
+ const base = `\n\n<sandbox>\nSandbox mode: ${currentSandboxLevel}.\nAvailable tools: ${allowed.join(", ")}.${blockedLine}`;
83
89
 
84
90
  if (currentSandboxLevel === "brainstorm") {
85
91
  return {
@@ -114,6 +120,7 @@ export default function (pi: ExtensionAPI) {
114
120
  savedTools = null;
115
121
  sandboxActive = false;
116
122
  currentSandboxLevel = null;
123
+ currentSandboxTools = null;
117
124
  }
118
125
  });
119
126
 
@@ -149,7 +156,8 @@ export default function (pi: ExtensionAPI) {
149
156
  });
150
157
 
151
158
  // Listen for ralph module ready event
152
- pi.events.on(UNIPI_EVENTS.MODULE_READY, (event: any) => {
159
+ pi.events.on(UNIPI_EVENTS.MODULE_READY, (data) => {
160
+ const event = data as { name?: string };
153
161
  if (event?.name === MODULES.RALPH) {
154
162
  ralphDetected = true;
155
163
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/workflow",
3
- "version": "0.1.17",
3
+ "version": "2.0.0",
4
4
  "description": "Structured development workflow commands for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -177,13 +177,27 @@ Wait for user response. If changes requested, make them and re-run self-review.
177
177
 
178
178
  ## Phase 8: Handoff
179
179
 
180
- Ask user what to do next:
181
-
182
- 1. **Proceed to /unipi:plan** — Turn decisions into implementation plan
183
- 2. **Keep exploring** — More questions or refine decisions
184
- 3. **Done for now** Return later
180
+ Ask user what to do next. If `ask_user` is available, prefer structured options so the plan handoff can run automatically:
181
+
182
+ ```ts
183
+ ask_user({
184
+ question: "What would you like to do next?",
185
+ options: [
186
+ {
187
+ label: "Proceed to /unipi:plan",
188
+ description: "Turn decisions into an implementation plan",
189
+ value: "plan",
190
+ action: "new_session",
191
+ prefill: "/unipi:plan specs:YYYY-MM-DD-<topic>-design",
192
+ },
193
+ { label: "Keep exploring", description: "Refine questions or decisions", value: "explore" },
194
+ { label: "Done for now", description: "Return later", value: "done", action: "end_turn" },
195
+ ],
196
+ allowFreeform: false,
197
+ })
198
+ ```
185
199
 
186
- If user selects "Proceed to /unipi:plan", suggest:
200
+ If `ask_user` is unavailable, ask conversationally with the same options. Keep this copyable fallback command visible:
187
201
  ```
188
202
  /unipi:plan specs:YYYY-MM-DD-<topic>-design
189
203
  ```
@@ -12,6 +12,8 @@ Active investigation to reproduce, diagnose, and root-cause bugs. Produces a str
12
12
  **This skill MAY:** read codebase, run diagnostic commands, spawn subagents, write debug report to `.unipi/docs/debug/`.
13
13
  **This skill MAY NOT:** edit code, fix issues, run tests that modify state, deploy.
14
14
 
15
+ **Write-permission clarification:** "Read-only" means source/project code is read-only for diagnosis. It does **not** prohibit creating or updating the debug report. The agent should use available file-writing tools to write exactly the report under `.unipi/docs/debug/`. If writing that report fails, report the write failure explicitly.
16
+
15
17
  **This is diagnosis only — not fixing.**
16
18
 
17
19
  ## Command Format
@@ -21,7 +23,7 @@ Active investigation to reproduce, diagnose, and root-cause bugs. Produces a str
21
23
  ```
22
24
 
23
25
  - `string(greedy)` — bug description, error message, or reproduction steps
24
- - Read-only sandbox + write to `.unipi/docs/debug/`
26
+ - Source/code read-only sandbox, with explicit permission to write the debug report to `.unipi/docs/debug/`
25
27
  - Spawns subagents if `@unipi/subagents` extension is installed
26
28
 
27
29
  ## Output Path
@@ -104,7 +106,7 @@ Deep dive into root cause:
104
106
 
105
107
  ### Phase 4: Document Findings
106
108
 
107
- Write debug report to `.unipi/docs/debug/YYYY-MM-DD-<topic>-debug.md`:
109
+ Write debug report to `.unipi/docs/debug/YYYY-MM-DD-<topic>-debug.md` using the available file-writing tool. Do not skip this because the investigation is otherwise read-only:
108
110
 
109
111
  ```markdown
110
112
  ---
@@ -179,22 +179,45 @@ Do NOT re-read or re-edit the spec checkboxes — Phase 4 already wrote them.
179
179
 
180
180
  ## Phase 6: Present & Handoff
181
181
 
182
- Present plan summary to user. Then ask:
183
-
184
- 1. **Proceed to /unipi:work** — Start implementing in a worktree
185
- 2. **Proceed to /unipi:auto** — Run full pipeline (work → review → merge)
186
- 3. **Revise plan** Adjust tasks or scope
187
- 4. **Done for now** — Return later
182
+ Present plan summary to user. Then ask what to do next. If `ask_user` is available, prefer structured handoff options using `action: "new_session"` so the selected workflow can be queued automatically:
183
+
184
+ ```ts
185
+ ask_user({
186
+ question: "What would you like to do next?",
187
+ options: [
188
+ {
189
+ label: "Proceed to /unipi:work",
190
+ description: "Start implementing the plan",
191
+ value: "work",
192
+ action: "new_session",
193
+ prefill: "<work-command>",
194
+ },
195
+ {
196
+ label: "Proceed to /unipi:auto",
197
+ description: "Run full pipeline (work → review → merge)",
198
+ value: "auto",
199
+ action: "new_session",
200
+ prefill: "/unipi:auto plan:YYYY-MM-DD-<topic>-plan.md",
201
+ },
202
+ { label: "Revise plan", description: "Adjust tasks or scope", value: "revise" },
203
+ { label: "Done for now", description: "Return later", value: "done", action: "end_turn" },
204
+ ],
205
+ allowFreeform: false,
206
+ })
207
+ ```
188
208
 
189
- If user selects "Proceed to /unipi:work":
190
- - **Worktree branch** → suggest: `/unipi:work worktree:<branch-name> specs:YYYY-MM-DD-<topic>-plan`
191
- - **Main branch** → suggest: `/unipi:work specs:YYYY-MM-DD-<topic>-plan` (no worktree arg)
209
+ Use the correct `<work-command>`:
210
+ - **Worktree branch** → `/unipi:work worktree:<branch-name> specs:YYYY-MM-DD-<topic>-plan`
211
+ - **Main branch** → `/unipi:work specs:YYYY-MM-DD-<topic>-plan` (no worktree arg)
192
212
 
193
- If user selects "Proceed to /unipi:auto":
194
- - **Worktree branch** → suggest: `/unipi:auto plan:YYYY-MM-DD-<topic>-plan.md`
195
- - **Main branch** → suggest: `/unipi:auto plan:YYYY-MM-DD-<topic>-plan.md` (same — auto reads workbranch from plan)
213
+ Copyable fallback commands when `ask_user` is unavailable:
214
+ ```
215
+ /unipi:work worktree:<branch-name> specs:YYYY-MM-DD-<topic>-plan
216
+ /unipi:work specs:YYYY-MM-DD-<topic>-plan
217
+ /unipi:auto plan:YYYY-MM-DD-<topic>-plan.md
218
+ ```
196
219
 
197
- Recommend starting a **new session** for work if using a worktree.
220
+ Recommend starting a **new session** for work if using a worktree; the ask_user launcher handles compact/direct queuing when available.
198
221
 
199
222
  ---
200
223
 
@@ -117,18 +117,34 @@ Followed by description explaining the status.
117
117
 
118
118
  ## Phase 5: Handoff
119
119
 
120
- Based on review results:
120
+ Based on review results, use `ask_user` `new_session` options when available so the selected next workflow command can be queued automatically. If `ask_user` is unavailable, present the same choices conversationally and keep copyable commands visible.
121
121
 
122
122
  **If all tasks done and checks pass:**
123
123
 
124
124
  *If `workbranch` is set (worktree):*
125
125
  > "All tasks complete and verified. Ready to merge back to main."
126
+
127
+ Offer:
128
+ ```ts
129
+ ask_user({
130
+ question: "Merge this worktree now?",
131
+ options: [
132
+ { label: "Proceed to /unipi:worktree-merge", value: "merge", action: "new_session", prefill: "/unipi:worktree-merge" },
133
+ { label: "Consolidate learnings", value: "consolidate", action: "new_session", prefill: "/unipi:consolidate" },
134
+ { label: "Done for now", value: "done", action: "end_turn" },
135
+ ],
136
+ allowFreeform: false,
137
+ })
138
+ ```
139
+ Copyable fallback:
126
140
  ```
127
141
  /unipi:worktree-merge
128
142
  ```
129
143
 
130
144
  *If `workbranch` is empty (main branch):*
131
145
  > "All tasks complete and verified. Changes already on main — no merge needed."
146
+
147
+ Offer `/unipi:consolidate` as a `new_session` handoff when available. Copyable fallback:
132
148
  ```
133
149
  /unipi:consolidate
134
150
  ```
@@ -141,6 +157,8 @@ Either way, user can consolidate learnings:
141
157
  **If tasks incomplete or checks fail:**
142
158
  > "Tasks remaining and/or checks failing. Continue work?"
143
159
 
160
+ Offer the applicable `/unipi:work ...` command as a `new_session` handoff when available.
161
+
144
162
  *If `workbranch` is set:*
145
163
  ```
146
164
  /unipi:work worktree:<branch> specs:<plan-path>
@@ -153,6 +171,8 @@ Either way, user can consolidate learnings:
153
171
 
154
172
  **If scoped review complete:**
155
173
  > "Scoped review complete. Run full review or continue work?"
174
+
175
+ Offer both commands as `new_session` options when available:
156
176
  ```
157
177
  /unipi:review-work plan:<plan-path> (full review)
158
178
  /unipi:work specs:<plan-path> (continue work)
@@ -163,13 +163,34 @@ When all tasks are `completed:`:
163
163
 
164
164
  **If working in worktree:**
165
165
  > "All tasks complete. Worktree: `{branch}`. Recommend reviewing before merge."
166
+
167
+ If `ask_user` is available, offer an automatic handoff:
168
+ ```ts
169
+ ask_user({
170
+ question: "Review this work now?",
171
+ options: [
172
+ {
173
+ label: "Proceed to /unipi:review-work",
174
+ description: "Review before merge",
175
+ value: "review",
176
+ action: "new_session",
177
+ prefill: "/unipi:review-work plan:<plan-path>",
178
+ },
179
+ { label: "Done for now", value: "done", action: "end_turn" },
180
+ ],
181
+ allowFreeform: false,
182
+ })
183
+ ```
184
+ Copyable fallback:
166
185
  ```
167
186
  /unipi:review-work plan:<plan-path>
168
187
  ```
169
- **Recommend starting a new session** for review.
188
+ **Recommend starting a new session** for review; the ask_user launcher can compact/direct queue the command.
170
189
 
171
190
  **If working on main branch:**
172
191
  > "All tasks complete. All changes committed directly on main."
192
+
193
+ If `ask_user` is available, offer the same review handoff with `prefill: "/unipi:review-work plan:<plan-path>"`. Copyable fallback:
173
194
  ```
174
195
  /unipi:review-work plan:<plan-path>
175
196
  ```