mirror of
https://github.com/wassname/pi-goals.git
synced 2026-09-12 12:50:58 +08:00
Use goals subcommands without option prefixes
This commit is contained in:
@@ -91,12 +91,12 @@ is not an OS sandbox. If pi-subagents is absent, Ready stays in planning after a
|
||||
install it, retry Ready, or use `/goals steward off`. The integration is process-local and does not
|
||||
require `pi-intercom`.
|
||||
|
||||
Other commands: `/goals --clear` disconnects this session from its active plan, preserving the
|
||||
versioned file on disk; `/goals --auto [minutes|off]` continues active goals after the agent settles
|
||||
Other commands: `/goals clear` disconnects this session from its active plan, preserving the
|
||||
versioned file on disk; `/goals auto [minutes|off]` continues active goals after the agent settles
|
||||
and then on that interval. It pauses after two automatic wakes with no working-plan change;
|
||||
`/goals --judge <model-ref>` picks a sign-off judge model (default: your current session model, else
|
||||
`/goals judge <model-ref>` picks a sign-off judge model (default: your current session model, else
|
||||
pi's default); `/goals steward [on|off|status]` controls the optional persistent plan steward. The
|
||||
older `--` forms remain only for the existing clear, auto, and judge controls.
|
||||
old `--clear`, `--auto`, and `--judge` forms remain compatibility aliases but are not required.
|
||||
|
||||
## Prompts
|
||||
|
||||
|
||||
+10
-8
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* PI: Each /goals call makes a new plan version, `.pi/plan/<session_id>-vN.md`. The selected version
|
||||
* stays in session state across resume and compaction. Old plans stay on disk but inert, so a new
|
||||
* conversation cannot silently edit them. `/goals --clear` only disconnects this session; the filename is the arm switch: a session that never ran
|
||||
* conversation cannot silently edit them. `/goals clear` only disconnects this session; the filename is the arm switch: a session that never ran
|
||||
* /goals has no active plan, so the widget, injections, and CompleteGoal all stay silent.
|
||||
*
|
||||
* The v1 lesson: the parser existed so TypeScript could read the plan, but almost every reader is a
|
||||
@@ -474,10 +474,10 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
|
||||
// --- /goals: enter plan mode (or clear / set judge / set steward) -------------------------------
|
||||
|
||||
pi.registerCommand("goals", {
|
||||
description: `Plan mode: draft goals into ${PLAN_SHAPE}, review, then work them. /goals <objective> | /goals steward [on|off|status] | /goals --clear | /goals --auto [minutes|off] | /goals --judge <model>`,
|
||||
description: `Plan mode: draft goals into ${PLAN_SHAPE}, review, then work them. /goals <objective> | /goals clear | /goals auto [minutes|off] | /goals judge <model> | /goals steward [on|off|status]`,
|
||||
handler: async (args, ctx) => {
|
||||
const arg = args.trim();
|
||||
if (arg === "--clear") {
|
||||
if (arg === "clear" || arg === "--clear") {
|
||||
if (state.planVersion === null) {
|
||||
ctx.ui.notify("No active plan to disconnect.", "info");
|
||||
return;
|
||||
@@ -500,8 +500,9 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
|
||||
ctx.ui.notify(`Disconnected from ${currentPlan}; the file remains on disk.`, "info");
|
||||
return;
|
||||
}
|
||||
if (arg === "--auto" || arg.startsWith("--auto ")) {
|
||||
const value = arg.slice("--auto".length).trim();
|
||||
if (arg === "auto" || arg.startsWith("auto ") || arg === "--auto" || arg.startsWith("--auto ")) {
|
||||
const command = arg.startsWith("--") ? "--auto" : "auto";
|
||||
const value = arg.slice(command.length).trim();
|
||||
if (value === "off") {
|
||||
clearAutoTimer();
|
||||
state = { ...state, autoIntervalMs: null, autoPaused: false };
|
||||
@@ -516,7 +517,7 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
|
||||
}
|
||||
const minutes = value ? Number(value) : AUTO_DEFAULT_INTERVAL_MS / 60_000;
|
||||
if (!Number.isInteger(minutes) || minutes < 1) {
|
||||
ctx.ui.notify("Use /goals --auto [whole minutes], or /goals --auto off.", "warning");
|
||||
ctx.ui.notify("Use /goals auto [whole minutes], or /goals auto off.", "warning");
|
||||
return;
|
||||
}
|
||||
autoWakeInFlight = false;
|
||||
@@ -562,8 +563,9 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
|
||||
ctx.ui.notify(`Persistent plan steward ${value === "on" ? "enabled" : "disabled"}.`, "info");
|
||||
return;
|
||||
}
|
||||
if (arg === "--judge" || arg.startsWith("--judge ")) {
|
||||
const ref = arg.slice("--judge".length).trim();
|
||||
if (arg === "judge" || arg.startsWith("judge ") || arg === "--judge" || arg.startsWith("--judge ")) {
|
||||
const command = arg.startsWith("--") ? "--judge" : "judge";
|
||||
const ref = arg.slice(command.length).trim();
|
||||
state = { ...state, judgeModel: ref || null };
|
||||
persist();
|
||||
ctx.ui.notify(ref ? `Sign-off judge model set to ${ref}` : "Sign-off judge reset to the session model", "info");
|
||||
|
||||
@@ -98,9 +98,12 @@ describe("/goals draft flow", () => {
|
||||
expect(readFileSync(join(flow.cwd, ".pi/plan/session-a-v2.md"), "utf-8")).toBe("");
|
||||
expect(flow.messages.at(-1)?.content).toContain("session-a-v2.md");
|
||||
|
||||
await flow.commands.get("goals").handler("judge the vendor options", flow.ctx);
|
||||
await flow.commands.get("goals").handler("compare the vendor options", flow.ctx);
|
||||
expect(readFileSync(join(flow.cwd, ".pi/plan/session-a-v3.md"), "utf-8")).toBe("");
|
||||
expect(flow.messages.at(-1)?.content).toContain("Objective: judge the vendor options");
|
||||
expect(flow.messages.at(-1)?.content).toContain("Objective: compare the vendor options");
|
||||
|
||||
await flow.commands.get("goals").handler("judge provider/model", flow.ctx);
|
||||
expect(flow.entries.at(-1)?.data).toMatchObject({ judgeModel: "provider/model", planVersion: 3 });
|
||||
} finally {
|
||||
rmSync(flow.cwd, { recursive: true, force: true });
|
||||
}
|
||||
@@ -113,7 +116,7 @@ describe("/goals draft flow", () => {
|
||||
const planPath = join(flow.cwd, ".pi/plan/session-a-v1.md");
|
||||
writeFileSync(planPath, "# Plan\n\n## Goals\n\n1. [ ] goal: preserve this\n");
|
||||
|
||||
await flow.commands.get("goals").handler("--clear", flow.ctx);
|
||||
await flow.commands.get("goals").handler("clear", flow.ctx);
|
||||
|
||||
expect(readFileSync(planPath, "utf-8")).toContain("goal: preserve this");
|
||||
expect(flow.entries.at(-1)?.data).toMatchObject({ phase: null, planVersion: null });
|
||||
@@ -427,7 +430,7 @@ describe("/goals draft flow", () => {
|
||||
const planPath = join(flow.cwd, ".pi/plan/session-a-v1.md");
|
||||
writeFileSync(planPath, "# Plan\n\n## Goals\n\n1. [/] goal: make the output\n");
|
||||
await flow.hooks.get("agent_settled")({}, flow.ctx);
|
||||
await flow.commands.get("goals").handler("--auto 1", flow.ctx);
|
||||
await flow.commands.get("goals").handler("auto 1", flow.ctx);
|
||||
|
||||
await flow.hooks.get("agent_settled")({}, flow.ctx);
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
@@ -454,7 +457,7 @@ describe("/goals draft flow", () => {
|
||||
const planPath = join(flow.cwd, ".pi/plan/session-a-v1.md");
|
||||
writeFileSync(planPath, "# Plan\n\n## Goals\n\n1. [/] goal: make the output\n");
|
||||
await flow.hooks.get("agent_settled")({}, flow.ctx);
|
||||
await flow.commands.get("goals").handler("--auto 1", flow.ctx);
|
||||
await flow.commands.get("goals").handler("auto 1", flow.ctx);
|
||||
await flow.hooks.get("agent_start")({}, flow.ctx);
|
||||
await flow.hooks.get("tool_call")({ toolName: "process", input: { action: "start" } }, flow.ctx);
|
||||
await flow.hooks.get("agent_settled")({}, flow.ctx);
|
||||
|
||||
Reference in New Issue
Block a user