From 6cd93546cbea7a7fde7adb28dc2e8a7a5e247368 Mon Sep 17 00:00:00 2001 From: roboomp Date: Wed, 1 Jul 2026 17:19:20 +0000 Subject: [PATCH 1/2] fix(agent): preserved approved plan path Approved plan execution now requires reading the durable local plan file instead of embedding the plan body in synthetic execution prompts. This keeps execution recoverable when Headroom-compressed inline content expires. Fixes #4164 --- packages/coding-agent/CHANGELOG.md | 4 +++ .../plan-mode/approved-plan-prompt.test.ts | 32 +++++++++++++++++++ .../src/prompts/system/plan-mode-approved.md | 17 ++++------ .../system/plan-mode-compact-instructions.md | 3 +- .../src/prompts/system/plan-mode-reference.md | 7 ++-- .../coding-agent/src/session/agent-session.ts | 4 +-- 6 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index d1722f2ec..498bdc858 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed approved plan execution prompts embedding the full plan instead of requiring the executor to read the durable `local://-plan.md` file. ([#4164](https://github.com/can1357/oh-my-pi/issues/4164)) + ## [16.2.12] - 2026-07-01 ### Breaking Changes diff --git a/packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts b/packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts new file mode 100644 index 000000000..fd833d8da --- /dev/null +++ b/packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "bun:test"; +import { prompt } from "@oh-my-pi/pi-utils"; +import planModeApprovedPrompt from "../prompts/system/plan-mode-approved.md" with { type: "text" }; +import planModeCompactInstructionsPrompt from "../prompts/system/plan-mode-compact-instructions.md" with { type: "text" }; +import planModeReferencePrompt from "../prompts/system/plan-mode-reference.md" with { type: "text" }; + +const PLAN_FILE_PATH = "local://durable-plan.md"; +const PLAN_SENTINEL = "SENTINEL_HEADROOM_COMPRESSED_PLAN_CONTENT"; + +describe("approved plan execution prompts", () => { + it("loads the approved plan from the durable local file instead of embedding content", () => { + const approved = prompt.render(planModeApprovedPrompt, { + planContent: PLAN_SENTINEL, + planFilePath: PLAN_FILE_PATH, + contextPreserved: false, + }); + const reference = prompt.render(planModeReferencePrompt, { + planContent: PLAN_SENTINEL, + planFilePath: PLAN_FILE_PATH, + }); + const compact = prompt.render(planModeCompactInstructionsPrompt, { + planFilePath: PLAN_FILE_PATH, + }); + + for (const rendered of [approved, reference, compact]) { + expect(rendered).toContain(PLAN_FILE_PATH); + expect(rendered).not.toContain(PLAN_SENTINEL); + } + expect(approved).toContain("MUST read `local://durable-plan.md`"); + expect(reference).toContain("MUST read `local://durable-plan.md`"); + }); +}); diff --git a/packages/coding-agent/src/prompts/system/plan-mode-approved.md b/packages/coding-agent/src/prompts/system/plan-mode-approved.md index 7b8b0df5f..96b7f9347 100644 --- a/packages/coding-agent/src/prompts/system/plan-mode-approved.md +++ b/packages/coding-agent/src/prompts/system/plan-mode-approved.md @@ -1,25 +1,22 @@ Plan approved. {{#if contextPreserved}} -- Context preserved. Use conversation history when useful; this plan is the source of truth if it conflicts with earlier exploration. +- Context preserved. Use conversation history when useful; the plan file is the source of truth if it conflicts with earlier exploration. {{/if}} -You MUST execute this plan step by step. You have full tool access. +You MUST read `{{planFilePath}}` before executing. +The file content is the authoritative plan; visible/compressed context is secondary. +Read failure? Report the exact path and error instead of guessing. +After reading, you MUST execute the plan step by step with full tool access. You MUST verify each step before proceeding to the next. {{#has tools "todo"}} -Before execution, initialize todo tracking with `todo`. +After reading the plan, initialize todo tracking with `todo`. After each completed step, immediately update `todo`. If `todo` fails, fix the payload and retry before continuing. {{/has}} -The plan path is for subagent handoff only. You already have the plan; NEVER read it. -The full plan is injected below. You MUST execute it now: - - -{{planContent}} - - +NEVER stop because inline plan content is compressed, expired, or unrecoverable. Read `{{planFilePath}}`. You MUST keep going until complete. This matters. diff --git a/packages/coding-agent/src/prompts/system/plan-mode-compact-instructions.md b/packages/coding-agent/src/prompts/system/plan-mode-compact-instructions.md index 1bc8d9a33..02be72a89 100644 --- a/packages/coding-agent/src/prompts/system/plan-mode-compact-instructions.md +++ b/packages/coding-agent/src/prompts/system/plan-mode-compact-instructions.md @@ -12,5 +12,6 @@ You MUST drop: - Restated context already present in the plan file. {{#if planFilePath}} -The approved plan file is at `{{planFilePath}}`; it is the authoritative source of truth and need not be re-summarized in detail. +The approved plan file is at `{{planFilePath}}`; it is the authoritative source of truth. +You MUST preserve this durable path and the fact that the executor must read it directly after compaction. {{/if}} diff --git a/packages/coding-agent/src/prompts/system/plan-mode-reference.md b/packages/coding-agent/src/prompts/system/plan-mode-reference.md index 8709a4942..410a707b5 100644 --- a/packages/coding-agent/src/prompts/system/plan-mode-reference.md +++ b/packages/coding-agent/src/prompts/system/plan-mode-reference.md @@ -1,11 +1,10 @@ ## Existing Plan - -{{planContent}} - +The approved plan file is at `{{planFilePath}}`. If this plan is relevant to current work and not complete, you MUST continue executing it. +If you do not have the current plan content in visible context, you MUST read `{{planFilePath}}`. If the plan is stale or unrelated, you MUST ignore it. -The plan path is for subagent handoff only. You already have the plan; NEVER read it. +NEVER stop because inline plan content is compressed, expired, or unrecoverable. Read the file. diff --git a/packages/coding-agent/src/session/agent-session.ts b/packages/coding-agent/src/session/agent-session.ts index 0fa7704da..92e0583d8 100644 --- a/packages/coding-agent/src/session/agent-session.ts +++ b/packages/coding-agent/src/session/agent-session.ts @@ -6523,9 +6523,8 @@ export class AgentSession { const planFilePath = this.#planReferencePath; const resolvedPlanPath = resolveLocalUrlToPath(planFilePath, this.#localProtocolOptions()); - let planContent: string; try { - planContent = await Bun.file(resolvedPlanPath).text(); + await fs.promises.access(resolvedPlanPath, fs.constants.R_OK); } catch (error) { if (isEnoent(error)) { return null; @@ -6535,7 +6534,6 @@ export class AgentSession { const content = prompt.render(planModeReferencePrompt, { planFilePath, - planContent, }); this.#planReferenceSent = true; From 2f7cbdab02db93a972f0589b899f604f5d0717dc Mon Sep 17 00:00:00 2001 From: roboomp Date: Wed, 1 Jul 2026 17:19:44 +0000 Subject: [PATCH 2/2] style: bun run fix --- .../coding-agent/src/plan-mode/approved-plan-prompt.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts b/packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts index fd833d8da..1d54446a0 100644 --- a/packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts +++ b/packages/coding-agent/src/plan-mode/approved-plan-prompt.test.ts @@ -1,7 +1,9 @@ import { describe, expect, it } from "bun:test"; import { prompt } from "@oh-my-pi/pi-utils"; import planModeApprovedPrompt from "../prompts/system/plan-mode-approved.md" with { type: "text" }; -import planModeCompactInstructionsPrompt from "../prompts/system/plan-mode-compact-instructions.md" with { type: "text" }; +import planModeCompactInstructionsPrompt from "../prompts/system/plan-mode-compact-instructions.md" with { + type: "text", +}; import planModeReferencePrompt from "../prompts/system/plan-mode-reference.md" with { type: "text" }; const PLAN_FILE_PATH = "local://durable-plan.md";