fix(pi-turn-limit): use turnCount for boundary check instead of event.turnIndex\n\nThe exceeded check used event.turnIndex which keeps incrementing from\nthe original session, causing false aborts after a boundary confirmation\nreset. Now turnCount is used consistently, and the dead exceeded check\nis removed since the boundary at turnCount === maxTurns handles all cases.
This commit is contained in:
parent
a7f9822fa0
commit
191507785f
122
.pi/skills/chat-to-plan/SKILL.md
Normal file
122
.pi/skills/chat-to-plan/SKILL.md
Normal file
@ -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 <file>"
|
||||||
|
|
||||||
|
## 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<void>`
|
||||||
|
- `registerShortcut` handler signature: `(ctx: ExtensionContext) => Promise<void> | void`
|
||||||
|
- `registerFlag` options shape
|
||||||
|
- `ui.confirm`, `ui.notify`, `ui.setWidget` signatures
|
||||||
|
- Event handler signatures: `(event: E, ctx: ExtensionContext) => Promise<R | void>`
|
||||||
|
- **Output:** Include the exact signature in the plan, not just a description.
|
||||||
|
- **Example:**
|
||||||
|
```
|
||||||
|
Handler signature: `async (args: string, ctx: ExtensionCommandContext) => Promise<void>`
|
||||||
|
- `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<void>`
|
||||||
|
- `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.
|
||||||
@ -71,7 +71,7 @@ export default function (pi: ExtensionAPI) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
pi.on("turn_start", async (event, ctx) => {
|
pi.on("turn_start", async (_event, ctx) => {
|
||||||
turnCount++;
|
turnCount++;
|
||||||
|
|
||||||
// Update live widget
|
// Update live widget
|
||||||
@ -105,14 +105,5 @@ export default function (pi: ExtensionAPI) {
|
|||||||
return;
|
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();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user