mirror of
https://github.com/wassname/pi-plan.git
synced 2026-09-26 14:10:23 +08:00
Make planning goals concrete
This commit is contained in:
+31
-2
@@ -5,7 +5,11 @@ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import piGoalsExtension from "../src/index.js";
|
||||
|
||||
function setup(selectChoices: Array<string | undefined>, editorChoices: Array<string | undefined> = []) {
|
||||
function setup(
|
||||
selectChoices: Array<string | undefined>,
|
||||
editorChoices: Array<string | undefined> = [],
|
||||
editPlan?: () => Promise<string | undefined>,
|
||||
) {
|
||||
const cwd = mkdtempSync(join(tmpdir(), "pi-goals-flow-"));
|
||||
const commands = new Map<string, any>();
|
||||
const hooks = new Map<string, any>();
|
||||
@@ -28,7 +32,7 @@ function setup(selectChoices: Array<string | undefined>, editorChoices: Array<st
|
||||
},
|
||||
editor: async () => {
|
||||
events.push("editor");
|
||||
return editorChoices.shift();
|
||||
return editPlan ? editPlan() : editorChoices.shift();
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -88,6 +92,29 @@ describe("/goals draft flow", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("waits for Refine notes before starting a revision turn", async () => {
|
||||
let submitNotes: (notes: string) => void;
|
||||
const flow = setup(["Refine"], [], () => new Promise((resolve) => {
|
||||
submitNotes = resolve;
|
||||
}));
|
||||
try {
|
||||
await flow.commands.get("goals").handler("objective", flow.ctx);
|
||||
const planPath = join(flow.cwd, ".pi/plan/session-a-v1.md");
|
||||
writeFileSync(planPath, "# Plan\n\n## Goals\n\n1. [ ] goal: make this specific\n");
|
||||
|
||||
const review = flow.hooks.get("agent_settled")({}, flow.ctx);
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
expect(flow.events).toEqual(["display", "select", "editor"]);
|
||||
expect(flow.messages.filter((message) => !message.display)).toHaveLength(1);
|
||||
|
||||
submitNotes!("Name the output artifact.");
|
||||
await review;
|
||||
expect(flow.messages.at(-1)?.content).toContain("Revise the plan at");
|
||||
} finally {
|
||||
rmSync(flow.cwd, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("starts work only when the human chooses Ready", async () => {
|
||||
const flow = setup(["Ready"]);
|
||||
try {
|
||||
@@ -140,6 +167,7 @@ describe("/goals draft flow", () => {
|
||||
const writePlan = await flow.hooks.get("tool_call")({ toolName: "write", input: { path: planPath } }, flow.ctx);
|
||||
const writeCode = await flow.hooks.get("tool_call")({ toolName: "write", input: { path: "README.md" } }, flow.ctx);
|
||||
const readShell = await flow.hooks.get("tool_call")({ toolName: "bash", input: { command: "pwd && ls && git log" } }, flow.ctx);
|
||||
const changeDirectoryThenRead = await flow.hooks.get("tool_call")({ toolName: "bash", input: { command: "cd . && ls -la" } }, flow.ctx);
|
||||
const pipeShell = await flow.hooks.get("tool_call")({ toolName: "bash", input: { command: "ls | head" } }, flow.ctx);
|
||||
const pythonWrite = await flow.hooks.get("tool_call")({ toolName: "bash", input: { command: "python -c \"open('README.md', 'w')\"" } }, flow.ctx);
|
||||
const signoff = await flow.tools.get("CompleteGoal").execute("", { goal: "work" }, undefined, undefined, flow.ctx);
|
||||
@@ -149,6 +177,7 @@ describe("/goals draft flow", () => {
|
||||
expect(writePlan).toBeUndefined();
|
||||
expect(writeCode?.block).toBe(true);
|
||||
expect(readShell).toBeUndefined();
|
||||
expect(changeDirectoryThenRead).toBeUndefined();
|
||||
expect(pipeShell?.block).toBe(true);
|
||||
expect(pythonWrite?.block).toBe(true);
|
||||
expect(signoff.isError).toBe(true);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { planDrafting, planningState } from "../src/prompts.js";
|
||||
|
||||
describe("planning prompt", () => {
|
||||
it("requires fact finding or a focused question before a goal", () => {
|
||||
expect(planDrafting).toContain("Use read-only tools to resolve discoverable facts.");
|
||||
expect(planDrafting).toContain("ask the\nhuman one focused question");
|
||||
expect(planDrafting).toContain("placeholder goal such as \"work out the thing\"");
|
||||
expect(planDrafting).toContain("object and an observable result");
|
||||
});
|
||||
|
||||
it("restores the same rule after compaction", () => {
|
||||
expect(planningState(".pi/plan/test.md")).toContain("Use read-only tools to find facts yourself");
|
||||
expect(planningState(".pi/plan/test.md")).toContain("one focused question");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user