unmistakable
Rewrite English so an AI agent cannot misread it. A skill that rewrites, and a linter that checks.
/plugin install unmistakable@gago-plugins
An agent cannot ask what you meant
A tool description, an error message or a system prompt has one reader and no author to call. Every word with two meanings, and every sentence with two parses, is a coin toss. The ASD-STE100 rules were built to remove both, so a maintenance technician could not misread an instruction. An agent is in the same position.
Before
An error may have occurred while processing your request due to a possible mismatch in the expected data format, which could be caused by an outdated client version.
After
Your request may have failed. The cause may be a data format that does not match what the server expects. An outdated client can cause this mismatch. Check your client version.
The rewrite keeps the hedges. “May have failed” stays “may have failed”. Confidence is content, and a rewrite that sounds surer than its author is wrong.
How it works
Three steps. The linter is TypeScript that Node runs as it is. Nothing to install but the plugin, and Node 22.18 or later.
- Ask in plain words. “Rewrite this tool description so an agent cannot misread it.” The skill picks strict mode for procedures and error messages, and a lighter mode for READMEs and PR descriptions.
- It rewrites without losing a fact. Each flagged sentence is fixed one rule at a time. A condition, a number or a scope qualifier is never dropped to make a sentence shorter.
- The linter checks.
ste-lintruns on the result and names each remaining problem with the number of the rule behind it.
A linter you can run anywhere
No dependency and no binary: about 60 KB of readable TypeScript. Exit code 1 when hard findings pass the baseline. Good for CI.
$ echo "We spin up the box; it isn't running." | node scripts/ste-lint.ts <stdin>:1:4 phrasal-verb (STE-9.3): Soft phrasal verb. Use the single plain verb ... [spin up] <stdin>:1:19 semicolon (STE-8.1): STE bans the semicolon (Rule 8.1). Split into separate sentences. [;] <stdin>:1:24 contraction (STE-4.2): Contraction. Write the full words ... [isn't]
| Profile | Use it for |
|---|---|
agent (default) | Text that an agent reads. Every check. |
descriptive | Explanations. The checks that follow a numbered STE rule, 25 words per sentence. |
procedure | Steps and instructions. 20 words per sentence. |
upstream | The original ste-lint.py output, byte for byte. |
What it checks
Structure, not meaning. It has no part-of-speech tagger, and it never flags a hedge.
Semicolons, phrasal verbs, nominalizations, passive voice, compound tenses, one term per action, sentence length, paragraph length, contractions, -ing forms, multi-word nouns, WARNING and CAUTION blocks, dropped articles, British spellings, marketing adjectives and dangling conjunctions in lists. Each finding carries its rule number (STE-6.6). A check that is not an STE rule has the prefix X-.
Credit, and what this is not
The skill and the first linter are by Dustin Yuchen Teng: danyuchn/asd-ste100-skill, MIT. unmistakable packages them, fixes the statements that an audit against Issue 9 found wrong, ports the linter to TypeScript, and adds profiles and checks. UPSTREAM.md lists every change.
ASD-STE100 is a copyright and a trademark of ASD, Brussels. This project is not made, checked or endorsed by ASD, and it does not claim that a text complies with the standard. It ships no part of the dictionary and none of the text of the rules. Get the standard, free, from asd-ste100.org.