diff --git a/.opencode/command/ponytail-audit.md b/.opencode/command/ponytail-audit.md new file mode 100644 index 0000000..4722747 --- /dev/null +++ b/.opencode/command/ponytail-audit.md @@ -0,0 +1,5 @@ +--- +description: Audit the whole repo for over-engineering, what can be deleted +--- + +Audit the entire repository for over-engineering only, not correctness. Scan the whole tree, not a diff. One line per finding, ranked biggest cut first: . . [path]. Tags: delete (dead code/speculative feature), stdlib (reinvented standard library), native (dependency doing what the platform does), yagni (abstraction with one implementation), shrink (same logic, fewer lines). End with the net lines and dependencies removable. If nothing to cut: 'Lean already. Ship.' diff --git a/README.md b/README.md index cf91b8e..9334ea2 100644 --- a/README.md +++ b/README.md @@ -99,14 +99,15 @@ Run OpenCode from a checkout of this repo (the plugin reuses its `hooks/` and `s { "plugin": ["./.opencode/plugins/ponytail.mjs"] } ``` -Injects the ruleset every turn at the active level; adds `/ponytail` and `/ponytail-review`. OpenCode also auto-loads this repo's `AGENTS.md`, so the rules hold even without the plugin. The plugin adds the `lite/full/ultra/off` levels. +Injects the ruleset every turn at the active level; adds `/ponytail`, `/ponytail-review`, and `/ponytail-audit`. OpenCode also auto-loads this repo's `AGENTS.md`, so the rules hold even without the plugin. The plugin adds the `lite/full/ultra/off` levels. 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 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 ultra` exists for when the codebase has wronged you personally. `/ponytail-help` explains the rest. -In Codex, invoke the skills as `@ponytail`, `@ponytail-review`, and -`@ponytail-help`. Startup and mode-change text shows the current mode. +In Codex, invoke the skills as `@ponytail`, `@ponytail-review`, +`@ponytail-audit`, 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-audit.toml b/commands/ponytail-audit.toml new file mode 100644 index 0000000..4ebc3b2 --- /dev/null +++ b/commands/ponytail-audit.toml @@ -0,0 +1,2 @@ +description = "Audit the whole repo for over-engineering, what can be deleted" +prompt = "Audit the entire repository for over-engineering only, not correctness. Scan the whole tree, not a diff. One line per finding, ranked biggest cut first: . . [path]. Tags: delete (dead code/speculative feature), stdlib (reinvented standard library), native (dependency doing what the platform does), yagni (abstraction with one implementation), shrink (same logic, fewer lines). End with the net lines and dependencies removable. If nothing to cut: 'Lean already. Ship.'" diff --git a/docs/agent-portability.md b/docs/agent-portability.md index 9b71700..6db5d17 100644 --- a/docs/agent-portability.md +++ b/docs/agent-portability.md @@ -28,5 +28,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-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 b75cc65..1899026 100644 --- a/pi-extension/index.js +++ b/pi-extension/index.js @@ -114,6 +114,11 @@ export default function ponytailExtension(pi) { handler: (_args, ctx) => sendAlias("/skill:ponytail-review", "", ctx), }); + pi.registerCommand("ponytail-audit", { + description: "Run /skill:ponytail-audit", + handler: (_args, ctx) => sendAlias("/skill:ponytail-audit", "", 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 76cf15d..6123c5f 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-help", "ponytail-review"]); + assert.deepEqual([...commands.keys()].sort(), ["ponytail", "ponytail-audit", "ponytail-help", "ponytail-review"]); }); test("/ponytail updates session mode and injects instructions", async () => withTempConfig(async () => { @@ -98,10 +98,12 @@ test("skill alias commands delegate to Pi skill commands", async () => { const ctx = createCommandContext(); await commands.get("ponytail-review").handler("", ctx); + await commands.get("ponytail-audit").handler("", ctx); await commands.get("ponytail-help").handler("", ctx); assert.deepEqual(sentUserMessages.map((entry) => entry.text), [ "/skill:ponytail-review", + "/skill:ponytail-audit", "/skill:ponytail-help", ]); }); diff --git a/skills/ponytail-audit/SKILL.md b/skills/ponytail-audit/SKILL.md new file mode 100644 index 0000000..9c803ee --- /dev/null +++ b/skills/ponytail-audit/SKILL.md @@ -0,0 +1,40 @@ +--- +name: ponytail-audit +description: > + Whole-repo audit for over-engineering. Like ponytail-review, but scans the + entire codebase instead of a diff: a ranked list of what to delete, simplify, + or replace with stdlib/native equivalents. Use when the user says "audit this + codebase", "audit for over-engineering", "what can I delete from this repo", + "find bloat", "ponytail-audit", or "/ponytail-audit". One-shot report, does + not apply fixes. +--- + +ponytail-review, repo-wide. Scan the whole tree instead of a diff. Rank +findings biggest cut first. + +## Tags + +Same as ponytail-review: + +- `delete:` dead code, unused flexibility, speculative feature. Replacement: nothing. +- `stdlib:` hand-rolled thing the standard library ships. Name the function. +- `native:` dependency or code doing what the platform already does. Name the feature. +- `yagni:` abstraction with one implementation, config nobody sets, layer with one caller. +- `shrink:` same logic, fewer lines. Show the shorter form. + +## Hunt + +Deps the stdlib or platform already ships, single-implementation interfaces, +factories with one product, wrappers that only delegate, files exporting one +thing, dead flags and config, hand-rolled stdlib. + +## Output + +One line per finding, ranked: ` . . [path]`. +End with `net: - lines, - deps possible.` Nothing to cut: `Lean already. Ship.` + +## Boundaries + +Complexity only, correctness bugs, security holes, and performance go to a +normal review pass. Lists findings, applies nothing. One-shot. +"stop ponytail-audit" or "normal mode" to revert.