Skip to content

Commit ff713f2

Browse files
committed
Release v0.1.26
1 parent b640348 commit ff713f2

5 files changed

Lines changed: 34 additions & 10 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ A global [Pi coding agent](https://github.com/badlogic/pi-mono) extension that a
1919
- **Switch to Build and implement here**
2020
- **Start fresh and implement**
2121
- **Stay in Plan mode**
22-
- Staying in Plan mode produces a durable acknowledgement and stops the run until the user responds.
22+
- Staying in Plan mode—or pressing Escape in the approval dialog—produces a durable acknowledgement and stops the run until the user responds.
2323
- Mode state survives reloads, resumes, and forks.
2424
- When Pi recreates the custom editor, the latest 100 user prompts from the active session branch are restored for Up/Down history navigation.
2525

@@ -76,11 +76,11 @@ When planning is complete, `plan_exit` displays the entire persisted plan and as
7676

7777
Selecting **Start fresh and implement** stops the current run and pre-fills `/build-fresh`. Press Enter to confirm. Pi only exposes session creation to user-invoked command contexts, so this confirmation is required. The command creates a linked child session, copies the approved plan to its canonical plan file, switches it to Build, and starts implementation without transferring the planning conversation.
7878

79-
Selecting **Stay in Plan mode** displays:
79+
Selecting **Stay in Plan mode**, or pressing Escape while the approval dialog is open, displays:
8080

8181
> Staying in Plan mode. Let me know when you’re ready to revise or implement the plan.
8282
83-
The agent then stops and waits for the next user message.
83+
Both actions leave Plan mode active, stop the agent, and wait for the next user message.
8484

8585
## Plan-mode permissions
8686

index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
makePlanPath,
3030
nextMode,
3131
nextThinkingLevel,
32+
normalizePlanExitChoice,
3233
PLAN_EXIT_APPROVE_CHOICE,
3334
PLAN_EXIT_FRESH_CHOICE,
3435
PLAN_EXIT_STAY_ACKNOWLEDGEMENT,
@@ -289,15 +290,15 @@ export default function planBuildModes(pi: ExtensionAPI): void {
289290
if (!plan.trim()) throw new Error("Cannot request plan approval because the plan file is empty");
290291
pi.appendEntry(PLAN_REVIEW_ENTRY_TYPE, { plan, planPath });
291292
const displayPath = shorten(planPath, ctx.cwd);
292-
const choice = await ctx.ui.select(
293+
const selection = normalizePlanExitChoice(await ctx.ui.select(
293294
`Build Agent: Plan at ${displayPath} is complete. What would you like to do?`,
294295
[PLAN_EXIT_APPROVE_CHOICE, PLAN_EXIT_FRESH_CHOICE, PLAN_EXIT_STAY_CHOICE],
295-
);
296-
const decision = classifyPlanExitChoice(choice);
296+
));
297+
const decision = classifyPlanExitChoice(selection.choice);
297298
if (decision === "stay") {
298299
freshImplementationPlan = undefined;
299300
pi.appendEntry(MODE_NOTICE_ENTRY_TYPE, { message: PLAN_EXIT_STAY_ACKNOWLEDGEMENT });
300-
return buildPlanExitStayResult(planPath, choice === undefined);
301+
return buildPlanExitStayResult(planPath, selection.cancelled);
301302
}
302303
if (decision === "implement-fresh") {
303304
freshImplementationPlan = plan;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@janvitos/pi-plan-build",
3-
"version": "0.1.25",
3+
"version": "0.1.26",
44
"description": "Plan safely, approve explicitly, then implement here or in a clean session.",
55
"type": "module",
66
"license": "MIT",

utils.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
makePlanPath,
2323
nextMode,
2424
nextThinkingLevel,
25+
normalizePlanExitChoice,
2526
PLAN_EXIT_APPROVE_CHOICE,
2627
PLAN_EXIT_FRESH_CHOICE,
2728
PLAN_EXIT_STAY_ACKNOWLEDGEMENT,
@@ -202,11 +203,21 @@ test("declining plan exit stays in Plan mode and terminates the run", () => {
202203
assert.equal(cancelled.details.cancelled, true);
203204
});
204205

206+
test("plan exit normalizes Escape to the explicit Stay choice", () => {
207+
assert.deepEqual(normalizePlanExitChoice(undefined), {
208+
choice: PLAN_EXIT_STAY_CHOICE,
209+
cancelled: true,
210+
});
211+
assert.deepEqual(normalizePlanExitChoice(PLAN_EXIT_STAY_CHOICE), {
212+
choice: PLAN_EXIT_STAY_CHOICE,
213+
cancelled: false,
214+
});
215+
});
216+
205217
test("plan exit classifies all three choices and fails safe", () => {
206218
assert.equal(classifyPlanExitChoice(PLAN_EXIT_APPROVE_CHOICE), "implement-here");
207219
assert.equal(classifyPlanExitChoice(PLAN_EXIT_FRESH_CHOICE), "implement-fresh");
208220
assert.equal(classifyPlanExitChoice(PLAN_EXIT_STAY_CHOICE), "stay");
209-
assert.equal(classifyPlanExitChoice(undefined), "stay");
210221
assert.equal(classifyPlanExitChoice("unexpected value"), "stay");
211222
});
212223

utils.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,19 @@ export const PLAN_EXIT_STAY_ACKNOWLEDGEMENT =
139139

140140
export type PlanExitDecision = "implement-here" | "implement-fresh" | "stay";
141141

142-
export function classifyPlanExitChoice(choice: string | undefined): PlanExitDecision {
142+
export interface NormalizedPlanExitChoice {
143+
choice: string;
144+
cancelled: boolean;
145+
}
146+
147+
export function normalizePlanExitChoice(choice: string | undefined): NormalizedPlanExitChoice {
148+
return {
149+
choice: choice ?? PLAN_EXIT_STAY_CHOICE,
150+
cancelled: choice === undefined,
151+
};
152+
}
153+
154+
export function classifyPlanExitChoice(choice: string): PlanExitDecision {
143155
if (choice === PLAN_EXIT_APPROVE_CHOICE) return "implement-here";
144156
if (choice === PLAN_EXIT_FRESH_CHOICE) return "implement-fresh";
145157
return "stay";

0 commit comments

Comments
 (0)