From d9e1480c74986fcc7ff3c18e1773f5364e17deed Mon Sep 17 00:00:00 2001 From: DietrichGebert Date: Mon, 15 Jun 2026 02:32:45 +0200 Subject: [PATCH] feat: add ponytail-debt skill (#40) Closes the last gap from the field review: deferral creep. /ponytail-debt greps the repo for `ponytail:` comment markers and prints a ledger (file:line, what was simplified, ceiling, upgrade trigger), flagging any marker with no trigger as the rot risk. One-shot, reports only. Full parity like ponytail-audit: skill + commands/.toml + .opencode/.md + pi registerCommand (+ test) + agent-portability + README. Verified: tests 32/32 (pi command list updated), rule check green, the scan finds the repo's real markers, and a live end-to-end run produced a correct ledger (2 markers, 1 no-trigger, prose/examples excluded). Co-authored-by: Claude Opus 4.8 (1M context) --- .opencode/command/ponytail-debt.md | 5 ++++ README.md | 6 ++-- commands/ponytail-debt.toml | 2 ++ docs/agent-portability.md | 1 + pi-extension/index.js | 5 ++++ pi-extension/test/extension.test.js | 4 ++- skills/ponytail-debt/SKILL.md | 44 +++++++++++++++++++++++++++++ 7 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 .opencode/command/ponytail-debt.md create mode 100644 commands/ponytail-debt.toml create mode 100644 skills/ponytail-debt/SKILL.md diff --git a/.opencode/command/ponytail-debt.md b/.opencode/command/ponytail-debt.md new file mode 100644 index 0000000..8509d12 --- /dev/null +++ b/.opencode/command/ponytail-debt.md @@ -0,0 +1,5 @@ +--- +description: Harvest ponytail: comments into a tracked debt ledger +--- + +Harvest every `ponytail:` comment in this repository into a debt ledger so deferrals do not rot into 'later means never'. Grep the whole tree for comment markers (grep -rnE '(#|//) ?ponytail:' ., skipping node_modules/.git/build output). One row per marker, grouped by file: :. ceiling: . upgrade: . Tag any marker that names no upgrade path or trigger as no-trigger, those rot silently. End with the count of markers and how many lack a trigger. If none: 'No ponytail: debt. Clean ledger.' Report only, change nothing. diff --git a/README.md b/README.md index 76dfe2a..32daff9 100644 --- a/README.md +++ b/README.md @@ -111,11 +111,11 @@ Loads the ruleset as always-on context every session and registers `/ponytail` a That was it. He'd be proud. He won't say it. -Active every session. `/ponytail-review` finds what to delete in your diff, `/ponytail-audit` does the same for the whole repo. `/ponytail ultra` exists for when the codebase has wronged you personally. `/ponytail-help` explains the rest. +Active every session. `/ponytail-review` finds what to delete in your diff, `/ponytail-audit` does the same for the whole repo, `/ponytail-debt` harvests the `ponytail:` shortcuts you've deferred so they don't rot. `/ponytail ultra` exists for when the codebase has wronged you personally. `/ponytail-help` explains the rest. In Codex, invoke the skills as `@ponytail`, `@ponytail-review`, -`@ponytail-audit`, and `@ponytail-help`. Startup and mode-change text shows the -current mode. +`@ponytail-audit`, `@ponytail-debt`, and `@ponytail-help`. Startup and +mode-change text shows the current mode. Cursor, Windsurf, Cline, Copilot, Aider, Kiro: copy the matching rules file from this repo ([`.cursor/rules/`](.cursor/rules/), [`.windsurf/rules/`](.windsurf/rules/), [`.clinerules/`](.clinerules/), [`.github/copilot-instructions.md`](.github/copilot-instructions.md), [`AGENTS.md`](AGENTS.md), [`.kiro/steering/`](.kiro/steering/)). diff --git a/commands/ponytail-debt.toml b/commands/ponytail-debt.toml new file mode 100644 index 0000000..fe41f09 --- /dev/null +++ b/commands/ponytail-debt.toml @@ -0,0 +1,2 @@ +description = "Harvest ponytail: comments into a tracked debt ledger" +prompt = "Harvest every `ponytail:` comment in this repository into a debt ledger so deferrals do not rot into 'later means never'. Grep the whole tree for comment markers (grep -rnE '(#|//) ?ponytail:' ., skipping node_modules/.git/build output). One row per marker, grouped by file: :. ceiling: . upgrade: . Tag any marker that names no upgrade path or trigger as no-trigger, those rot silently. End with the count of markers and how many lack a trigger. If none: 'No ponytail: debt. Clean ledger.' Report only, change nothing." diff --git a/docs/agent-portability.md b/docs/agent-portability.md index 82606c5..989d28e 100644 --- a/docs/agent-portability.md +++ b/docs/agent-portability.md @@ -33,5 +33,6 @@ instructions, keep its copied rule text aligned with `AGENTS.md`. - `skills/ponytail/SKILL.md`: lazy senior dev mode - `skills/ponytail-review/SKILL.md`: over-engineering review - `skills/ponytail-audit/SKILL.md`: whole-repo over-engineering audit +- `skills/ponytail-debt/SKILL.md`: harvest `ponytail:` shortcuts into a tracked ledger - `skills/ponytail-help/SKILL.md`: quick reference - `AGENTS.md`: compact always-on instruction set for agents without skill support diff --git a/pi-extension/index.js b/pi-extension/index.js index 1899026..5d74798 100644 --- a/pi-extension/index.js +++ b/pi-extension/index.js @@ -119,6 +119,11 @@ export default function ponytailExtension(pi) { handler: (_args, ctx) => sendAlias("/skill:ponytail-audit", "", ctx), }); + pi.registerCommand("ponytail-debt", { + description: "Run /skill:ponytail-debt", + handler: (_args, ctx) => sendAlias("/skill:ponytail-debt", "", ctx), + }); + pi.registerCommand("ponytail-help", { description: "Run /skill:ponytail-help", handler: (_args, ctx) => sendAlias("/skill:ponytail-help", "", ctx), diff --git a/pi-extension/test/extension.test.js b/pi-extension/test/extension.test.js index 6123c5f..1c5f7c0 100644 --- a/pi-extension/test/extension.test.js +++ b/pi-extension/test/extension.test.js @@ -57,7 +57,7 @@ function withTempConfig(fn) { test("extension registers Ponytail commands", () => { const { commands } = createPiHarness(); - assert.deepEqual([...commands.keys()].sort(), ["ponytail", "ponytail-audit", "ponytail-help", "ponytail-review"]); + assert.deepEqual([...commands.keys()].sort(), ["ponytail", "ponytail-audit", "ponytail-debt", "ponytail-help", "ponytail-review"]); }); test("/ponytail updates session mode and injects instructions", async () => withTempConfig(async () => { @@ -99,11 +99,13 @@ test("skill alias commands delegate to Pi skill commands", async () => { await commands.get("ponytail-review").handler("", ctx); await commands.get("ponytail-audit").handler("", ctx); + await commands.get("ponytail-debt").handler("", ctx); await commands.get("ponytail-help").handler("", ctx); assert.deepEqual(sentUserMessages.map((entry) => entry.text), [ "/skill:ponytail-review", "/skill:ponytail-audit", + "/skill:ponytail-debt", "/skill:ponytail-help", ]); }); diff --git a/skills/ponytail-debt/SKILL.md b/skills/ponytail-debt/SKILL.md new file mode 100644 index 0000000..ba672c8 --- /dev/null +++ b/skills/ponytail-debt/SKILL.md @@ -0,0 +1,44 @@ +--- +name: ponytail-debt +description: > + Harvest every `ponytail:` comment in the codebase into a debt ledger, so the + deliberate shortcuts and deferrals ponytail leaves behind get tracked instead + of rotting into "later means never". Use when the user says "ponytail debt", + "/ponytail-debt", "what did ponytail defer", "list the shortcuts", "ponytail + ledger", or "what did we mark to do later". One-shot report, changes nothing. +--- + +Every deliberate ponytail shortcut is marked with a `ponytail:` comment naming +its ceiling and upgrade path. This collects them into one ledger so a deferral +can't quietly become permanent. + +## Scan + +Grep the repo for comment markers, skipping `node_modules`, `.git`, and build +output: + +`grep -rnE '(#|//) ?ponytail:' .` (add other comment prefixes if your stack uses them) + +Each hit is one ledger row. The comment prefix keeps prose that merely mentions +the convention out of the ledger. + +## Output + +One row per marker, grouped by file: + +`:. ceiling: . upgrade: .` + +The convention is `ponytail: , `, so pull the ceiling +and the trigger straight from the comment. Want an owner per row too? add +`git blame -L,`. + +Flag the rot risk: any `ponytail:` comment that names no upgrade path or +trigger gets a `no-trigger` tag, those are the ones that silently rot. + +End with ` markers, with no trigger.` Nothing found: `No ponytail: debt. Clean ledger.` + +## Boundaries + +Reads and reports only, changes nothing. To persist it, ask and it writes the +ledger to a file (e.g. `PONYTAIL-DEBT.md`). One-shot. "stop ponytail-debt" or +"normal mode" to revert.