Teardownspublic

ponytail

Four lines shortlisted out of a rule set with 92,000 stars; one held up. The more valuable finding came from my own rules.

The headline number collapsed, and one line got adopted. This repository’s face is “−54% code”; recomputed under the definition its own report declares, it’s −35.4% — and there is no correctness gate to begin with, since “did it write any code at all” is what counts as correct. Of four shortlisted lines, the only one whose evidence held is “grep every call site,” and even that went into a single agent rather than globally. What this investigation actually found wasn’t a problem with their rule set but three contradictions inside mine.

the product is this one ladder — you stop at the first rung that catches 1 need to exist at all? 2 already in this codebase? 3 standard library? 4 platform native? 5 installed dependency? 6 does one line do it? 7 minimal code catch on any of these six and it ends there — no code gets written the ladder runs after you understand the problem · laziness means writing less answer, not doing less reading — its own words
Not a code tool but prompt distribution infrastructure. What it sells is this one text; everything else is plumbing that pushes it into twenty hosts.

What it actually sells

A prompt rule set that keeps “don’t build it yet” resident in an agent’s context. It doesn’t inspect or modify code — the product is one 120-line text file containing the ladder above, and the rest of the repository is plumbing that installs that text into twenty agent hosts and keeps it current.

92,133 stars, 5,069 forks, 9,166 weekly npm downloads. Seven weeks old.

Two conditions attached to the ladder separate this from plain “build less.”

  • The ladder runs after you understand the problem — reverse that order and it’s just carelessness
  • Laziness means writing less answer, not doing less reading — bug fixes are nailed down as “root cause, not symptom; grep every call site”

There’s also a do-not-cut list: trust-boundary input validation, data-loss error handling, security, accessibility, hardware calibration knobs. It marks the places where minimalism turns dangerous itself.

Two things that looked different up close

The rule text isn’t in one place. Besides the file called canonical, rules are spread across a separate conventions file (which more than half of the twenty hosts actually load), a JS fallback copy, and five auxiliary skills. Three or four locations. Narrowed to one host the canonical file holds, but across the repository it doesn’t match the “one page” impression.

The intensity levels barely differ. Three tiers are sold — lite, full, ultra — and the actual injected text is 5,202 / 5,229 / 5,267 characters. A 65-character spread, 1.2%. That’s rhetoric, not content. Diffing full against ultra at runtime gives three lines out of a hundred, and none of those three says anything about handling fewer edge cases.

The headline number swapped definitions

“−54% code” is this repository’s face. Both the report and the README declare that figure to be a per-task average.

Computing it from the published twelve-task table, the per-task average is −35.4%. The −54% is a total weighted by baseline line count. The definition declared and the arithmetic performed are not the same.

And of that −54%, 17.7 points come from two tasks — a date picker and a colour picker. Drop those two and it’s −36.5%; take only the six backend tasks and it’s −22.2%.

But there’s a more fundamental problem underneath. There is no correctness gate.

sc = {"correct": 1 if stats.get("total_loc", 0) > 0 else 0, "safe": 1, "reason": "git-diff"}

correct means “did it write any code at all” and safe is a hardcoded constant 1. Nothing anywhere in this benchmark shows that a 23-line date picker actually satisfied the ticket.

The author knows about the hole. There’s a separate script for it, with a comment calling “you wrote less because you did less” the most credible attack on the headline number. It has never been reported.

The instrument is flawed too. Counting code volume requires excluding tests, and the detector recognises only Python conventions and certain folder names — so frontend *.test.tsx files get counted as source. The harness declares that “tests are counted separately, never as bloat”, and that fails in exactly one language — which happens to be the language of all six of its biggest wins.

The honesty is real; what’s tilted all tilts one way

It’s easy to dismiss this repository, and that would be wrong. The author self-reported a contamination bug and superseded the entire earlier result set, and published the unflattering data — that the effect converges on backend work, that one model gets slower, that another costs 38.7% more. There’s even a gate that refuses to spend API budget at all if the instrument fails its own self-test. That is well above the average for this genre.

So what collapses isn’t the honesty. It’s that the aggregation method, the instrument choice, the task selection and the unreported items all lean the same direction. One of those is a mistake; four in the same direction is a structure that produces a result.

