A 1986 aerospace writing standard cuts AI slop by up to 74%. I ported it twice and measured what a linter can actually check — the half that matters least.
Caveman deletes your articles to save tokens. A 1986 aerospace standard forbids dropping them, because dropping them creates ambiguity. Both claim to make writing clearer. Only one was tested in a domain where a misreading kills the reader.
The idea for this post came from Ege Chelebi’s video, The cure for AI slop is a 1986 aircraft manual. He took ASD-STE100 — Simplified Technical English, the controlled language the aerospace industry writes maintenance manuals in — packaged it as an agent skill, and measured it against a baseline, a banned-words list, and Orwell’s six rules across six engineering writing tasks. Violations per hundred words dropped 74% on Claude Sonnet and 50% on GPT-5.5. He’s careful about what that means: n=6, model-specific, and it measures form.
I’d been running the same standard through two very different systems — a personal work vault, then a documentation plugin I maintain — and I measured something else. Not whether the writing got better. How much of the standard a machine can actually check.
The answer, roughly: the half that matters least. That turns out to be the useful finding, because the half a machine can’t check is where the standard earns its keep — and the second port produced six to nine real bugs to prove it.
The Foundation
Concept. A controlled natural language is a restricted subset of a real language with a fixed vocabulary and a fixed grammar. ASD-STE100 approves 875 general words, assigns each one meaning, mandates specific sentence shapes, and caps length at 20 words for procedures, 25 for descriptions. Domain vocabulary is unlimited: the standard never lists a single aircraft part. It defines 22 categories of “technical noun” and 4 of “technical verb,” and anything fitting a category is legal.
Connection. You already use a controlled language. RFC 2119 reserved MUST, SHOULD, and MAY and gave each exactly one meaning, so a spec author can’t hedge by accident. Same mechanism, five words instead of 875.
Why now. Your prose has a second reader. AGENTS.md, CLAUDE.md, skill files, ticket descriptions — that isn’t documentation anymore, it’s input to something that executes. A human who hits an ambiguity asks. An agent fills the gap with a plausible assumption and keeps going, and you find out three steps later.
Reality check. This makes writing checkable. It does not make it correct. Everything below is a variation on that sentence.
Rulesets Beat Adjectives
Two tools were everywhere this spring, and they’re why the STE result lands the way it does.
Caveman strips filler from model output and answers in telegraphic speech — 65–75% token reduction per its author’s tests. Ponytail is a YAGNI ruleset that walks the agent down a six-step ladder before it writes anything: does this need to exist, does the stdlib do it, does the platform do it, is it already a dependency, is it one line, and only then the minimum that works.
Both do the same correct thing: they replaced an adjective with a ruleset. “Be concise” and “don’t over-engineer” are instructions models nod at and ignore, because the target is undefined. A decision ladder isn’t. Same lesson we all learned the hard way about context — specificity is the whole game.
Neither targets ambiguity in prose. Caveman targets token count; Ponytail targets lines of code. A ruleset aimed specifically at being misread has existed since 1986, written for a non-native-English mechanic holding a wrench at 3 a.m., where a misreading costs more than a wasted turn.
Which produces a direct collision. Caveman drops articles because they cost tokens. STE rule 4.5 says do not drop articles or demonstratives; 4.2 says do not omit words at all. Both tools claim clarity and issue opposite instructions.
My port had to resolve it, because a Kanban line is deliberately telegraphic and I wasn’t giving that up. The resolution generalizes: terse is safe when the format supplies structurally what the sentence omits. A line shaped #tag Owner: Task @{date} carries the subject in the Owner slot, so the missing subject isn’t missing. Keep the terse line, require every slot filled. That’s a stricter reading of the rule than writing it out longhand — and it’s the check Caveman doesn’t run, because it counts tokens, not referents.
Port One: What Actually Transferred
I ran this in two gates. Gate one produced a distillation — all 61 items marked adopt, adapt, or reject, each with its reasoning. Gate two designed the standard from that record. It felt like overhead and wasn’t: three times later a verdict came into question and the reasoning was already written down. Skip gate one and you keep the rules but lose the why, which is the only thing that helps when a rule starts causing friction six weeks later.
Three things transferred better than expected.
Control the general vocabulary; never enumerate the domain. This is what makes the project finishable in an afternoon. I never catalogued our products, vendors, or services — six noun categories and four verb categories legalize them wholesale. What’s left is the small set of general words that create vagueness: a one-page list, not a glossary program.
The word-counting rules are load-bearing, and everyone skips them. The famous part of STE is the length caps. Adopt those alone and they’re unusable in a corpus dense with identifiers and dates. Four unglamorous rules fix it: a number, a date, an abbreviation, an identifier, a quoted title, a proper noun, a hyphenated group, and any parenthetical each count as one word. Publish the policy doc to the wiki before 2026-08-01 is six words, not nine. When you port a rule set, the rule that makes another rule survivable is easy to miss and fatal to miss.
The section I expected to throw away was the best one. Section 7 governs safety instructions — the warnings in an aircraft manual, apparently irrelevant to anything I write. Its required shape is [signal word] + [command or condition] + [consequence if ignored], and that’s exactly what a project blocker should be. The third part is the one always missing:
- Before:
Blockers: waiting on the platform team. - After:
BLOCKER: Get the platform team's sign-off on the gateway policy before 2026-08-01. Without it, the tiering requirement is unenforceable.
Writing the consequence isn’t a formatting exercise. It repeatedly changed what the item meant. One flag reading “this touches a critical path” became, once I was forced to finish the sentence, “this re-creates the exact dependency today’s decision removed, and it fails silently.” Same fact, different urgency, and the second version is the true one.
The single highest-value rule is the ban on phrasal verbs — reach out to, look into, circle back, spin up, loop in. They’re vague in one specific, damaging way: they hide the completion test. “Reach out to the vendor contact” — is a sent, unanswered email done? Neither I nor the agent can say, so neither of us can agree the task is finished. “Send an email to the vendor contact” is unambiguous. My own Kanban format doc used the bad form as its documented example.
The Measurement That Changed My Mind
Then the question that actually mattered: can a script enforce this?
Cheapest possible experiment. Two agents, byte-identical neutral prompts, one README, read-only, structured output — RULE_ID | line | text | reason. Then diff the finding sets.
| Result | |
|---|---|
| Agent 1 findings | 116 |
| Agent 2 findings | 104 |
| Same rule at the same line | 89 |
| Union | 131 |
| Agreement | 68% |
68% reads like a mediocre standard. It isn’t — the disagreement wasn’t noise. It split almost perfectly along one axis:
| Rule type | Agreement | Nature |
|---|---|---|
| Punctuation, tense, verb position, sentence length | 100% | Syntactic. Visible in the string |
| Named agent, active voice, phrasal verbs | 67–93% | Mostly syntactic, some judgment |
| One name per thing, abstraction, completion tests | 14–40% | Semantic. Requires domain knowledge |
The rule I had personally ranked most important scored 17%. “One name per thing” — one agent found 11 violations, the other 3, same file. That’s not a defect in the rule. Deciding whether “the central gateway” and the product’s actual name refer to one thing requires knowing the domain, and no regex will ever know it.
Two conclusions, and the second one is the post:
- A linter certifies the mechanical half of a standard and nothing more. Never present a clean lint as a clean document.
- Automatability is inversely correlated with value. The rules that catch real ambiguity are precisely the ones a script can’t check. Build your standard to be lintable and you will build the wrong standard.
The Standard Was Wrong About Itself
The same tests found something more uncomfortable than the numbers. Six defects were the standard contradicting itself: a profile whose own example used the mood that same page forbids, two files giving different sentence counts for the same section, a rule with no ID in a document requiring stable IDs.
Every one was in an example, not a rule. Examples are where authors relax, and a wrong example teaches louder than a right rule. I wrote all six within hours and found zero by re-reading.
Port Two: When the Style Pass Found Real Bugs
Months later I ported the same distillation into a documentation plugin — a different context, since a plugin’s rules get copied into repos it doesn’t control. The 434-page source PDF was never reopened. That’s the strongest argument for the two-gate method: the distillation is the durable artifact; the spec is merely its input.
Two things the new context changed.
The 17% rule became checkable. One-name-per-thing scored 17% in prose because nothing in that corpus knew which terms co-refer. A code repo does — identifiers, service names, and CLI commands are a name registry. “Use the approved term” becomes “use the name the code uses,” checkable by grep against ground truth. The low agreement was a property of corpora without a registry, not of the rule.
Measurement bands had to become a shipping contract. You can’t ship three agreement percentages. They collapsed into two tiers — mechanical, which may be asserted, and judgment, which is flagged for confirmation and never auto-fixed — plus a downgrade clause: any finding whose confirmation needs domain knowledge reports at judgment tier regardless of its rule’s default. One sentence travels as protocol: a clean style pass certifies the mechanical tier only.
Then the part I’d like to claim I avoided. I ran this port with the six-self-contradictions story consciously in mind, actively trying not to repeat it. One clean-context agent, neutral prompt, 97,291 tokens, about nine minutes: 64 findings across nine policy files, 13 of them in the new rules file itself, written hours earlier. A rule tagged mechanical whose test is plainly judgment. Three different names for one scope, inside the file that defines the one-name-per-thing rule.
Authoring-time awareness of a failure mode is worth approximately nothing. Schedule the clean-context read; don’t budget care.
Then the result that justifies the whole exercise. Once the standard governed the plugin’s own skills and instruction files — not its documentation, its instructions — and I ran it against real repositories, six to nine failures surfaced that had been happening all along. Not style findings. Real, wrong behavior, previously invisible.
The mechanism is straightforward once you see it. The bugs were living in the gaps: an instruction that didn’t quite say which artifact, a step whose completion test was implied. The agent had been filling those gaps with reasonable assumptions and proceeding — and reasonable assumptions are indistinguishable from correct ones until they aren’t. Close the gaps and the agent stops guessing, and the places where it had been guessing surface as the failures they always were.
Rewriting agent instructions to a controlled standard is a bug-finding pass. The bugs it finds are exactly the semantic ones no linter sees — the same claim the 17% number makes, arriving from the opposite direction.
The effect extends past files. Apply the rules to what the agent writes back — name the action and its completion test, name the actor, use the code’s names, state the consequence, resolve every referent — and it becomes markedly clearer what it’s telling you, in a form you can act on. That block ships with an explicit carve-out, and it matters: the rules ban vague references, not honest uncertainty. An agent that says “I’m not sure” is giving you information. An agent that says “the config was updated” is hiding which one and by whom.
Where This Doesn’t Belong
Documentation is squarely in scope — consistency and predictability are what it wants anyway. Two things aren’t, and the boundary is measurable.
I applied the rules to a personal daily note. The rewrite came out 22% longer and read as a status report written about its author. Not yours to own, but ask them so you're not caught flat-footed became They own the renewal. You need the outcome. The instruction survived; the political read didn’t. A rewrite that gets longer and changes register is telling you the rules are fighting the artifact — a cheap, mechanical diagnostic for wrong scope. Notes where the hedging is the information stay exempt, as does anything creative.
Three costs to price in:
- Every reserved term strands its general class. Reserving a word as a product name leaves no legal way to use it as an ordinary adjective. Keep the banned list tiny; grow it only on evidence of a real misreading.
- A style pass must stop at a code fence. Mine surfaced genuine bugs inside command examples, and correcting syntax there changes what the thing does, not how it reads. Report; don’t quietly repair.
- A rule that never fires is ambiguous data. One of mine never fired at all, along with 11 of 13 word-swap rows. Either the scope is wrong or the corpus is healthy, and you can’t tell which without looking.
Next Step
Don’t start by adopting STE. Start by asking what other mature standard already solved the problem you’re hitting with agents — the answer is usually yes, and usually older than you’d guess.
Two questions to run against any candidate:
- What does it say, versus how is it built? Seventy percent of ASD-STE100 is a dictionary of aerospace verbs I had no use for. Its architecture — a tiny closed set of controlled general words plus an unlimited open set defined by category — was the most valuable idea in the document. The second answer ports when the first doesn’t. Ask both, separately.
- Does this domain punish ambiguity with something worse than embarrassment? That’s the filter. Standards written where a misreading is merely awkward never got stress-tested.
A shortlist, all battle-tested, none written with AI in mind: RFC 2119, a controlled vocabulary you already have and probably misuse. ICAO standard phraseology and its readback/hearback protocol — a closed loop that confirms the receiver’s understanding rather than the sender’s transmission, which is the exact failure mode of a confident agent. IMO’s Standard Marine Communication Phrases, a fixed phrase set for crews with no shared native language. SBAR — Situation, Background, Assessment, Recommendation — a clinical handoff format that spread from submarines to hospitals precisely because it forces the recommendation to be stated. IEC/IEEE 82079-1, the international standard for writing instructions for use.
Pick one. Distil it before you adopt it, and write the reasoning next to each verdict. That record, not the rules, is what survives to the next port.
Go Deeper
- The cure for AI slop is a 1986 aircraft manual — Ege Chelebi’s experiment, plus the full kit with his linter and before/after samples
- ASD-STE100 Issue 9 (2025-01-15) — the source standard. ASD provides a free official copy on request; the text itself is copyrighted, so derive from it rather than quoting it in anything you ship
- Caveman and Ponytail — the ruleset-over-adjective pattern applied to tokens and to code
One question I still don’t have a good answer to: if a clean style pass can only ever certify the mechanical tier, what’s the honest way to report the other half — to a teammate, or in CI — without either overclaiming or burying it? Tell me what’s worked for you.
