diff --git a/.pi/skills/chat-to-plan/SKILL.md b/.pi/skills/chat-to-plan/SKILL.md new file mode 100644 index 0000000..8132a39 --- /dev/null +++ b/.pi/skills/chat-to-plan/SKILL.md @@ -0,0 +1,122 @@ +--- +name: chat-to-plan +description: Enrich a plan markdown with precise file locations, API signatures, and event firing conditions. Use when a plan has been discussed in chat and needs to be made implementation-ready, or when asked to "enrich a plan", "refine a plan", or "chat-to-plan". +--- + +# Chat-to-Plan Enrichment + +Take a plan written in chat or a markdown file and enrich it with precise, verifiable details so a coding agent can execute it without guessing. + +## When to Use + +- A plan has been discussed in chat and needs to be written to markdown +- A markdown plan exists but lacks file locations, API signatures, or event details +- The user says "enrich this plan", "refine the plan", or "chat-to-plan " + +## Enrichment Checklist + +For each phase/step in the plan, add the following where applicable: + +### 1. File Locations +- **What to do:** Grep the source code to find the exact files that need modification. +- **How:** Use `grep`/`find`/`rg` to locate relevant code, imports, and type definitions. +- **Output:** A table or list of files with a brief note on what changes in each. +- **Example:** + ``` + | File | Change | + |------|--------| + | `src/turn-limit.ts` | Add command registration, widget updates, confirmation logic | + ``` + +### 2. API Signatures +- **What to do:** Grep the pi-coding-agent type definitions for exact handler signatures. +- **How:** Search `~/.local/share/mise/installs/node/*/lib/node_modules/@mariozechner/pi-coding-agent/dist/core/extensions/types.d.ts` for relevant interfaces. +- **Key things to check:** + - `registerCommand` handler signature: `(args: string, ctx: ExtensionCommandContext) => Promise` + - `registerShortcut` handler signature: `(ctx: ExtensionContext) => Promise | void` + - `registerFlag` options shape + - `ui.confirm`, `ui.notify`, `ui.setWidget` signatures + - Event handler signatures: `(event: E, ctx: ExtensionContext) => Promise` +- **Output:** Include the exact signature in the plan, not just a description. +- **Example:** + ``` + Handler signature: `async (args: string, ctx: ExtensionCommandContext) => Promise` + - `args` is a single string (not array), use `args.trim().split(/\s+/)` for parsing + ``` + +### 3. Event Firing Conditions +- **What to do:** Check when each event fires (fresh start, reload, compact, etc.). +- **How:** Search `agent-session.js` for `this._extensionRunner.emit({ type: "..."` to find event emission points. +- **Key mappings:** + - `session_start` with `reason: "startup"` — fresh session start + - `session_start` with `reason: "reload"` — session reload + - `agent_start` — agent begins a new turn (NOT on reload) + - `turn_start` — each agent turn begins + - `agent_end` — agent finishes a turn +- **Output:** Note when each event fires in the plan. +- **Example:** + ``` + Note: `session_start` fires on both startup (reason: "startup") and reload (reason: "reload"). + `agent_start` only fires when the agent begins a turn, NOT on reload. + ``` + +### 4. Required Imports +- **What to do:** Check what imports are needed for new APIs. +- **How:** Look at existing imports in the file and grep for new types/functions. +- **Output:** List any new imports needed. +- **Example:** + ``` + No new imports needed — `pi.registerCommand` is available on the `pi` object. + ``` + +### 5. Type Definitions to Reference +- **What to do:** Note which type interfaces are relevant. +- **How:** List the exact interface names from the type definitions. +- **Output:** Link to the relevant types. +- **Example:** + ``` + Relevant types: `RegisteredCommand`, `ExtensionCommandContext`, `ExtensionContext`, `ExtensionAPI` + Location: `@mariozechner/pi-coding-agent/dist/core/extensions/types.d.ts` + ``` + +## Process + +1. **Read the plan** — understand what needs to be implemented. +2. **Grep source files** — find the exact files, functions, and types involved. +3. **Grep pi-coding-agent types** — find exact API signatures. +4. **Grep event emission points** — find when events fire. +5. **Enrich the plan** — add the findings to the markdown. +6. **Save the enriched plan** — overwrite the original file or create a new one. + +## Example Enrichment + +Given a plan phase like: +```markdown +- [ ] Add `/turn-limit` command + - Register via `pi.registerCommand()` + - Handler parses args, validates positive integer + - Updates `maxTurns` in-memory variable +``` + +Enrich it to: +```markdown +- [ ] Add `/turn-limit` command + - **File:** `packages/pi-turn-limit/src/turn-limit.ts` + - **API:** `pi.registerCommand("turn-limit", { description, handler })` + - **Handler signature:** `async (args: string, ctx: ExtensionCommandContext) => Promise` + - `args` is a single string — use `args.trim().split(/\s+/)` for parsing + - `ctx` is `ExtensionCommandContext` (extends `ExtensionContext`) — has `ctx.ui`, `ctx.abort()` + - **Handler:** + - Parse `args.trim()` as integer + - If invalid: `ctx.ui.notify("Invalid turn limit. Must be a positive integer.", "error")` + - Update `maxTurns` in-memory variable (change `const` to `let`) + - `ctx.ui.setWidget("turn-limit", ["Turns: ${turnCount}/${maxTurns}"])` + - `ctx.ui.notify("Turn limit set to {N}.", "info")` +``` + +## Tips + +- **Be specific, not descriptive.** Prefer exact signatures over "parses args as integer". +- **Verify before including.** Don't guess — grep the actual files. +- **Keep it concise.** The enrichment should make the plan actionable, not bloated. +- **Preserve the original structure.** Add enrichment inline, don't rewrite the plan. diff --git a/packages/pi-turn-limit/src/turn-limit.ts b/packages/pi-turn-limit/src/turn-limit.ts index f36a12e..6078882 100644 --- a/packages/pi-turn-limit/src/turn-limit.ts +++ b/packages/pi-turn-limit/src/turn-limit.ts @@ -71,7 +71,7 @@ export default function (pi: ExtensionAPI) { }, }); - pi.on("turn_start", async (event, ctx) => { + pi.on("turn_start", async (_event, ctx) => { turnCount++; // Update live widget @@ -105,14 +105,5 @@ export default function (pi: ExtensionAPI) { return; } } - - const { exceeded } = checkTurnLimit(event.turnIndex, maxTurns); - if (exceeded && ctx.hasUI) { - ctx.ui.notify( - `Turn limit exceeded: ${maxTurns} turns reached. Agent aborted.`, - "error", - ); - ctx.abort(); - } }); }