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) <noreply@anthropic.com>
This commit is contained in:
DietrichGebert
2026-06-15 02:32:45 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent f3da910b4f
commit d9e1480c74
7 changed files with 63 additions and 4 deletions
+5
View File
@@ -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: <file>:<line> — <what was simplified>. ceiling: <the limit named in the comment>. upgrade: <the trigger to revisit>. 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.
+3 -3
View File
@@ -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. 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`, In Codex, invoke the skills as `@ponytail`, `@ponytail-review`,
`@ponytail-audit`, and `@ponytail-help`. Startup and mode-change text shows the `@ponytail-audit`, `@ponytail-debt`, and `@ponytail-help`. Startup and
current mode. 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/)). 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/)).
+2
View File
@@ -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: <file>:<line> — <what was simplified>. ceiling: <the limit named in the comment>. upgrade: <the trigger to revisit>. 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."
+1
View File
@@ -33,5 +33,6 @@ instructions, keep its copied rule text aligned with `AGENTS.md`.
- `skills/ponytail/SKILL.md`: lazy senior dev mode - `skills/ponytail/SKILL.md`: lazy senior dev mode
- `skills/ponytail-review/SKILL.md`: over-engineering review - `skills/ponytail-review/SKILL.md`: over-engineering review
- `skills/ponytail-audit/SKILL.md`: whole-repo over-engineering audit - `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 - `skills/ponytail-help/SKILL.md`: quick reference
- `AGENTS.md`: compact always-on instruction set for agents without skill support - `AGENTS.md`: compact always-on instruction set for agents without skill support
+5
View File
@@ -119,6 +119,11 @@ export default function ponytailExtension(pi) {
handler: (_args, ctx) => sendAlias("/skill:ponytail-audit", "", ctx), 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", { pi.registerCommand("ponytail-help", {
description: "Run /skill:ponytail-help", description: "Run /skill:ponytail-help",
handler: (_args, ctx) => sendAlias("/skill:ponytail-help", "", ctx), handler: (_args, ctx) => sendAlias("/skill:ponytail-help", "", ctx),
+3 -1
View File
@@ -57,7 +57,7 @@ function withTempConfig(fn) {
test("extension registers Ponytail commands", () => { test("extension registers Ponytail commands", () => {
const { commands } = createPiHarness(); 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 () => { 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-review").handler("", ctx);
await commands.get("ponytail-audit").handler("", ctx); await commands.get("ponytail-audit").handler("", ctx);
await commands.get("ponytail-debt").handler("", ctx);
await commands.get("ponytail-help").handler("", ctx); await commands.get("ponytail-help").handler("", ctx);
assert.deepEqual(sentUserMessages.map((entry) => entry.text), [ assert.deepEqual(sentUserMessages.map((entry) => entry.text), [
"/skill:ponytail-review", "/skill:ponytail-review",
"/skill:ponytail-audit", "/skill:ponytail-audit",
"/skill:ponytail-debt",
"/skill:ponytail-help", "/skill:ponytail-help",
]); ]);
}); });
+44
View File
@@ -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:
`<file>:<line> — <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit>.`
The convention is `ponytail: <ceiling>, <upgrade path>`, so pull the ceiling
and the trigger straight from the comment. Want an owner per row too? add
`git blame -L<line>,<line>`.
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 `<N> markers, <M> 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.