- README описывает термины, команды, два режима и вывод проверки; модель не пересказывается — истина остаётся в репозитории набора - CLAUDE.md фиксирует распределение языков, инварианты кода и решения, которые уже приняты и не пересматриваются без просьбы - отдельным разделом перечислены известные остатки, чтобы их не искали заново
142 lines
10 KiB
Markdown
142 lines
10 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with
|
|
code in this repository.
|
|
|
|
## Язык
|
|
|
|
Общение по репозиторию — на русском. Внутри репозитория язык распределён так, и
|
|
это распределение проверяется глазами при ревью:
|
|
|
|
- **английский** — комментарии в коде, имена, тексты ошибок, вывод CLI,
|
|
сообщения и имена тестов;
|
|
- **русский** — `README.md`, `CLAUDE.md`, сообщения коммитов;
|
|
- **язык проверяемого набора** — содержимое тестовых фикстур и литералы
|
|
словарей в `internal/lang`. Это данные под проверкой, а не текст инструмента,
|
|
и переводить их нельзя: сломается то, что они проверяют.
|
|
|
|
Слова словаря законно попадают внутрь английских сообщений, потому что
|
|
подставляются из набора: `rule GTIM-1 has no ПОЧЕМУ block`. Инструмент говорит
|
|
по-английски и цитирует то, чем записан проверяемый набор.
|
|
|
|
## Что это
|
|
|
|
CLI для управления конвенциями. Модель здесь не описывается: она живёт в
|
|
репозитории набора `dev-conventions` — `README.md` (набор и копии),
|
|
`LANGUAGE.md` (форма правила и список проверок), `GUIDE.md` (ведение набора,
|
|
префикс META), `TOOL.md` (решения об инструменте). При расхождении истина там,
|
|
а не в коде и не здесь.
|
|
|
|
Пользовательская сторона — в `README.md`. Ниже — то, что нужно знать, правя код.
|
|
|
|
## Раскладка
|
|
|
|
```
|
|
internal/lang словарь: реестр «версия языка × естественный язык»
|
|
internal/manifest suite.toml — чтение и текстовая правка
|
|
internal/doc разбор документа: шапка, области правил, блоки
|
|
internal/suite сборка набора в память, отбор слоёв под компонент
|
|
internal/check проверки: manifest, form, spread, links
|
|
internal/cli команды, диалог, два режима
|
|
```
|
|
|
|
Зависимость одна — `BurntSushi/toml`. Вторую не заводить: так решено в
|
|
`TOOL.md`, и `Undecoded()` этого парсера бесплатно ловит опечатки в ключах
|
|
манифеста.
|
|
|
|
## Инварианты кода
|
|
|
|
- **В коде нет ни одной темы, ни одного префикса, ни одного пути набора.** Всё
|
|
это приходит из манифеста. Список проверяемых файлов берётся из
|
|
`[prefixes.live]`, а не из дерева директорий: это и есть граница «язык
|
|
употребляет» против «язык цитирует».
|
|
- **Словарь зашит в бинарь** по паре «версия языка × естественный язык», а не
|
|
объявляется в манифесте. Когда спецификация языка уедет в отдельный
|
|
репозиторий и там появятся спеки словарей, источником станут они —
|
|
подменяется `registry`, тип `Vocabulary` и проверки поверх него не трогаются.
|
|
- **Что инструмент пишет, инструмент принимает.** Набор, созданный `suite init`,
|
|
`add` и `rule`, обязан проходить `suite check` без правок. Это проверяет
|
|
`checkClean` в `internal/cli`; ломать инвариант нельзя.
|
|
- **Манифест правится текстом, а не энкодером.** В `suite.toml` комментариев
|
|
больше, чем данных. `manifest.AddEntry` вставляет запись, подстраиваясь под
|
|
порядок таблицы: отсортированную по алфавиту держит отсортированной,
|
|
упорядоченную вручную дополняет в конец. Комментарий, отделённый пустой
|
|
строкой, принадлежит таблице **ниже** себя.
|
|
- **Разбор опирается на разметку, а не на суждение.** Область правила — от
|
|
заголовка до следующего заголовка любого уровня. Метка открывает блок только
|
|
первой в абзаце и полужирным. Огороженные блоки кода исключаются везде;
|
|
инлайн-код вырезается там, где ищутся ссылки, и не вырезается там, где ищутся
|
|
пути канона.
|
|
|
|
## Решения, которые уже приняты
|
|
|
|
Их не пересматривают без явной просьбы — каждое обсуждалось и стоило времени.
|
|
|
|
- **Порядок правил в файле — по читаемости, а не по номерам.** Номер стабилен и
|
|
не переиспользуется, поэтому «порядок по номерам» означал бы «порядок по
|
|
времени написания» навсегда. Проверяется сплошность нумерации, а не
|
|
возрастание.
|
|
- **Ссылка на чужую тему вне нормы разрешена** (META-20): обоснование,
|
|
потерявшее адресата, деградирует честно. Внутри своей темы ссылаться можно
|
|
только в базовый слой, и это проверяется во всём документе, а не только в
|
|
норме: гарантированно присутствует в копии один базовый слой.
|
|
- **Заголовок правила — объявление, а не ссылка.** При разборе ссылок строки
|
|
заголовков пропускаются.
|
|
- **Лок-файла, `push`, отчёта о расхождении и перенумерации не будет.** Модель
|
|
отвергает каждое явно.
|
|
|
|
## Проверки
|
|
|
|
Семейства повторяют деление из `LANGUAGE.md`, раздел «Что стоит проверять
|
|
машиной», и это деление держится в коде: `form` — в любом файле, который язык
|
|
употребляет; `spread` — только в конвенциях, потому что эти проверки о том, что
|
|
документ уезжает к потребителю. Третья часть списка (взаимоисключительность
|
|
строк таблицы, покрытие области действия, отвечает ли обоснование на «что
|
|
сломается») разбором текста не даётся и в коде отсутствует намеренно.
|
|
|
|
Новая проверка заводится вместе с двумя тестами: что она срабатывает и что она
|
|
**молчит** там, где не должна. Второй важнее: проверка, краснеющая на исправном
|
|
файле, выключается целиком. Ложные срабатывания собраны в
|
|
`TestNoFalsePositives`.
|
|
|
|
Перед тем как заводить проверку, стоит прогнать её замысел по живому канону
|
|
(`dev-conventions`): если она покраснеет на исправном наборе, замысел неверен.
|
|
|
|
## Известные остатки
|
|
|
|
- Набор без документа самоуправления, в котором конвенция потеряла `topic`,
|
|
проскочит: признаков «этот документ один» и «у него нет ключей слоя» не
|
|
хватает. Закрывается маркером в манифесте — правка формата, не сделана.
|
|
- Проверка пути канона считает путём любой токен `*.md`, который резолвится в
|
|
файл набора; упоминание `README.md` в конвенции она пометит ошибочно. На
|
|
текущем каноне не срабатывает.
|
|
- Машиночитаемого вывода находок (`--json`) нет.
|
|
|
|
## Тесты
|
|
|
|
```
|
|
go test ./... всё
|
|
go test ./internal/check/ -v проверки, по одному подтесту на случай
|
|
gofmt -l . && go vet ./... перед коммитом
|
|
```
|
|
|
|
Тесты фикстурные: набор пишется во временную директорию и прогоняется целиком.
|
|
`internal/cli` проверяет обе моды, включая диалог — интерактивный режим иначе не
|
|
покрыть, из шелла он требует терминала.
|
|
|
|
## Коммиты
|
|
|
|
Русский, строчная буква, без точки в конце, прошедшее время или страдательный
|
|
залог. Изредка область через двоеточие (`suite check:`). Тело — маркированный
|
|
список на 2–4 пункта с переносом по ~76 колонок, объясняет почему. Conventional
|
|
Commits и `Co-Authored-By` не используются.
|
|
|
|
## Состояние
|
|
|
|
Наборная сторона закончена: `init`, `add`, `rule`, `retire`, `list`, `check`.
|
|
Проектные команды (`add`, `pull`, `list`, `check` без `suite`) не начаты; отбор
|
|
слоёв под компонент для них уже написан — `suite.Assemble`, — и переписывать его
|
|
в сборщике не нужно.
|
|
|
|
Линтеров и CI нет.
|