Task selection especially. Rung four of the ladder literally names a native date input as its example, and the top headline task is “add a date picker.” What’s being measured isn’t general minimalism — it’s the recall rate of that one sentence. And of twelve tasks, the number where minimalism costs you something — accessibility requirements, hardware calibration — is zero.

The safety tier is the same story. The README says seven safety tasks and the reproduction command lists seven, and the report presents six. The missing one happens to be the task the author built to answer a critic.

The raw data isn’t published. The re-scoring reproduction path the report advertises is not executable by a third party.

⇒ What survives in defensible form is roughly this: on one small model, on frontend tickets replaceable by a native HTML input, unverified code volume drops a lot.

The one line that stayed, and why it survived

What got adopted is one line: “grep every call site.”

The repo’s own benchmark has this task. Two functions share an internal debit routine, the bug report names only one of them, and the scorer checks for an overdraft in the one the report never mentions. Fix only what the report names and you fail.

the same instruction, reworded — does it find the call site the report omits? no rule 1 / 6 as prose 0 / 3 — “trace the flow all the way through” as an instruction 6 / 6 “grep every call site” — same meaning, different shape, and it went from none to all
This line survived because there was a control group. What transferred was the shape of the sentence, not its meaning.

The control group is what decides it. The same meaning written as flowing prose — “trace the flow all the way through” — scored zero in three. Only the imperative form moved it to six out of six.

Why is this the only survivor on this page? Everything knocked down above is an aggregation problem on the code-volume axis, and this sits on the quality axis, where that problem doesn’t apply. And two reviews arguing opposite conclusions converged independently on this one item.

Its limits go on the record too: the repo’s own benchmark, n=6, a single task, raw data unpublished. It doesn’t transfer to small models — that’s a ceiling region where the baseline fails as well.

Why the other three were dropped

  • Rung 2 (already here)the repo’s own benchmark failed to demonstrate any behavioural value. Baseline and ponytail both reused the helper, and the duplication failure didn’t reproduce
  • Rung 4 (platform native) — the effect concentrates on replacing HTML form controls. My work is game-engine C#, Python tests and pipeline JS, where it doesn’t apply
  • The one-liner reflex — my own rules already cover it (“if you write 200 lines and it could be 50, rewrite it”)

What the investigation found was my own rule set, not theirs

Working through a wholesale adoption, I counted the places it collides with my rules. Three. But something bigger turned up — my rule set already contradicts itself in three places, with no help from ponytail.

Axis One side The other
Configurability no configurability that wasn’t requested tuning knobs go in config keys even when equal to the code default
Error handling no error handling for impossible scenarios always, comprehensively, at every level
Speculation nothing speculative unit, integration and E2E all required, 80% coverage

All three are permanently loaded, and nowhere is it defined which one wins. So every turn, the model decides for itself.

Settling those three comes before adding another clause. And it hasn’t been done — the homework this investigation created is bigger than the one line it brought home.

So: not globally, but into a single agent

Rather than guessing how far a global rule reaches, I measured it. The result was bad: global instructions survive into child processes even when the system prompt is replaced wholesale. Put this in globally and it reaches test-case generation and QA automation without exception, and there is no way to switch it off.

Over there, “build less” is the coverage hole. In particular the line “never stop for something you could answer with a default” directly inverts my own rule, which is to stop and mark it “needs confirmation” when the spec doesn’t say.

So it narrowed in three steps. Global ❌ → project ❌ → one agent, the one that writes game code ✅. Project scope failed because it doesn’t isolate — the QA agents in that same project get caught with it. The content-authoring agent was excluded too: over there volume is the value, and on the verification side the harness and fixtures are the asset.

Even in that one agent, two lines were dropped. “As few files as possible” runs straight into my rule to split files small, and “never stop” runs into the first rule I have, which is to stop when something is unclear. A collision that survives narrowing the target isn’t fixed by narrowing the target.

⚠ I got one measurement wrong along the way. The first probe reported that global rules don’t propagate to children — a false negative caused by asking two things in one question. A same-question control corrected it. Probes ask one thing at a time.