The standard and language models

Last updated: 2026-09-05Why a model breaks the standard in favour of the style it was trained on, why you should not hand it the full document, and Small GRAIN — twelve laws that fit in a prompt.

The standard and language models

A separate chapter, because it is a separate problem: a standard written against "code with no author" has to be applied to the thing producing that code.

Why a model breaks the standard

A language model picks the most probable continuation. The most probable handler name in the world is handleSubmit. The most probable home for a function with nowhere to live is utils.ts. The most probable comment restates the line below it. The most probable safety net is a try/catch around a pure function.

The standard bans exactly those. Which means it asks the model to walk against its own distribution — on every line, not once. Over a short fragment that works. Over a long one it drifts back: the further from the start of the answer, the closer to the middle of the distribution, to the style the model was trained on.

What the failure looks like

  • Half-compliance. Exported functions get renamed by the dictionary; the callback three lines down is still handleClick. On paper the file was "rewritten to the standard".
  • Invented rules. The model adds rules the standard does not contain: a Service suffix, an I prefix on interfaces, Async in a name. They look plausible because they come from neighbouring conventions.
  • Imitated form. A comment gets a why: tag, and behind the tag is a restatement of the code. The tag is there, the "why" is not: the linter is satisfied, the reader is misled.
  • False confidence. Asked "does this follow the standard?", the model says yes — because it looks like it does, not because it checked.
  • Attention spent on commas. The longer the document in context, the more budget goes to obeying it and the less to the actual task. The code ends up perfectly named and wrong.

Do not hand a model the full standard

A direct recommendation: do not wire the full standard into an assistant. Not because the model is not good enough, but because the full document and the model solve different problems. The standard is written for a human who reads it once and carries it for years, and for a linter that checks literally and never tires. A model does neither: it holds the rules for exactly as long as they fit in active attention, and the longer the answer, the worse that gets.

The full document in a prompt does not buy stricter code — it buys more confident violations: the model cites the rules, follows half of them, and defends the result. That costs more than letting it write ordinary code the linter will correct.

Small GRAIN

Twelve laws that survive any model. Copy it into the prompt whole; it is generated from the same vocabularies the linter reads, so it cannot drift from the standard.

GRAIN — минимальный свод правил кода. Соблюдай буквально. Если правило не покрывает
случай, действуй по смыслу правила, а не по своей привычке. Новых правил не выдумывай.

1. ИМЯ ФУНКЦИИ — ДЕЙСТВИЕ. Начинается с глагола из списка:
   find get list count read write load save make derive resolve parse format encode decode normalize sign verify hash create delete archive restore ensure assert apply set emit send start stop use with render
   Предикат называется префиксом: is has can should was will must.
   ЗАПРЕЩЕНО: handle process manage do perform execute check init update fetch retrieve calculate compute generate build setup validate transform convert prepare determine deal run trigger
2. КОНТРАКТ В ИМЕНИ. find* может вернуть null и никогда не бросает. get* гарантирует
   значение. list* — всегда коллекция. count* — число.
3. ЧИСЛО НЕСЁТ ЕДИНИЦУ: At Ms Sec Min Hours Days Bytes Kb Mb Gb Cents Ratio Pct Count Index Px Deg Hz Bpm Db (refreshTtlSec, priceCents,
   sizeBytes). Без единицы допустимо только безразмерное: x y z id width height depth port page limit offset version priority.
4. БУЛЕВО — только с префиксом: is has can should was will must.
5. СЛОВА-ПУСТЫШКИ ЗАПРЕЩЕНЫ В ИМЕНАХ: data info obj object temp tmp stuff misc thing things res ret arr str num flag val result helper handler manager wrapper util utils.
   Сокращения пишутся целиком: request, response, message, error, index, config.
6. КОММЕНТАРИЙ ОТВЕЧАЕТ «ПОЧЕМУ» и начинается с тега: why: perf: safety: spec: ref:.
   Пересказ кода, TODO, эмодзи, ASCII-разделители, «шаг 1» — не писать.
7. ФАЙЛ = ОДНА РОЛЬ, роль в имени: <домен>.entry.ts <домен>.route.ts <домен>.rpc.ts <домен>.store.ts <домен>.wire.ts <домен>.policy.ts <домен>.shape.ts <домен>.event.ts <домен>.job.ts <домен>.pure.ts.
   store — единственное место с SQL. pure — ноль I/O. Запрещены: utils util helpers helper common shared misc lib main types constants service manager handler index.
8. CATCH ОБЯЗАН ДЕЙСТВОВАТЬ: пробросить дальше или вернуть типизированный отказ.
   Записать в лог и продолжить — нельзя.
9. НЕДЕТЕРМИНИЗМ ТОЛЬКО НА ГРАНИЦЕ: Date.now Math.random crypto.randomUUID process.env performance.now — только в
   ролях entry route rpc job wire. В домен приходят аргументом.
10. НЕЗАВИСИМЫЕ AWAIT — ЧЕРЕЗ Promise.all. Последовательность только там, где второй
    вызов использует результат первого.
11. ТОЛЬКО ИМЕНОВАННЫЕ ЭКСПОРТЫ. any не существует: внешнее приходит как unknown и
    разбирается схемой.
12. СОБЫТИЕ — СВЕРШИВШИЙСЯ ФАКТ: v1.{домен}.{предмет}.{что произошло} (verified,
    granted, paid), не команда (не payInvoice).

Если сомневаешься в имени — возьми ближайший глагол из списка. Не изобретай синоним,
не добавляй «улучшений» к правилам и не объясняй правила в коде.

Deliberately left out: nesting and length limits, directory depth, the guard → acquire → derive → effect funnel, import direction, the shape of a failure code. Not because they do not matter, but because a linter checks them better — those are precisely the rules where a machine is exact and a model guesses. What remains is what a machine cannot check, or checks too late: the verb dictionary, the find/get contract, a unit on every number, whether a comment means anything, and a catch that does not go silent.

The arbiter is the linter, not the model

Do not ask an assistant whether the code follows the standard. Ask the linter: it reads the same vocabularies, answers with a list of lines, and cannot be confident without a reason. Debt recorded as numbers means new code has to be clean no matter who wrote it — the only guarantee that works identically for a human and for a model.

The standard and language models | AS Docs