mirror of
https://github.com/wassname/pi-plan.git
synced 2026-09-25 14:00:15 +08:00
Name goals files <last 6 of session id>-vN.md, as main's plan files did
Session IDs start with a timestamp, so the last 6 characters are the distinguishing part. A new /goals new in the same session makes the next version and never overwrites (flag wx). Co-Authored-By: Claude <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
@@ -27,7 +27,7 @@ pi-goals bundles the scheduler. Install pi-subagents yourself (0.70.1 tested); t
|
||||
## Use
|
||||
|
||||
```
|
||||
/goals new <idea> discuss and draft .pi/goals/<session>-<id>.md; nothing runs yet
|
||||
/goals new <idea> discuss and draft .pi/goals/<last 6 of session id>-vN.md; nothing runs yet
|
||||
/goals review show the draft with Ready / Refine / Edit / Cancel
|
||||
/goals pause remove the scheduled loop; the file stays
|
||||
/goals resume start a new loop for the paused goals
|
||||
|
||||
+8
-4
@@ -1,6 +1,6 @@
|
||||
// PI/OpenAI: one agent, one goals file, human Ready, and a stock scheduled loop.
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join, relative, resolve } from "node:path";
|
||||
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
||||
import { Type } from "typebox";
|
||||
@@ -124,11 +124,15 @@ export default function piGoals(pi: ExtensionAPI): void {
|
||||
}
|
||||
if (arg !== "new" && !arg.startsWith("new ")) throw new Error("Use /goals new [idea], review, pause, resume, clear, or judge.");
|
||||
if (state.file) throw new Error("Clear the current goals before starting new ones; the file is preserved.");
|
||||
const file = join(ctx.cwd, ".pi/goals", `${ctx.sessionManager.getSessionId()}-${randomUUID().slice(0, 8)}.md`);
|
||||
mkdirSync(dirname(file), { recursive: true });
|
||||
const idea = arg.slice(3).trim();
|
||||
const dir = join(ctx.cwd, ".pi/goals");
|
||||
mkdirSync(dir, { recursive: true });
|
||||
// Session IDs start with a timestamp; the last 6 characters differ between sessions.
|
||||
const suffix = ctx.sessionManager.getSessionId().slice(-6);
|
||||
const taken = readdirSync(dir).map(name => Number(new RegExp(`^${suffix}-v(\\d+)\\.md$`).exec(name)?.[1] ?? 0));
|
||||
const file = join(dir, `${suffix}-v${Math.max(0, ...taken) + 1}.md`);
|
||||
// Slash commands skip the input hook; keep the user's opening words verbatim too.
|
||||
writeFileSync(file, idea ? appendInterview("", `/goals new ${idea}`).trimStart() : "");
|
||||
writeFileSync(file, idea ? appendInterview("", `/goals new ${idea}`).trimStart() : "", { flag: "wx" });
|
||||
state = { ...state, owner: ctx.sessionManager.getSessionId(), phase: "planning", file };
|
||||
generation++; reviewRequested = false; resyncDue = false;
|
||||
persist(); refresh(ctx);
|
||||
|
||||
+10
-1
@@ -16,7 +16,7 @@ describe("planning and Ready", () => {
|
||||
const h = setup({ choices: ["Ready"] });
|
||||
await h.commands.get("goals").handler("new plot the data", h.ctx);
|
||||
const file = h.branch.findLast(e => e.customType === "pi-goals-single-agent").data.file;
|
||||
expect(file).toMatch(/\.pi\/goals\/sess-[\w]+\.md$/);
|
||||
expect(file).toMatch(/\.pi\/goals\/sess-v1\.md$/);
|
||||
expect(readFileSync(file, "utf8")).toContain("> /goals new plot the data");
|
||||
writeFileSync(file, GOALS);
|
||||
await h.hook("input", { source: "interactive", text: "yes, reuse judge_demos.py" });
|
||||
@@ -32,6 +32,15 @@ describe("planning and Ready", () => {
|
||||
expect(await h.hook("tool_call", { toolName: "write", input: { path: "train.py" } })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("a second /goals new in the same session makes -v2 and keeps v1", async () => {
|
||||
const h = setup();
|
||||
await h.commands.get("goals").handler("new first", h.ctx);
|
||||
await h.commands.get("goals").handler("clear", h.ctx);
|
||||
await h.commands.get("goals").handler("new second", h.ctx);
|
||||
expect(h.branch.findLast(e => e.customType === "pi-goals-single-agent").data.file).toMatch(/sess-v2\.md$/);
|
||||
expect(readFileSync(`${h.cwd}/.pi/goals/sess-v1.md`, "utf8")).toContain("new first");
|
||||
});
|
||||
|
||||
it("Cancel starts nothing and keeps the file", async () => {
|
||||
const h = setup({ choices: ["Cancel"] });
|
||||
const file = await ready(h);
|
||||
|
||||
Reference in New Issue
Block a user