след сверки: ключ переехал в секцию docs, конфиг больше не отвергается
Ключ [healthcheck] last, заведённый вчера темой 78, роняли оба скрипта плагина: верхний уровень .av-dev.toml стережёт TOP_KEYS в shared/config.py, и неизвестный ключ там — отказ кодом 3. Первый же прогон сверки сделал бы нерабочими canon check/adopt/upgrade, весь task-track и гейт проекта. След живёт теперь ключом healthcheck_last в секции [docs] — по смыслу (настройки проверок документов) и по цене (правка одной константы DOCS_KEYS в docs.py, общий читатель не тронут). Воспроизведено до и после: docs.py и tasks.py конфиг с ключом принимают. Корень был не в описке, а в ложном обещании канона «неизвестный ключ docs.py игнорирует» — оно старше темы 78, и на него опёрлись, не открыв скрипт. Обещание снято, на его месте правило: новый ключ заводится правкой константы скрипта-владельца, и только потом попадает в канон. Журнал — тема 79.
This commit is contained in:
@@ -555,12 +555,10 @@ version = 1 # версия раскладки
|
|||||||
|
|
||||||
[docs]
|
[docs]
|
||||||
migrations = "internal/store/migrations" # если БД есть
|
migrations = "internal/store/migrations" # если БД есть
|
||||||
|
healthcheck_last = "a1b2c3d" # сверка документов: коммит прошлого прогона
|
||||||
|
|
||||||
[tasks]
|
[tasks]
|
||||||
dir = "tasks" # каталог задач от корня репозитория
|
dir = "tasks" # каталог задач от корня репозитория
|
||||||
|
|
||||||
[healthcheck]
|
|
||||||
last = "a1b2c3d" # сверка документов: коммит прошлого прогона
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`version` — версия раскладки, под которую проект приведён, целым числом:
|
`version` — версия раскладки, под которую проект приведён, целым числом:
|
||||||
@@ -571,13 +569,18 @@ last = "a1b2c3d" # сверка документов: ко
|
|||||||
делает сверку с `database.md`. `[tasks]` — где лежит каталог задач и как названы
|
делает сверку с `database.md`. `[tasks]` — где лежит каталог задач и как названы
|
||||||
его части; состав ключей описывает скилл `task-track`.
|
его части; состав ключей описывает скилл `task-track`.
|
||||||
|
|
||||||
`[healthcheck] last` — коммит, на котором в последний раз проходила сверка
|
`[docs] healthcheck_last` — коммит, на котором в последний раз проходила сверка
|
||||||
документов; ставит его сам `av-dev:doc-healthcheck` последним шагом прогона, а
|
документов; ставит его сам `av-dev:doc-healthcheck` последним шагом прогона, а
|
||||||
читает `av-dev:doc-sync`, чтобы сосчитать задачи, сделанные с тех пор. **Ключ
|
читает `av-dev:doc-sync`, чтобы сосчитать задачи, сделанные с тех пор. **Ключ
|
||||||
необязательный и в скелете его нет намеренно**: у нового проекта сверок не было,
|
необязательный и в скелете его нет намеренно**: у нового проекта сверок не было,
|
||||||
и пустое значение врало бы про это меньше, чем отсутствие ключа, только на вид.
|
и пустое значение врало бы про это меньше, чем отсутствие ключа, только на вид.
|
||||||
Отсутствие читается однозначно — «не сверялись ни разу».
|
Отсутствие читается однозначно — «не сверялись ни разу».
|
||||||
|
|
||||||
|
Секции он достался по смыслу: `[docs]` — настройки проверок документов, а сверка
|
||||||
|
документов и есть такая проверка. Своя секция верхнего уровня стоила бы правки
|
||||||
|
общего читателя `shared/config.py` и сделала бы файл, объявленный «версией и
|
||||||
|
настройками», хранилищем состояния.
|
||||||
|
|
||||||
**Формат TOML взят ради комментариев.** Файл лежит в репозитории проекта, и
|
**Формат TOML взят ради комментариев.** Файл лежит в репозитории проекта, и
|
||||||
человек, открывший его через полгода, обязан прочитать в нём, что означает
|
человек, открывший его через полгода, обязан прочитать в нём, что означает
|
||||||
число. JSON комментариев не знает, и объяснение приходилось держать в другом
|
число. JSON комментариев не знает, и объяснение приходилось держать в другом
|
||||||
@@ -592,6 +595,20 @@ last = "a1b2c3d" # сверка документов: ко
|
|||||||
читаются: два дома для одной версии расходятся молча. Увидев их, `docs.py` и
|
читаются: два дома для одной версии расходятся молча. Увидев их, `docs.py` и
|
||||||
`tasks.py` говорят «прежняя раскладка» и зовут `upgrade` — версия 1 журнала.
|
`tasks.py` говорят «прежняя раскладка» и зовут `upgrade` — версия 1 журнала.
|
||||||
|
|
||||||
Ключей будет больше по мере роста проверок; неизвестный ключ `docs.py`
|
Ключей будет больше по мере роста проверок, но **заводятся они только вместе с
|
||||||
игнорирует, отсутствующий — считает «проверка неприменима» и говорит об этом
|
правкой скрипта**: неизвестный ключ — не безмолвный пропуск, а **отказ кодом
|
||||||
строкой, а не молчит.
|
3**. Верхний уровень стережёт `shared/config.py` (`TOP_KEYS`), секцию `[docs]` —
|
||||||
|
`docs.py` (`DOCS_KEYS`), секцию `[tasks]` — `tasks.py`. Довод у отказа
|
||||||
|
проверяемый: ключ, положенный не в ту секцию, при молчаливом пропуске не значит
|
||||||
|
ничего — проверка объявляет себя неприменимой, отчёт выходит зелёным, и на месте
|
||||||
|
настройки оказывается тишина.
|
||||||
|
|
||||||
|
**Здесь это правило однажды соврало, и цена была немедленной.** Абзац обещал, что
|
||||||
|
неизвестный ключ игнорируется; по этому обещанию скилл сверки завёл себе секцию
|
||||||
|
`[healthcheck]` верхнего уровня — и первый же её прогон сделал бы нерабочими
|
||||||
|
`docs.py`, `tasks.py` и гейт проекта, который их зовёт. Отсюда и порядок: **новый
|
||||||
|
ключ заводится правкой константы в скрипте-владельце, и только потом появляется
|
||||||
|
здесь**.
|
||||||
|
|
||||||
|
**Отсутствующий** ключ — другое дело: он значит «проверка неприменима», и скрипт
|
||||||
|
говорит об этом строкой, а не молчит.
|
||||||
|
|||||||
@@ -296,7 +296,15 @@ def read_config(root: Path, rep: Report) -> dict:
|
|||||||
|
|
||||||
# Ключи секции `[docs]`. Секцию знает этот скрипт, а не общий читатель: ключ
|
# Ключи секции `[docs]`. Секцию знает этот скрипт, а не общий читатель: ключ
|
||||||
# заводится вместе с проверкой, которая его читает.
|
# заводится вместе с проверкой, которая его читает.
|
||||||
DOCS_KEYS = ("migrations",)
|
#
|
||||||
|
# `healthcheck_last` — коммит прошлой сверки документов; пишет его скилл
|
||||||
|
# `av-dev:doc-healthcheck`, читает `av-dev:doc-sync`, чтобы сосчитать задачи с
|
||||||
|
# тех пор. Здесь он стоит **только чтобы файл не отвергли**: неизвестный ключ —
|
||||||
|
# отказ кодом 3, то есть ключ, заведённый скиллом мимо этой константы, сделал бы
|
||||||
|
# нерабочими и `docs.py`, и `tasks.py`, и гейт проекта, который их зовёт.
|
||||||
|
# Проверки, читающей его, у скрипта нет и не предполагается: значение — след
|
||||||
|
# работы человека, а не настройка.
|
||||||
|
DOCS_KEYS = ("migrations", "healthcheck_last")
|
||||||
|
|
||||||
|
|
||||||
def docs_cfg(cfg: dict) -> dict:
|
def docs_cfg(cfg: dict) -> dict:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: doc-healthcheck
|
name: doc-healthcheck
|
||||||
description: "Проверка здоровья документации проекта судом, а не машиной: не разошлись ли документы между собой и с кодом. Зовёт двух агентов на весь канон разом — doc-consistency (один факт в двух домах, прямое противоречие, поведение в architecture.md вместо спек, ADR без парного статуса, число без происхождения) и doc-code-drift (протухший факт: имя ветки, команды, пути, зависимости поимённо, настройки с числом, единые точки, capability). Разбирает урожай порциями: строка на замену идёт в документ сразу, работа больше абзаца становится задачей. Прогон оставляет след — ключ [healthcheck] last в .av-dev.toml, — и по нему синк документации считает, сколько задач сделано с прошлой сверки, и выдаёт сигнал строкой. Использовать, когда с прошлой сверки сделан десяток задач, когда вернулись к проекту после перерыва, перед тем как опереться на документ в решении, а также шагом adopt и upgrade. Дорого — не на каждой задаче. Раскладку и версию раскладки проверяет скилл av-dev:canon, язык документов — агент doc-wording."
|
description: "Проверка здоровья документации проекта судом, а не машиной: не разошлись ли документы между собой и с кодом. Зовёт двух агентов на весь канон разом — doc-consistency (один факт в двух домах, прямое противоречие, поведение в architecture.md вместо спек, ADR без парного статуса, число без происхождения) и doc-code-drift (протухший факт: имя ветки, команды, пути, зависимости поимённо, настройки с числом, единые точки, capability). Разбирает урожай порциями: строка на замену идёт в документ сразу, работа больше абзаца становится задачей. Прогон оставляет след — ключ [docs] healthcheck_last в .av-dev.toml, — и по нему синк документации считает, сколько задач сделано с прошлой сверки, и выдаёт сигнал строкой. Использовать, когда с прошлой сверки сделан десяток задач, когда вернулись к проекту после перерыва, перед тем как опереться на документ в решении, а также шагом adopt и upgrade. Дорого — не на каждой задаче. Раскладку и версию раскладки проверяет скилл av-dev:canon, язык документов — агент doc-wording."
|
||||||
---
|
---
|
||||||
|
|
||||||
# Здоровье документации
|
# Здоровье документации
|
||||||
@@ -128,11 +128,17 @@ check` и его скрипт; здесь начинается там, где к
|
|||||||
|
|
||||||
## След прогона
|
## След прогона
|
||||||
|
|
||||||
**Последним шагом прогон правит `.av-dev.toml`** — ключ `last` в секции
|
**Последним шагом прогон правит `.av-dev.toml`** — ключ `healthcheck_last` в
|
||||||
`[healthcheck]`: хеш коммита `HEAD` и дата комментарием рядом. Состав ключей —
|
секции `[docs]`: хеш коммита `HEAD` и дата комментарием рядом. Состав ключей —
|
||||||
[канон](../canon/references/canon.md), раздел `.av-dev.toml`; правится **строка**,
|
[канон](../canon/references/canon.md), раздел `.av-dev.toml`; правится **строка**,
|
||||||
а не файл целиком.
|
а не файл целиком.
|
||||||
|
|
||||||
|
**Секцию и имя ключа не выбирай сам.** Неизвестный ключ `.av-dev.toml` — отказ
|
||||||
|
кодом 3, а не пропуск: ключ, заведённый мимо константы скрипта-владельца, роняет
|
||||||
|
`docs.py`, `tasks.py` и гейт проекта разом. Этот ключ там уже назван
|
||||||
|
(`DOCS_KEYS` в `av-dev/skills/canon/scripts/docs.py`), а любой другой пришлось бы
|
||||||
|
заводить правкой скрипта.
|
||||||
|
|
||||||
**Без следа признак «десяток задач» не считается никем.** Так и было: сверку
|
**Без следа признак «десяток задач» не считается никем.** Так и было: сверку
|
||||||
звали по памяти, то есть не звали — тот же прозаический триггер, что дал 6
|
звали по памяти, то есть не звали — тот же прозаический триггер, что дал 6
|
||||||
записей ADR на 43 изменения. След превращает признак в число, которое
|
записей ADR на 43 изменения. След превращает признак в число, которое
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: doc-sync
|
name: doc-sync
|
||||||
description: "Вести содержимое документов канона по ходу разработки. Правки двух родов, и спрашивается один: отражение сделанного (вливание дельт, миграция в database.md, компонент в architecture.md) пишется молча, а новая запись и новая норма (ADR, правило в conventions, записка в research, инвариант CLAUDE.md, периметр security.md, граница passport.md, дефект в review.md) только предлагается — пишет её второй запуск после слова человека. Построчный отчёт по каждому документу остаётся: каждый назван либо правкой, либо предложением, либо отрицанием с причиной. ADR и записка разведки — промоут цитатой из архивного design.md или записки, а не второе сочинение. Синк же считает и выдаёт строкой сигнал сверки: сколько задач сделано с прошлого прогона av-dev:doc-healthcheck. Использовать, когда задача сделана и надо обновить документацию, когда просят завести ADR или записать решение, занести находку о внешних данных, записать проскочивший дефект, разгрузить разросшуюся архитектуру. Раскладку и соответствие канону проверяет скилл av-dev:canon."
|
description: "Вести содержимое документов канона по ходу разработки. Правки двух родов, и спрашивается один: отражение сделанного (вливание дельт, миграция в database.md, компонент в architecture.md) пишется молча, а новая запись и новая норма (ADR, правило в conventions, записка в research, инвариант CLAUDE.md, периметр security.md, граница passport.md, дефект в review.md) только предлагается — пишет её второй запуск после слова человека. Построчный отчёт по каждому документу остаётся: каждый назван либо правкой, либо предложением, либо отрицанием с причиной. ADR и записка разведки — промоут цитатой из архивного design.md или записки, а не второе сочинение. Синк же считает и выдаёт строкой сигнал сверки: сколько задач сделано с прошлого прогона av-dev:doc-healthcheck, читая след в ключе [docs] healthcheck_last. Использовать, когда задача сделана и надо обновить документацию, когда просят завести ADR или записать решение, занести находку о внешних данных, записать проскочивший дефект, разгрузить разросшуюся архитектуру. Раскладку и соответствие канону проверяет скилл av-dev:canon."
|
||||||
---
|
---
|
||||||
|
|
||||||
# Ведение содержимого канона
|
# Ведение содержимого канона
|
||||||
@@ -303,9 +303,9 @@ av-dev:code-review`, его `references/review-journal.md`.
|
|||||||
ровно тот прозаический триггер, который дал 6 записей ADR на 43 изменения, — и
|
ровно тот прозаический триггер, который дал 6 записей ADR на 43 изменения, — и
|
||||||
здесь он не срабатывал по той же причине.
|
здесь он не срабатывал по той же причине.
|
||||||
|
|
||||||
**След оставляет сама сверка** — ключ `[healthcheck] last` в `.av-dev.toml`
|
**След оставляет сама сверка** — ключ `healthcheck_last` в секции `[docs]`
|
||||||
(состав ключей — [canon.md](../canon/references/canon.md), раздел
|
файла `.av-dev.toml` (состав ключей — [canon.md](../canon/references/canon.md),
|
||||||
`.av-dev.toml`). **Считает синк**, и вот чем:
|
раздел `.av-dev.toml`). **Считает синк**, и вот чем:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git rev-list --count <last>..HEAD -- openspec/changes/archive
|
git rev-list --count <last>..HEAD -- openspec/changes/archive
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# 79. След сверки переехал в секцию docs; ключ верхнего уровня ронял скрипты (2026-08-23)
|
||||||
|
|
||||||
|
## Что было
|
||||||
|
|
||||||
|
Тема 78 завела след сверки документов ключом `last` в секции `[healthcheck]`
|
||||||
|
файла `.av-dev.toml`. Ревью трансформации — три прохода по скиллам и документам —
|
||||||
|
нашло, что такого ключа не переживает ни один скрипт плагина.
|
||||||
|
|
||||||
|
Проверено запуском, а не рассуждением. В проекте с `[healthcheck] last` команда
|
||||||
|
`docs.py check` печатает `ОТКАЗ: .av-dev.toml: неизвестные ключи верхнего уровня:
|
||||||
|
healthcheck` и выходит кодом 3; `tasks.py check` — то же самое. Верхний уровень
|
||||||
|
файла стережёт `shared/config.py` константой `TOP_KEYS`, и неизвестный ключ там —
|
||||||
|
**отказ**, а не пропуск. То есть первый же прогон сверки сделал бы нерабочими
|
||||||
|
`canon check/adopt/upgrade`, весь `task-track` вместе с закрытием задачи и гейт
|
||||||
|
проекта, который их зовёт.
|
||||||
|
|
||||||
|
**Корень — не описка, а ложное обещание документа.** Раздел `.av-dev.toml` в
|
||||||
|
каноне утверждал: «неизвестный ключ `docs.py` игнорирует». Утверждение было
|
||||||
|
неверным и старше темы 78; при проектировании следа опёрлись на него и скрипт не
|
||||||
|
открыли, хотя докстринг `check_keys` говорит прямо обратное: «неизвестный ключ —
|
||||||
|
отказ, а не безмолвный пропуск».
|
||||||
|
|
||||||
|
## Решено
|
||||||
|
|
||||||
|
**Р319. След живёт ключом `healthcheck_last` в секции `[docs]`.** Секция досталась
|
||||||
|
ему по смыслу: `[docs]` — настройки проверок документов, а сверка документов и
|
||||||
|
есть такая проверка. Своя секция верхнего уровня стоила бы правки общего читателя
|
||||||
|
`shared/config.py` и превратила бы файл, объявленный «версией и настройками», в
|
||||||
|
хранилище состояния.
|
||||||
|
|
||||||
|
**Р320. Новый ключ `.av-dev.toml` заводится правкой константы скрипта-владельца,
|
||||||
|
и только потом появляется в каноне.** Порядок именно такой, а не обратный:
|
||||||
|
владелец ключа — тот скрипт, чья константа его перечисляет (`TOP_KEYS` в
|
||||||
|
`shared/config.py`, `DOCS_KEYS` в `docs.py`, свой список в `tasks.py`).
|
||||||
|
|
||||||
|
**Р321. Канон приведён к скрипту, а не скрипт к канону.** Отказ кодом 3 —
|
||||||
|
поведение верное: ключ, положенный не в ту секцию, при молчаливом пропуске не
|
||||||
|
значит ничего, проверка объявляет себя неприменимой, отчёт выходит зелёным, и на
|
||||||
|
месте настройки оказывается тишина. Ложное обещание снято, на его месте — правило
|
||||||
|
Р320 и названная цена этой ошибки.
|
||||||
|
|
||||||
|
## Следствия
|
||||||
|
|
||||||
|
**С282. Версия раскладки не двигается.** Ключ необязательный и заводится сам
|
||||||
|
первым прогоном сверки; проекту делать нечего, а запись журнала версий нужна ради
|
||||||
|
пункта «что сделать проекту».
|
||||||
|
|
||||||
|
**С283. Правило «своей прозе здесь верить нельзя» распространяется и на
|
||||||
|
собственную документацию плагина.** Оно написано про возврат агента, но работает
|
||||||
|
шире: утверждение документа о поведении скрипта проверяется **запуском скрипта**,
|
||||||
|
и стоит эта проверка одной команды. Здесь её не сделали, и цена вышла в рабочую
|
||||||
|
поломку у всякого, кто позвал бы сверку.
|
||||||
|
|
||||||
|
**С284. Гейт репозитория такого класса дефектов не ловит и ловить не может.** Он
|
||||||
|
судит форму: фронтматтеры, дословность копий, адреса, номера журнала, рендер
|
||||||
|
диаграмм. Согласованность прозы с поведением скрипта — суждение, и добыло его
|
||||||
|
ревью, а не хук. Это довод в пользу того, чтобы прогон ревью по трансформации
|
||||||
|
шёл не «если останется время», а следом за ней.
|
||||||
@@ -130,3 +130,4 @@
|
|||||||
| 76 | [Лёгкий проход в цикле, тяжёлые — в отдельном скилле](76-proof-in-cycle-deep-review-apart.md) | 2026-08-23 |
|
| 76 | [Лёгкий проход в цикле, тяжёлые — в отдельном скилле](76-proof-in-cycle-deep-review-apart.md) | 2026-08-23 |
|
||||||
| 77 | [Цикл задачи проверяет механику; метки сняты](77-cycle-checks-mechanics-labels-dropped.md) | 2026-08-23 |
|
| 77 | [Цикл задачи проверяет механику; метки сняты](77-cycle-checks-mechanics-labels-dropped.md) | 2026-08-23 |
|
||||||
| 78 | [Хвост задачи: отражение молча, новое — по слову](78-tail-reflection-silent-new-by-word.md) | 2026-08-23 |
|
| 78 | [Хвост задачи: отражение молча, новое — по слову](78-tail-reflection-silent-new-by-word.md) | 2026-08-23 |
|
||||||
|
| 79 | [След сверки переехал в секцию docs; ключ верхнего уровня ронял скрипты](79-healthcheck-trace-moved-into-docs-section.md) | 2026-08-23 |
|
||||||
|
|||||||
Reference in New Issue
Block a user