@janvitos/pi-plan-build 0.1.24 → 0.1.26

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
@@ -8,7 +8,7 @@ A global [Pi coding agent](https://github.com/badlogic/pi-mono) extension that a
8
8
 
9
9
  - New sessions start in **Build** mode.
10
10
  - Bare `Tab` cycles **Build → Plan → Build**, while active autocomplete dropdowns retain Pi's normal Tab completion.
11
- - The composer uses OpenCode prompt-inspired blue/orange mode colors on the rounded top-left border and left rail, complemented by Pi's border color on the right rail and rounded bottom-right border; dim rounded corners with color-matched horizontal `╌` segments bridge the borders at both junctions, paired with a light vertical `┆` at the top right and a mode-specific bottom-left transition: thin `┆` in Plan and heavy `┇` in Build. It also includes a mode/model/thinking metadata row; cycling the thinking level updates this row without adding a duplicate status above the composer. The model is shown as `model-id [provider]` (for example, `gpt-5.6-luna [openai]`), with the model ID inheriting the terminal foreground like unselected entries in `/model` and the provider using the footer's dim text color. The footer keeps the remaining path and usage stats without duplicating model metadata.
11
+ - The composer uses OpenCode prompt-inspired blue/orange mode colors on the rounded top-left border and left rail, complemented by Pi's border color on the right rail and rounded bottom-right border; rounded corners inherit their vertical rail colors while horizontal `╌` segments bridge the borders at both junctions, paired with a light vertical `┆` at the top right and a mode-specific bottom-left transition: thin `┆` in Plan and heavy `┇` in Build. It also includes a mode/model/thinking metadata row; cycling the thinking level updates this row without adding a duplicate status above the composer. The model is shown as `model-id [provider]` (for example, `gpt-5.6-luna [openai]`), with the model ID inheriting the terminal foreground like unselected entries in `/model` and the provider using the footer's dim text color. The footer keeps the remaining path and usage stats without duplicating model metadata.
12
12
  - `/plan`, `/build`, and the `--plan` startup flag.
13
13
  - Per-session plans at `~/.pi/agent/plans/<session-id>.md`.
14
14
  - In Plan mode, built-in `edit` and `write` are restricted to the exact plan file.
@@ -19,7 +19,7 @@ A global [Pi coding agent](https://github.com/badlogic/pi-mono) extension that a
19
19
  - **Switch to Build and implement here**
20
20
  - **Start fresh and implement**
21
21
  - **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.
23
23
  - Mode state survives reloads, resumes, and forks.
24
24
  - When Pi recreates the custom editor, the latest 100 user prompts from the active session branch are restored for Up/Down history navigation.
25
25
 
@@ -76,11 +76,11 @@ When planning is complete, `plan_exit` displays the entire persisted plan and as
76
76
 
77
77
  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.
78
78
 
79
- Selecting **Stay in Plan mode** displays:
79
+ Selecting **Stay in Plan mode**, or pressing Escape while the approval dialog is open, displays:
80
80
 
81
81
  > Staying in Plan mode. Let me know when you’re ready to revise or implement the plan.
82
82
 
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.
84
84
 
85
85
  ## Plan-mode permissions
86
86
 
package/index.ts CHANGED
@@ -29,6 +29,7 @@ import {
29
29
  makePlanPath,
30
30
  nextMode,
31
31
  nextThinkingLevel,
32
+ normalizePlanExitChoice,
32
33
  PLAN_EXIT_APPROVE_CHOICE,
33
34
  PLAN_EXIT_FRESH_CHOICE,
34
35
  PLAN_EXIT_STAY_ACKNOWLEDGEMENT,
@@ -289,15 +290,15 @@ export default function planBuildModes(pi: ExtensionAPI): void {
289
290
  if (!plan.trim()) throw new Error("Cannot request plan approval because the plan file is empty");
290
291
  pi.appendEntry(PLAN_REVIEW_ENTRY_TYPE, { plan, planPath });
291
292
  const displayPath = shorten(planPath, ctx.cwd);
292
- const choice = await ctx.ui.select(
293
+ const selection = normalizePlanExitChoice(await ctx.ui.select(
293
294
  `Build Agent: Plan at ${displayPath} is complete. What would you like to do?`,
294
295
  [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);
297
298
  if (decision === "stay") {
298
299
  freshImplementationPlan = undefined;
299
300
  pi.appendEntry(MODE_NOTICE_ENTRY_TYPE, { message: PLAN_EXIT_STAY_ACKNOWLEDGEMENT });
300
- return buildPlanExitStayResult(planPath, choice === undefined);
301
+ return buildPlanExitStayResult(planPath, selection.cancelled);
301
302
  }
302
303
  if (decision === "implement-fresh") {
303
304
  freshImplementationPlan = plan;
@@ -506,7 +507,7 @@ export default function planBuildModes(pi: ExtensionAPI): void {
506
507
  width - 1,
507
508
  "",
508
509
  );
509
- const topBorder = formatModeTopBorder(selectedMode, width, ctx.ui.theme.fg("dim", "╮"));
510
+ const topBorder = formatModeTopBorder(selectedMode, width, this.borderColor("╮"));
510
511
  return renderModeComposer(
511
512
  lines,
512
513
  topBorder,
@@ -514,7 +515,7 @@ export default function planBuildModes(pi: ExtensionAPI): void {
514
515
  rightRail,
515
516
  topRightVerticalTransition,
516
517
  metadata,
517
- ctx.ui.theme.fg("dim", "╰"),
518
+ formatModeRail(selectedMode, "╰"),
518
519
  railWidth,
519
520
  width,
520
521
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@janvitos/pi-plan-build",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Plan safely, approve explicitly, then implement here or in a clean session.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/utils.ts CHANGED
@@ -139,7 +139,19 @@ export const PLAN_EXIT_STAY_ACKNOWLEDGEMENT =
139
139
 
140
140
  export type PlanExitDecision = "implement-here" | "implement-fresh" | "stay";
141
141
 
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 {
143
155
  if (choice === PLAN_EXIT_APPROVE_CHOICE) return "implement-here";
144
156
  if (choice === PLAN_EXIT_FRESH_CHOICE) return "implement-fresh";
145
157
  return "stay";