From a4bc9191e74558556117a7ac9f9e4db043324e6c Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Sun, 23 Aug 2026 19:06:06 +0300 Subject: [PATCH] =?UTF-8?q?=D1=85=D0=B2=D0=BE=D1=81=D1=82=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0=D1=87=D0=B8:=20=D0=BE=D1=82=D1=80=D0=B0=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=BE=D0=BB=D1=87=D0=B0,=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BE=D0=B5=20=E2=80=94=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D1=81=D0=BB=D0=BE=D0=B2=D1=83=20=D1=87=D0=B5=D0=BB=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Синк документации делил правки по документам, а делить их надо по роду. Отражение сделанного (вливание дельт, миграция, компонент в обзоре) пишется молча: без правки документ станет ложным. Новая запись и новая норма — ADR, конвенция, записка разведки, инвариант, периметр, дефект в журнале — только предлагаются, а пишет их третий такт шага 6 после слова человека. Реплика при этом одна на весь хвост: вопрос про урожай ревью переехал с шага 5 на шаг 6 и слился с предложениями синка — решение одно, «что из найденного переживёт задачу». Плановых стопов в сценарии решения стало ровно два, и оба про решения человека. Сверка документов получила счётчик: doc-healthcheck оставляет след ключом [healthcheck] last в .av-dev.toml, синк считает по нему задачи с прошлого прогона и говорит строкой. Прежде признак «десяток задач» держался в памяти, то есть не срабатывал. Журнал — тема 78. --- README.md | 4 +- av-dev/skills/canon/references/canon.md | 15 ++ av-dev/skills/code-resolve/SKILL.md | 15 +- .../code-resolve/references/maintain.md | 10 ++ .../code-resolve/references/research.md | 7 + .../skills/code-resolve/references/solve.md | 142 +++++++++++---- av-dev/skills/code-review/SKILL.md | 12 +- .../skills/code-review/references/promote.md | 13 ++ av-dev/skills/doc-healthcheck/SKILL.md | 31 +++- av-dev/skills/doc-sync/SKILL.md | 162 +++++++++++++++--- .../78-tail-reflection-silent-new-by-word.md | 112 ++++++++++++ decisions/README.md | 1 + 12 files changed, 462 insertions(+), 62 deletions(-) create mode 100644 decisions/78-tail-reflection-silent-new-by-word.md diff --git a/README.md b/README.md index 1eefb42..6b00015 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,9 @@ `doc-sync`, `doc-init` и `canon`; - `doc-sync` — содержимое канона по ходу разработки: ADR из архивного `design.md`, промоут конвенций, запись в разведку и журнал ревью, чистка - архитектуры. + архитектуры. Правки двух родов, и спрашивается один: отражение сделанного + пишется молча, новая запись и новая норма — только по слову человека. Он же + считает и говорит строкой, сколько задач сделано с прошлой сверки документов. **Учёт работ.** Владеет каталогом задач. diff --git a/av-dev/skills/canon/references/canon.md b/av-dev/skills/canon/references/canon.md index 4d9b9cb..a5b2608 100644 --- a/av-dev/skills/canon/references/canon.md +++ b/av-dev/skills/canon/references/canon.md @@ -295,6 +295,11 @@ kebab-case.** Причина не эстетическая: имя файла с «заменено на». +**Сработавший триггер даёт предложение, а не запись.** Заводит ADR человек своим +словом — правило и его причина в скилле `av-dev:doc-sync`, раздел «Два рода +правок». Канон здесь отвечает за другое: за то, при каких условиях предлагать +вообще есть что. + Не заводится для рутины и для того, что видно из кода и `git log`. Записи неизменяемы: передумали — заводится новая, старая получает статус. @@ -553,6 +558,9 @@ migrations = "internal/store/migrations" # если БД есть [tasks] dir = "tasks" # каталог задач от корня репозитория + +[healthcheck] +last = "a1b2c3d" # сверка документов: коммит прошлого прогона ``` `version` — версия раскладки, под которую проект приведён, целым числом: @@ -563,6 +571,13 @@ dir = "tasks" # каталог задач от корн делает сверку с `database.md`. `[tasks]` — где лежит каталог задач и как названы его части; состав ключей описывает скилл `task-track`. +`[healthcheck] last` — коммит, на котором в последний раз проходила сверка +документов; ставит его сам `av-dev:doc-healthcheck` последним шагом прогона, а +читает `av-dev:doc-sync`, чтобы сосчитать задачи, сделанные с тех пор. **Ключ +необязательный и в скелете его нет намеренно**: у нового проекта сверок не было, +и пустое значение врало бы про это меньше, чем отсутствие ключа, только на вид. +Отсутствие читается однозначно — «не сверялись ни разу». + **Формат TOML взят ради комментариев.** Файл лежит в репозитории проекта, и человек, открывший его через полгода, обязан прочитать в нём, что означает число. JSON комментариев не знает, и объяснение приходилось держать в другом diff --git a/av-dev/skills/code-resolve/SKILL.md b/av-dev/skills/code-resolve/SKILL.md index 41de6de..81b25ce 100644 --- a/av-dev/skills/code-resolve/SKILL.md +++ b/av-dev/skills/code-resolve/SKILL.md @@ -1,6 +1,6 @@ --- name: code-resolve -description: "Взять одну задачу и довести её до закрытия. Одна точка входа, три сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ известен и меняется поведение — сценарий решения: цикл Spec Driven Development (opsx propose → чекпоинт с объяснением человеческим языком, где форму решения одобряет человек → opsx apply → ревью кода постоянным составом → archive → синк документации → коммит → закрытие). Способ известен, а спека не меняется (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) — сценарий обслуживания: правка → гейт со сверкой состава проверок → ревью фиксированным планом без change (autotests, operations, плюс conventions и техника, если тронут код) → синк документации → коммит → закрытие; планового стопа нет, change не заводится. Нашлась дельта-спека — задача оказалась шире своего типа: стоп с объяснением простым языком и двумя решениями человека, переформулировать запись в fix или feature и решать её процессом того типа следующим прогоном либо прекратить работу. Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → вычитка написанного → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст постановки: размеченная запись не обязательна — текст берётся так же, как его берёт opsx:propose, и текстом идут все три сценария. Использовать, когда просят взять, сделать или решить задачу — хоть записью из каталога, хоть описанием прямо в разговоре, — обновить зависимости или сборку, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога." +description: "Взять одну задачу и довести её до закрытия. Одна точка входа, три сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ известен и меняется поведение — сценарий решения: цикл Spec Driven Development (opsx propose → чекпоинт с объяснением человеческим языком, где форму решения одобряет человек → opsx apply → ревью кода постоянным составом → archive и отражение в документах молча → одна реплика о новом, где человек решает, что заводится: ADR, конвенция, задачи из урожая ревью → письмо одобренного → коммит → закрытие). Плановых стопов у сценария два, и оба про решения человека: чекпоинт до кода решает форму решения, реплика после кода — что из найденного переживёт задачу. Способ известен, а спека не меняется (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) — сценарий обслуживания: правка → гейт со сверкой состава проверок → ревью фиксированным планом без change (autotests, operations, плюс conventions и техника, если тронут код) → синк документации, где почти всё письмо — отражение фактов и идёт молча → коммит → закрытие; планового стопа нет, change не заводится. Нашлась дельта-спека — задача оказалась шире своего типа: стоп с объяснением простым языком и двумя решениями человека, переформулировать запись в fix или feature и решать её процессом того типа следующим прогоном либо прекратить работу. Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → вычитка написанного → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст постановки: размеченная запись не обязательна — текст берётся так же, как его берёт opsx:propose, и текстом идут все три сценария. Использовать, когда просят взять, сделать или решить задачу — хоть записью из каталога, хоть описанием прямо в разговоре, — обновить зависимости или сборку, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога." --- # Работа над одной задачей @@ -302,7 +302,8 @@ flowchart TD | код — `opsx:apply`, вместе с гейтом до зелёного и поведенческой верификацией | [solve](references/solve.md), шаг 4 | | правки по находкам триажа, помеченным `инлайн` | [solve](references/solve.md), шаг 5; [maintain](references/maintain.md), шаг 4 | | правка оснастки в сценарии обслуживания | [maintain](references/maintain.md), шаг 2 | -| архивация change и синк документации — `opsx:archive` и `av-dev:doc-sync` | [solve](references/solve.md), шаг 6; [maintain](references/maintain.md), шаг 5 | +| архивация change и отражение в документах — `opsx:archive` и `av-dev:doc-sync` | [solve](references/solve.md), шаг 6, такт 1; [maintain](references/maintain.md), шаг 5 | +| письмо одобренного нового и задачи из урожая | [solve](references/solve.md), шаг 6, такт 3 | **Остальное остаётся оркестратору, и перечень закрыт:** выбор сценария и стопы, чекпоинт, вызовы `av-dev:code-review`, `av-dev-git:commit` и `av-dev:task-track`, @@ -363,8 +364,14 @@ flowchart TD **Чек-лист синка — единственное исключение из «не длиннее экрана».** Он приходит из хвостового агента целиком и целиком уезжает в доклад: тронутые документы -поимённо, нетронутые — одной строкой с общей причиной. Сжать его своими словами -значит потерять принуждённое отрицание, ради которого шаг и существует. +поимённо, предложенное — строкой с основанием, нетронутые — одной строкой с общей +причиной. Сжать его своими словами значит потерять принуждённое отрицание, ради +которого шаг и существует. + +**Предложения из этого чек-листа оркестратор не исполняет сам.** Они уезжают в +реплику человеку вместе с урожаем ревью, и написанным становится только то, что +он назвал (`solve.md`, шаг 6, такт второй). Агент, вернувший предложение, свою +работу сделал — заведение нового не его решение и не твоё. **Возврату на слово не верят, и перечитывать за агентом дифф для этого не надо.** Верят независимым артефактам: зелёному гейту, отчёту триажа, ревью следующего diff --git a/av-dev/skills/code-resolve/references/maintain.md b/av-dev/skills/code-resolve/references/maintain.md index 7a7af26..36d0c60 100644 --- a/av-dev/skills/code-resolve/references/maintain.md +++ b/av-dev/skills/code-resolve/references/maintain.md @@ -381,6 +381,16 @@ ADR: список источников канон закрыл двумя — а Нетронутые группируются одной строкой. Возврат приходит в этой же форме и уезжает в доклад целиком: тронутое без нетронутого не отличается от невыполненного шага. +**Второе правило синка тоже действует: отражение пишется молча, новое +предлагается** (дом — раздел «Два рода правок» скилла `av-dev:doc-sync`). Здесь +оно почти ничего не стоит: обслуживание двигает **факты** — команды, шаги гейта, +зависимости поимённо, пути, имя ветки, числа настроек, — а факт в документе, +разошедшийся с кодом, это отражение по определению. Реплика человеку на этом +сценарии редка, и поводов у неё два: **новый запрет или инвариант в `CLAUDE.md`** +и **сужение проверок в `review.*`**. Второе спрашивать не надо — проверки сузил +человек, слово по ним сказано; первое надо, потому что запрет свяжет все будущие +задачи. Нового нет — реплики нет, и шаг кончается возвратом агента. + **Здесь этот шаг весит больше, чем в решении, и вот почему.** Обслуживание не меняет поведения — значит, почти всё, что оно меняет, это документация: команды, шаги гейта, зависимости поимённо, пути, имя основной ветки, настройки с числовым diff --git a/av-dev/skills/code-resolve/references/research.md b/av-dev/skills/code-resolve/references/research.md index 7c2e17b..938209c 100644 --- a/av-dev/skills/code-resolve/references/research.md +++ b/av-dev/skills/code-resolve/references/research.md @@ -281,6 +281,13 @@ git и читается диффом, а второй стоп на каждой незачем. Но **названо должно быть каждое место, куда ты писал**, — доклад без перечня адресов неотличим от доклада о ненаписанном. +**Правило «новое по слову» здесь тоже не задаёт второго вопроса**, хотя ответ +разведки — новое от первой до последней строки. Слово уже сказано **чекпоинтом +вариантов**: человек выбрал вариант и тем самым заказал запись. Спросить ещё раз +значило бы переспросить только что одобренное — и заодно предложить выбросить +работу, ради которой прогон и шёл. Что записать нового сверх выбранного — +например ADR по решению с ценой, — предлагается, как везде. + **Документов канона в проекте нет** — писать ответ некуда: назови это исходом, предложи завести канон скиллом `av-dev:canon` и оставь ответ в докладе целиком, чтобы работа не пропала. Заводить `docs/` мимо канона нельзя. diff --git a/av-dev/skills/code-resolve/references/solve.md b/av-dev/skills/code-resolve/references/solve.md index d2ae11f..3d45ab5 100644 --- a/av-dev/skills/code-resolve/references/solve.md +++ b/av-dev/skills/code-resolve/references/solve.md @@ -28,14 +28,17 @@ flowchart TD s3(["3. ЧЕКПОИНТ: объяснение
в чём проблема, как решаем,
чем рискуем"]) s4["4. opsx:apply — код, гейт,
поведенческая верификация — агентом"] s5["5. ревью кода — постоянный состав
+ отработка замечаний агентом"] - s6["6. opsx:archive + синк документации —
одним агентом"] + s6["6. opsx:archive + отражение в документах —
одним агентом"] + s6q(["РЕПЛИКА: что заводим из нового —
ADR, конвенция, задачи из урожая"]) + s6b["6b. письмо одобренного и задачи —
тем же агентом"] s7["7. коммит работы — av-dev-git:commit"] s8["8. закрыть задачу — av-dev:task-track,
вторым коммитом учёта"] in --> s1 - s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 + s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s6q --> s6b --> s7 --> s8 s3 -.->|"скорректировать:
правка спек и дизайна"| s3 s5 -.->|"находка отменяет дизайн:
меняются дельта-спеки"| s3 + s6 -.->|"нового нет:
реплики нет"| s7 ``` Схема — **сводка**: содержание каждого шага в его разделе ниже, и при @@ -64,7 +67,8 @@ flowchart TD и без дома названы в границах покрытия; 3. решение прошло чекпоинт и не разошлось с одобренным — либо разошлось, и чекпоинт был пройден заново; -4. change заархивирован, дельты влиты в актуальные спеки; +4. change заархивирован, дельты влиты в актуальные спеки, и по **каждому** + документу канона назван исход — правка, предложение или отрицание с причиной; 5. коммит сделан в текущую ветку; 6. **критерии приёмки, если проект их дал, выписаны поимённо, и по каждому назван оракул и наблюдаемый исход** — «прогнал вот это, увидел вот то». Это **доклад, @@ -278,10 +282,15 @@ flowchart TD откуда взялась. **Задачи из урожая заводятся только тогда, когда человек сказал «заводим».** -Покажи список одной репликой и спроси. Сказал — зови `av-dev:task-track`, у него -на этот вход отдельный сценарий «задачи из ревью и аудита»: своя нарезка, свой -формат, свои правила дублей, и передавать находку туда надо дословно. Не сказал — -урожай остаётся строками доклада, и это исход, а не потеря. +Спрашивается это **не здесь, а на шаге 6** — там же, где спрашивается новое в +документах, и той же одной репликой: два вопроса подряд про одно и то же («что из +найденного заводим») стоили бы человеку двух переключений вместо одного. Сюда +урожай складывается, а не выносится. + +Сказал «заводим» — зовёт `av-dev:task-track` агент шага 6, у него на этот вход +отдельный сценарий «задачи из ревью и аудита»: своя нарезка, свой формат, свои +правила дублей, и передавать находку туда надо дословно. Не сказал — урожай +остаётся строками доклада, и это исход, а не потеря. **Молча беклог не наполняется.** Очередь работ ведёт человек, и задача, заведённая за него по ходу чужого прогона, отнимает у него ровно то решение, ради которого @@ -308,37 +317,62 @@ flowchart TD единственный **независимый** артефакт о составе прогона: своей прозе здесь верить нельзя — её написал тот, кто мог проход и пропустить. -### 6. Архивация и синк документации — одним агентом +### 6. Архивация и документы — отражение молча, новое по слову -**Оба шага уходят одному агенту, и это один запуск** (SKILL.md, «Кто пишет»). -Работа здесь письменная от начала до конца: `opsx:archive` вливает дельты в -актуальные спеки, `av-dev:doc-sync` правит документы канона, и обе правки идут по +Шаг идёт **в три такта**, и агент запускается в нём дважды. Причина одна: письмо +в документы бывает двух родов, а спрашивается только один. + +**Копия.** Дом правила — раздел «Два рода правок» скилла `av-dev:doc-sync`. +Правится дом, а не этот файл. + + + +- **Отражение** — документ уже описывает эту вещь, и без правки он **станет + ложным**: миграция написана, а `database.md` её не знает; компонент заведён, а + `architecture.md` перечисляет прежние. Такая правка ничего не решает, она + договаривает решённое на чекпоинте и уже стоящее в коде. **Пишется молча.** +- **Новое** — в каноне заводится запись или норма, которой не было: ADR, правило + в конвенциях, записка в `research/`, инвариант в `CLAUDE.md`, сдвиг периметра в + `security.md`, граница в `passport.md`, дефект в журнале `review.md`. Такая + запись переживёт задачу и свяжет следующие. **Пишется только по слову + человека.** + + + +#### Такт первый — агент: архив и отражение + +**Оба скилла уходят одному агенту, и это один запуск** (SKILL.md, «Кто пишет»). +Работа письменная от начала до конца: `opsx:archive` вливает дельты в актуальные +спеки, `av-dev:doc-sync` идёт по чек-листу и пишет отражение, и обе правки — по чек-листам своих скиллов, а не по суждению оркестратора. Разнесённые по двум -запускам, они стоили бы двух заданий, двух возвратов и паузы между ними — при том -что второй шаг читает ровно то, что оставил первый. +запускам, они стоили бы двух заданий, двух возвратов и паузы между ними — при +том что второй читает ровно то, что оставил первый. В задании: корень проекта, идентификатор change, база диффа и **порядок** — сначала `opsx:archive` с `openspec validate --strict` перед ним, затем -`av-dev:doc-sync`. Плюс требование довести гейт проекта до зелёного после правок: -документы у многих проектов гейт проверяет, и красный гейт здесь остановил бы -коммит следующим шагом. +`av-dev:doc-sync`. -**Вычитку языка зовёт сам `av-dev:doc-sync`** — агента `doc-wording` по пачке -правленых документов. Отдельным запуском её тянуть не надо, и в задании она не -называется: правило живёт в том скилле, а не здесь. +**Вычитка и гейт идут последним тактом, в котором писали.** Вернул непустой +список предложений — оба ждут третьего такта; список пуст — этот такт последний, +и оба идут в нём. Гонять гейт дважды подряд по одному дереву незачем, а вычитывать +пачку, которая сейчас пополнится, — тем более. Вычитку зовёт сам +`av-dev:doc-sync` (агента `doc-wording` по пачке правленого), и правило живёт в +том скилле; гейт до зелёного доводит агент, потому что красный гейт остановил бы +коммит следующим шагом — документы у многих проектов он проверяет. -**Возврат — адреса тронутого, исход валидации, чек-лист синка и исход гейта.** -Чек-лист уезжает в доклад целиком, и переписывать его своими словами нельзя — это -единственный след того, что каждый документ был назван. +**Возврат — чек-лист, адреса тронутого, исход валидации и исход гейта, если он +гонялся.** +Чек-лист уезжает в доклад целиком, и переписывать его своими словами нельзя — +это единственный след того, что каждый документ был назван. **Правило, которое задаёт его форму, одно и оно жёсткое: принуждённое -отрицание.** Доклад обязан назвать -**каждый** документ канона — либо чем он обновлён, либо «не требуется, потому -что…». Нетронутые группируются одной строкой с общей причиной. Список триггеров -прозой уже проверен на живом проекте и дал 6 записей ADR на 43 изменения; -работает только обязательное отрицание. **Требование стоит в задании агента** — -без него возврат придёт перечнем тронутого, а тронутое без нетронутого не -отличается от невыполненного шага. +отрицание.** Против **каждого** документа канона стоит одно из трёх — чем он +обновлён, что по нему предлагается, либо «не требуется, потому что…». +Нетронутые группируются одной строкой с общей причиной. Список триггеров прозой +уже проверен на живом проекте и дал 6 записей ADR на 43 изменения; работает +только обязательное отрицание. **Требование стоит в задании агента** — без него +возврат придёт перечнем тронутого, а тронутое без нетронутого не отличается от +невыполненного шага. **Список документов и их триггеров здесь не дублируется** — он в чек-листе скилла `av-dev:doc-sync`, и копия уже однажды разошлась с оригиналом, потеряв два @@ -349,6 +383,45 @@ flowchart TD задачу нельзя: документ, заведённый мимо канона, окажется вторым домом ровно тому, что канон потом заведёт своим. +#### Такт второй — одна реплика человеку на весь хвост + +Покажи **одним списком** всё, что заводится нового: + +- **предложения синка** — ADR, конвенция, записка в `research/`, инвариант, + периметр, дефект в журнал. Каждое строкой: что заведём, куда и на каком + основании; +- **урожай ревью с шага 5** — отложенные находки, из которых получаются задачи: + формулировка, оракул, откуда взялась. + +Человек отвечает разом. **Нового нет — реплики нет**, и шаг кончился первым +тактом; у большинства задач так и выходит. + +**Реплика одна, и делить её нельзя.** Спросить про ADR на синке, а про задачи +отдельно — значит взять с человека два переключения там, где решение одно: что из +найденного этой задачей переживёт её. Ровно поэтому вопрос про урожай и перенесён +сюда с шага 5. + +**Спрашиваешь, а не советуешь по каждому пункту.** Основание уже названо строкой, +и второй абзац уговоров превращает реплику в чтение. Человек вправе ответить +«ничего» — это исход, а не потеря: находки остаются строками доклада. + +#### Такт третий — тот же агент: письмо одобренного + +Запускается **только если человек что-то одобрил**. В задании: + +- **одобренные записи дословно** — формулировка, источник, основание; сочинять + заново нельзя, ADR цитирует решение из архивного `design.md`, а не пересказывает + его; +- **задачи из урожая** — вызовом `av-dev:task-track`, сценарий «задачи из ревью и + аудита», находка передаётся дословно вместе с оракулом; +- **вычитка** `doc-wording` по всей пачке правленого — и первого такта, и этого; +- **гейт проекта до зелёного** после правок. + +**Отвергнутое не пишется никуда.** Ни в один документ, ни отдельной записью «от +такого-то отказались»: журнала отвергнутого канон не держит, и заведение его +здесь было бы ровно тем новым, которого человек только что не заказал. Отказ +идёт строкой доклада. + ### 7. Коммит Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не @@ -397,6 +470,11 @@ change. Заводить запись задним числом, чтобы её - **`Урожай`** — отложенные находки списком (формулировка, оракул, откуда взялась) и **что человек по нему решил**: заведены задачи или список остался в докладе; +- **что заведено нового в документах** — одобренное по именам записей, и **что + предложено и отвергнуто**, тоже по именам. Отказ виден только здесь: в + документы он не пишется; +- **сигнал сверки** — строка синка о том, сколько задач сделано с прошлого + прогона `av-dev:doc-healthcheck`, либо что сверки не было ни разу; - **сколько находок ушло инлайном и сколько развилкой** — числом. По нему видно, во что прогон обошёлся человеку; - **одна строка границ покрытия**: какой режим гонялся, какие проходы не @@ -420,6 +498,12 @@ change. Заводить запись задним числом, чтобы её `av-dev:task-track` — по слову человека, у него на этот вход отдельный сценарий «задачи из ревью и аудита». Каталога задач в проекте нет — урожай остаётся списком в докладе, и это говорится строкой. +- **Стопов у сценария два, и оба про решения человека, а не про ход работ.** + Чекпоинт шага 3 решает форму решения **до** кода; реплика шага 6 решает, что из + найденного переживёт задачу. Между ними прогон идёт сам: правки инлайном чинятся + молча, отражение в документах пишется молча. Третьего стопа заводить нельзя — + прогон, останавливающийся чаще, теряет ровно то время, ради которого короткие + итерации и выбраны. - **Способ решения ты не выбираешь.** Он приходит известным: из постановки, из разведки, от человека. Выбор между двумя подходами с разной ценой делается в разведке, у своего чекпоинта, — не по ходу этого сценария. diff --git a/av-dev/skills/code-review/SKILL.md b/av-dev/skills/code-review/SKILL.md index 2953985..166e343 100644 --- a/av-dev/skills/code-review/SKILL.md +++ b/av-dev/skills/code-review/SKILL.md @@ -831,8 +831,12 @@ change»: сверять исход с планом триаж обязан и отчёте: формулировка, оракул, откуда взялась (какой проход, какой change). **Задачи из урожая заводятся только по слову человека, и это правило, а не -вежливость.** Список показывается ему одной репликой; сказал «заводим» — зови -`av-dev:task-track`, у него на этот вход отдельный сценарий «задачи из ревью и +вежливость.** Спрашивает не конвейер: список уезжает вызывающему и показывается +человеку **одной репликой на весь хвост задачи** — вместе с тем новым, что +предлагает записать синк документации (`av-dev:code-resolve`, +`references/solve.md`, шаг 6). Два вопроса про одно и то же — «что из найденного +переживёт задачу» — стоили бы двух переключений вместо одного. Сказал «заводим» — +зовётся `av-dev:task-track`, у него на этот вход отдельный сценарий «задачи из ревью и аудита»: свой формат, кластеризация по причине, дедуп против беклога и кладбища. Не сказал — урожай остаётся строками доклада, и это исход, а не потеря. Прогон, заводящий задачи сам, наполняет беклог работой, которую никто не выбирал; на @@ -844,7 +848,9 @@ change»: сверять исход с планом триаж обязан и - `Promote candidates` — по процедуре [references/promote.md](references/promote.md): находка → конвенция → правило линтера → **удаление формулировки из конвенций**. - Третий шаг обязателен. + Третий шаг обязателен. **Сама конвенция заводится по слову человека** — той же + репликой, что и задачи из урожая: её строка станет входом каждого следующего + прогона, и из всего, что пишет хвост задачи, она связывает дальше всего. - Дефект, проскочивший ревью и всплывший позже, идёт в журнал проекта ([references/review-journal.md](references/review-journal.md)) — сразу, не ретроспективно: теряется именно то, почему дефект не поймали. diff --git a/av-dev/skills/code-review/references/promote.md b/av-dev/skills/code-review/references/promote.md index 205d02a..2e2d841 100644 --- a/av-dev/skills/code-review/references/promote.md +++ b/av-dev/skills/code-review/references/promote.md @@ -52,6 +52,13 @@ flowchart TD тема относится к поведению системы, а не к тому, как мы пишем код, — это не конвенция, а требование: заводится дельта-спека обычным путём. +**Конвенция заводится по слову человека, и это не формальность.** Одна её строка +становится входом каждого следующего прогона ревью и критерием для всех будущих +задач — из всего, что пишет хвост задачи, конвенция связывает дальше всего. +В цикле задачи она поэтому **предлагается**, а не заводится: строка предложения +называет проверяемое свойство и проход, который его нашёл, и по этой паре человек +решает (`av-dev:code-resolve`, `references/solve.md`, шаг 6, такт второй). + Промоут идёт **тем же путём, что change → spec**: правка попадает в тот же коммит, что и исправление кода, с пометкой в сообщении — история промоутов остаётся видна в `git log` по файлу конвенций. @@ -75,6 +82,12 @@ flowchart TD хук блокирует любой коммит, и правило снимут первым же раздражённым движением. Приводить код в соответствие — часть шага 2, отдельным коммитом. +**Отсюда и место шага 2: он не помещается в хвост чужой задачи.** Конфиг, +сканер и приведение кода к зелёному — это работа размером с задачу, и сделанная +попутно она удваивает прогон, который человек заводил ради другого. Согласованный +промоут даёт **строку конвенции сейчас** и **задачу `chore` на механизацию**; +задачу заводит `av-dev:task-track` тем же словом, что и саму конвенцию. + ## Шаг 3. Удаление из конвенций и из промптов **Шаг, который пропускают чаще всего, и единственный, ради которого затевались diff --git a/av-dev/skills/doc-healthcheck/SKILL.md b/av-dev/skills/doc-healthcheck/SKILL.md index ed04c7d..7a84ef2 100644 --- a/av-dev/skills/doc-healthcheck/SKILL.md +++ b/av-dev/skills/doc-healthcheck/SKILL.md @@ -1,6 +1,6 @@ --- name: doc-healthcheck -description: "Проверка здоровья документации проекта судом, а не машиной: не разошлись ли документы между собой и с кодом. Зовёт двух агентов на весь канон разом — doc-consistency (один факт в двух домах, прямое противоречие, поведение в architecture.md вместо спек, ADR без парного статуса, число без происхождения) и doc-code-drift (протухший факт: имя ветки, команды, пути, зависимости поимённо, настройки с числом, единые точки, capability). Разбирает урожай порциями: строка на замену идёт в документ сразу, работа больше абзаца становится задачей. Использовать, когда с прошлой сверки сделан десяток задач, когда вернулись к проекту после перерыва, перед тем как опереться на документ в решении, а также шагом adopt и upgrade. Дорого — не на каждой задаче. Раскладку и версию раскладки проверяет скилл av-dev:canon, язык документов — агент doc-wording." +description: "Проверка здоровья документации проекта судом, а не машиной: не разошлись ли документы между собой и с кодом. Зовёт двух агентов на весь канон разом — doc-consistency (один факт в двух домах, прямое противоречие, поведение в architecture.md вместо спек, ADR без парного статуса, число без происхождения) и doc-code-drift (протухший факт: имя ветки, команды, пути, зависимости поимённо, настройки с числом, единые точки, capability). Разбирает урожай порциями: строка на замену идёт в документ сразу, работа больше абзаца становится задачей. Прогон оставляет след — ключ [healthcheck] last в .av-dev.toml, — и по нему синк документации считает, сколько задач сделано с прошлой сверки, и выдаёт сигнал строкой. Использовать, когда с прошлой сверки сделан десяток задач, когда вернулись к проекту после перерыва, перед тем как опереться на документ в решении, а также шагом adopt и upgrade. Дорого — не на каждой задаче. Раскладку и версию раскладки проверяет скилл av-dev:canon, язык документов — агент doc-wording." --- # Здоровье документации @@ -20,7 +20,10 @@ check` и его скрипт; здесь начинается там, где к - **с прошлой сверки сделан десяток задач.** Документы протухают ровно от сделанной работы: переименованная цель сборки, ушедшая зависимость, второй способ делать то, что обзор объявил единственным, факт, дописанный в - `architecture.md` и уже живущий в `CLAUDE.md`; + `architecture.md` и уже живущий в `CLAUDE.md`. **Этот признак считается, а не + вспоминается**: счёт ведёт синк документации по следу прошлого прогона и + выдаёт строкой на каждой сделанной задаче (`av-dev:doc-sync`, раздел «Сигнал + сверки»); - **вернулись к проекту после перерыва** — прежде чем опираться на написанное; - **перед тем как опереться на документ в решении**, если оно дорогое; - шагом `adopt` и шагом `upgrade` — их зовёт скилл `canon` сам. @@ -123,6 +126,28 @@ check` и его скрипт; здесь начинается там, где к прогоне. Класс ошибок, который повторяется, идёт в `docs/review.*`, раздел настройки, — там дом типовых ложноположительных. +## След прогона + +**Последним шагом прогон правит `.av-dev.toml`** — ключ `last` в секции +`[healthcheck]`: хеш коммита `HEAD` и дата комментарием рядом. Состав ключей — +[канон](../canon/references/canon.md), раздел `.av-dev.toml`; правится **строка**, +а не файл целиком. + +**Без следа признак «десяток задач» не считается никем.** Так и было: сверку +звали по памяти, то есть не звали — тот же прозаический триггер, что дал 6 +записей ADR на 43 изменения. След превращает признак в число, которое +`av-dev:doc-sync` считает командой +`git rev-list --count ..HEAD -- openspec/changes/archive` и говорит вслух +на каждой задаче. + +Ключ **необязательный и заводится сам** — первым же прогоном сверки; проекту для +этого делать нечего. Его отсутствие значит «сверки не было ни разу», и синк +говорит это отдельной строкой. + +**Позвал одного агента из двух — след всё равно ставится, но в докладе назван +неполным.** Иначе следующая сверка отсчитывалась бы от прогона, который смотрел +половину. + ## Доклад - **Кого позвал** — обоих или одного, и почему одного. @@ -147,3 +172,5 @@ check` и его скрипт; здесь начинается там, где к - **Не правит документы за агентов** — они возвращают формулировки, решение подставить принимает человек или ты по его правилу. - **Не заводит задачи** — этим владеет `av-dev:task-track`. +- **Не решает, когда себя звать.** Признак считает синк и говорит строкой; часы + на прогон тратит человек своим словом. diff --git a/av-dev/skills/doc-sync/SKILL.md b/av-dev/skills/doc-sync/SKILL.md index df5c647..eb3a177 100644 --- a/av-dev/skills/doc-sync/SKILL.md +++ b/av-dev/skills/doc-sync/SKILL.md @@ -1,6 +1,6 @@ --- name: doc-sync -description: Вести содержимое документов канона по ходу разработки — синк после сделанной задачи с построчным отчётом по каждому документу, заведение ADR промоутом из архивного design.md или из записки разведки, запись наблюдения в research, запись дефекта и настройки конвейера в review.md, чистка architecture.md от поведения с маркерами долга. Использовать, когда задача сделана и надо обновить документацию, когда просят завести 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. Использовать, когда задача сделана и надо обновить документацию, когда просят завести ADR или записать решение, занести находку о внешних данных, записать проскочивший дефект, разгрузить разросшуюся архитектуру. Раскладку и соответствие канону проверяет скилл av-dev:canon." --- # Ведение содержимого канона @@ -27,32 +27,84 @@ description: Вести содержимое документов канона Это тот же приём, что «границы покрытия» в отчёте ревью и «пустое называется пустым» в каноне. +## Два рода правок, и спрашивается один + +Второе правило, поперёк первого: **пройти по всем документам обязан ты, а +завести новое — человек**. Признак проверяемый и читается одним вопросом: **что +станет с документом, если правку не сделать**. + + + +- **Отражение** — документ уже описывает эту вещь, и без правки он **станет + ложным**: миграция написана, а `database.md` её не знает; компонент заведён, а + `architecture.md` перечисляет прежние. Такая правка ничего не решает, она + договаривает решённое на чекпоинте и уже стоящее в коде. **Пишется молча.** +- **Новое** — в каноне заводится запись или норма, которой не было: ADR, правило + в конвенциях, записка в `research/`, инвариант в `CLAUDE.md`, сдвиг периметра в + `security.md`, граница в `passport.md`, дефект в журнале `review.md`. Такая + запись переживёт задачу и свяжет следующие. **Пишется только по слову + человека.** + + + +**Показывается новое одной репликой и одним списком.** Каждый пункт — строкой: +что заведём, куда и на каком основании. Человек отвечает разом, и одобренное +пишет **следующий заход синка** — в цикле задачи это третий такт шага 6 +(`av-dev:code-resolve`, `references/solve.md`). **Нового нет — реплики нет**, и +это обычный исход: у большинства задач хвост состоит из одного отражения. + +**«По слову» — это по слову, а не вторым вопросом.** Человек уже сказал в этом +прогоне «заведи ADR», сам решил сузить проверки, сам одобрил формулировку +конвенции — слово сказано, и переспрашивать нечего: запись идёт как одобренная, а +в докладе стоит, чьим решением. Предложение существует ради нового, которое +заметил ты, а не ради ритуала. + +**Отказ человека — строка доклада и всё.** В документы он не пишется: журнала +отвергнутых ADR и снятых конвенций канон не держит, и заведение такого журнала +здесь было бы ровно тем новым, которого никто не заказывал. + +**Отрицание от этого не ослабло.** Документ, по которому нечего предложить, +по-прежнему обязан быть назван — просто раньше отрицание читал отчёт, а теперь +человек, и читает он его **до** того, как что-то написано. Обязанность та же: +пропуск неотличим от «не требуется», пока отрицание не сказано вслух. + ## Чек-лист синка Идёт сверху вниз; каждая строка попадает в доклад. -| Документ | Обновляется, когда | Проверка | -| --- | --- | --- | -| `openspec/specs/` | всегда при изменении поведения | вливает `opsx:archive` | -| `database.md` | тронуты миграции | `docs.py check --base` | -| `architecture.md` | новый компонент, граница, внешняя зависимость, изменилось окружение | `docs.py`: capability без упоминания | -| `adr/` | сработал триггер канона (перечень — [canon.md](../canon/references/canon.md#adr)) | нет — только этот чек-лист | -| `research/` | узнали новое о внешнем формате или данных | нет | -| `security.md` | новый недоверенный вход, токен, путь наружу, сдвиг периметра | нет | -| `conventions/` | находка принята и не специфична для одного места | промоут | -| `review.md` | дефект воспроизведён; сузили или расширили проверку | нет | -| `passport.md` | новый потребитель, сдвиг границы «чем не является» | нет | -| `CLAUDE.md` | изменился инвариант, гейт, запрет, необратимое | нет | +| Документ | Род | Обновляется, когда | Проверка | +| --- | --- | --- | --- | +| `openspec/specs/` | отражение | всегда при изменении поведения | вливает `opsx:archive` | +| `database.md` | отражение | тронуты миграции | `docs.py check --base` | +| `architecture.md` | отражение | новый компонент, граница, внешняя зависимость, изменилось окружение | `docs.py`: capability без упоминания | +| `adr/` | новое | сработал триггер канона (перечень — [canon.md](../canon/references/canon.md#adr)) | нет — только этот чек-лист | +| `research/` | новое | узнали новое о внешнем формате или данных | нет | +| `security.md` | новое | новый недоверенный вход, токен, путь наружу, сдвиг периметра | нет | +| `conventions/` | новое | находка принята и не специфична для одного места | промоут | +| `review.md` | новое | дефект воспроизведён; сузили или расширили проверку | нет | +| `passport.md` | новое | новый потребитель, сдвиг границы «чем не является» | нет | +| `CLAUDE.md` | новое | изменился инвариант, гейт, запрет, необратимое | нет | + +**Разрез в таблице не произволен.** Ложным без правки становится ровно тот +документ, который описывает **состояние системы**, — потому отражений в чек-листе +и мало. Остальные задают норму или хранят память: им не с чем разойтись, пока в +них не написано новое. Пример доклада: ``` -Синк документации: +Синк документации. +Отражено, записано: +- openspec/specs/ — влиты дельты change add-bucket-reindex - architecture.md — добавлен воркер свёртки, ссылка на capability reindex - database.md — миграция 00006, таблица bucket -- adr/ — заведён ADR-2026-08-03-queue-as-table: отказ от внешней очереди -- research/ — новое о формате не узнано -- passport, security, conventions, review — не требуется: изменение внутреннее +Предложено, жду слова: +- adr/ — отказ от внешней очереди в пользу таблицы; источник: архивный + design.md; триггер: намеренный отказ от очевидного подхода +Не требуется: research, security, conventions, review, passport, CLAUDE.md — +периметр не двигался, инварианты те же, новое о внешних данных не узнано. +Сверка документов: с прошлой (a1b2c3d, 2026-07-30) сделано 11 задач — пора +звать av-dev:doc-healthcheck. ``` ## Сверка — не здесь, а в `av-dev:doc-healthcheck` @@ -118,9 +170,16 @@ description: Вести содержимое документов канона нет**. Строка «adr/ — не требуется: решение рутинное» и есть то, ради чего чек-лист существует; её отсутствие неотличимо от «забыл посмотреть». -Порядок работы: открой источник — архивный `design.md` change либо записку -разведки, — найди в нём решение, проходящее триггер, процитируй его и причину, -сошлись на источник, добавь строку в индекс `docs/adr/README.md` сверху. +**Запись — новое, и заводится она по слову** (раздел «Два рода правок»). +Сработавший триггер даёт не файл, а строку предложения: какое решение, из какого +источника, каким из трёх триггеров прошло. Своей записи ADR не стоит ничего, а +каталог решений читают как список того, что в проекте всерьёз, — и разбавленный +рутиной он перестаёт им быть. + +Порядок работы после «да»: открой источник — архивный `design.md` change либо +записку разведки, — найди в нём решение, проходящее триггер, процитируй его и +причину, сошлись на источник, добавь строку в индекс `docs/adr/README.md` +сверху. ## Чистка `architecture.md` @@ -197,9 +256,16 @@ av-dev:code-review`, его `references/review-journal.md`. Твоя часть на синке: **дефект пишется сразу**, а не «потом, когда починим». Со временем теряется не факт, а то, почему дефект не поймали, — единственное, -ради чего журнал есть. И решение сузить проверки (перестали звать проход, -переселили его в другой скилл) обязано попасть в раздел настройки, а не остаться -в отчёте ревью. +ради чего журнал есть. + +«Сразу» и «по слову» здесь не спорят: запись — новое, и она идёт предложением, но +**предложением этого прогона**, а не следующего. Отложить её до «когда починим» +нельзя ни с чьего согласия: чинится дефект, а теряется причина промаха. + +**Решение сузить проверки** (перестали звать проход, переселили его в другой +скилл) обязано попасть в раздел настройки, а не остаться в отчёте ревью. Второй +раз оно не спрашивается: такое решение принимает человек по определению, и слово +по нему уже сказано — сказано тогда, когда проверку сузили. ## Промоут в конвенции @@ -216,6 +282,53 @@ av-dev:code-review`, его `references/review-journal.md`. На синке это отдельная строка: «conventions/ — правило X механизировано, формулировка удалена» либо «не требуется». +**Конвенция — самое дорогое из нового, и на синке она только предлагается.** +Одна её строка становится входом каждого следующего прогона ревью и критерием +для всех будущих задач; находка, доехавшая до конвенции по инерции хвоста, потом +годами разменивается на внимание прохода. Предложение называет **проверяемое +свойство и проход, который его нашёл**, — по этой паре человек и решает. + +**Шаг 2 в хвост задачи не помещается.** Механизация правила — конфиг линтера или +сканер, плюс приведение кода к зелёному — это работа размером с задачу, и делать +её попутно значит удваивать чужой прогон. Согласованный промоут даёт строку +конвенции сейчас и **задачу типа `chore`** на механизацию — заводит её +`av-dev:task-track`, и заводится она тем же словом человека, что и сама +конвенция. + +## Сигнал сверки — строка, а не вызов + +Сверку документов (`av-dev:doc-healthcheck`) зовёт человек по признаку **«с +прошлой сверки сделан десяток задач»**. Признак наблюдаемый, но считать его было +нечем: следа у сверки не оставалось, и «десяток» держался в чьей-то памяти. Это +ровно тот прозаический триггер, который дал 6 записей ADR на 43 изменения, — и +здесь он не срабатывал по той же причине. + +**След оставляет сама сверка** — ключ `[healthcheck] last` в `.av-dev.toml` +(состав ключей — [canon.md](../canon/references/canon.md), раздел +`.av-dev.toml`). **Считает синк**, и вот чем: + +```sh +git rev-list --count ..HEAD -- openspec/changes/archive +``` + +Коммит, тронувший архив, — это доехавшая до конца задача, так что счёт идёт в +задачах, а не в правках. `openspec` в проекте нет — считай коммиты +(`git rev-list --count ..HEAD`) и **скажи, что считал коммиты**: число +другого рода, и молчаливая подмена сделала бы признак вдвое чувствительнее. + +Строка доклада обязательна всегда, и вариантов у неё три: + +- **счёт меньше десятка** — «с прошлой сверки N задач, звать рано»; +- **счёт от десятка** — «с прошлой сверки N задач, пора звать + `av-dev:doc-healthcheck`»; +- **ключа нет** — «сверка документов не проводилась ни разу», и это самый + сильный из трёх сигналов, а не отсутствие данных. + +**Сам не зовёшь.** Прогон сверки идёт по всему канону и держит `opus`; решение о +таких часах принимает тот, кто их оплачивает. Синк, позвавший её сам, превратил +бы самую дорогую проверку процесса в церемонию хвоста задачи — против чего она и +вынесена в отдельный скилл. + ## Чего этот скилл не делает - **Не проверяет раскладку** — это `canon`. @@ -223,3 +336,6 @@ av-dev:code-review`, его `references/review-journal.md`. `doc-init`. - **Не сочиняет содержание.** Нечего записать — так и пишется, честной строкой. - **Не переоформляет документы «заодно»**: правится то, чего коснулась работа. +- **Не заводит новое молча** — ни ADR, ни конвенцию, ни записку. Молча идёт + только отражение, и признак у него один: без правки документ станет ложным. +- **Не зовёт сверку документов** — считает и говорит строкой; зовёт человек. diff --git a/decisions/78-tail-reflection-silent-new-by-word.md b/decisions/78-tail-reflection-silent-new-by-word.md new file mode 100644 index 0000000..672aa6d --- /dev/null +++ b/decisions/78-tail-reflection-silent-new-by-word.md @@ -0,0 +1,112 @@ +# 78. Хвост задачи: отражение молча, новое — по слову (2026-08-23) + +## Что было + +Тема 77 привела ревью в соответствие с ролью агента: цикл проверяет корректность +и механику, а суждение о замысле стоит там, где решает человек. **Хвост задачи +остался прежним.** + +Шаг 6 писал в документы сам. Синк шёл по чек-листу из десяти строк с +принуждённым отрицанием и по сработавшему триггеру заводил ADR, промоутил находку +в конвенцию, писал в `research/`, `security.md`, `CLAUDE.md`, журнал дефектов. +Человек узнавал об этом **постфактум** — строками чек-листа в докладе, который +читают последним и по диагонали. Задачи из урожая ревью к этому времени уже +заводились по слову (Р307), а документы — нет: одна и та же работа, «что из +найденного переживёт задачу», решалась в двух разных режимах. + +Вопросов при этом выходило два — про урожай на шаге 5 и про документы на шаге 6, +— то есть два переключения человека там, где решение одно. + +Отдельно стояла **сверка документов**. `av-dev:doc-healthcheck` зовут по +наблюдаемому признаку «с прошлой сверки сделан десяток задач», но следа сверка не +оставляла и задачи с тех пор не считал никто. Это ровно тот прозаический триггер, +измеренная цена которого записана в самом же синке: у ADR такой триггер дал **6 +записей на 43 изменения**. + +## Решено + +**Р311. Правки в документы разделены по роду, и спрашивается один род.** Признак +проверяемый: **что станет с документом, если правку не сделать**. Станет ложным — +это **отражение**, и оно пишется молча. Появится запись или норма, которой не +было, — это **новое**, и оно пишется только по слову человека. + +**Р312. Отражение — документы, описывающие состояние системы.** Это +`openspec/specs/`, `database.md` и `architecture.md`. Остальной чек-лист — новое: +`adr/`, `conventions/`, `research/`, `security.md`, `passport.md`, `CLAUDE.md` и +журнал `review.md` задают норму или хранят память, и разойтись им не с чем, пока +в них не написано новое. + +**Р313. Реплика человеку одна на весь хвост.** В ней и предложения синка, и +урожай ревью; вопрос про урожай перенесён с шага 5 на шаг 6. Нового нет — +реплики нет, и у большинства задач так и выходит. + +**Р314. Шаг 6 идёт в три такта, агент запускается в нём дважды.** Первый такт — +`opsx:archive` и отражение; второй — реплика; третий — письмо одобренного и +задачи из урожая. Вычитку `doc-wording` зовёт `av-dev:doc-sync` **последним +тактом, в котором писал**: вернул непустой список предложений — вычитка ждёт +третьего такта, список пуст — идёт в первом. + +**Р315. Конвенция — самое дорогое из нового, и в хвосте она только +предлагается.** Её строка становится входом каждого следующего прогона ревью. +Механизация правила (шаг 2 промоута: конфиг, сканер, приведение кода к зелёному) +в хвост чужой задачи не помещается вовсе — это задача `chore`, заводимая тем же +словом, что и сама конвенция. + +**Р316. Отвергнутое не пишется никуда.** Ни в один документ, ни отдельной +записью «от такого-то отказались»: журнала отвергнутого канон не держит, и +заведение его было бы ровно тем новым, которого человек только что не заказал. +Отказ идёт строкой доклада. + +**Р317. «По слову» — это по слову, а не вторым вопросом.** Сказанное человеком в +этом же прогоне повторно не спрашивается: решение сузить проверки принимает он по +определению, ответ разведки одобрен чекпоинтом вариантов, прямая просьба «заведи +ADR» и есть слово. Предложение существует ради нового, которое заметил агент. + +**Р318. Сверка документов оставляет след, а синк его считает.** След — ключ +`[healthcheck] last` в `.av-dev.toml`, хеш коммита прошлого прогона; ставит его +`av-dev:doc-healthcheck` последним шагом. Счёт — `git rev-list --count +..HEAD -- openspec/changes/archive`, то есть в задачах, доехавших до архива; +без openspec считаются коммиты, и это говорится вслух. Строка доклада +обязательна всегда, вариантов три: рано, пора, не сверялись ни разу. **Синк +сверку не зовёт** — часы на неё тратит тот, кто их оплачивает. + +## Следствия + +**С275. Плановых стопов в сценарии решения два, и оба про решения человека.** +Чекпоинт шага 3 решает форму решения до кода, реплика шага 6 — что из найденного +переживёт задачу. Между ними прогон идёт сам: инлайн чинится молча, отражение +пишется молча. Третий стоп заводить нельзя — прогон, останавливающийся чаще, +теряет то время, ради которого выбраны короткие итерации. + +**С276. Принуждённое отрицание сменило адресата, но не ослабло.** Каждый документ +канона по-прежнему назван — правкой, предложением или отрицанием с причиной; +изменилось то, что отрицание читает человек и читает его **до** того, как +что-нибудь написано. + +**С277. Сценарий обслуживания почти не спрашивает.** Он двигает факты — команды, +шаги гейта, зависимости поимённо, пути, числа настроек, — а факт, разошедшийся с +кодом, это отражение по определению. Поводов для реплики у него два: новый запрет +в `CLAUDE.md` и сужение проверок в `review.*`, причём второе не спрашивается по +Р317. + +**С278. Признак «десяток задач» стал числом.** Ключ `.av-dev.toml` +необязательный и заводится сам первым же прогоном сверки, поэтому версия +раскладки не двигается и `upgrade` проектам не нужен. Отсутствие ключа читается +однозначно: не сверялись ни разу. + +**С279. Журнал дефектов теперь зависит от ответа человека.** Запись +воспроизведённого дефекта — новое, и молчаливого «да» у неё больше нет. Правило +«пишется сразу» сохранено в другом виде: предложение делается **этим** прогоном, +отложить его до «когда починим» нельзя ни с чьего согласия. Но человек вправе +отказать, и тогда калибровка конвейера по этому дефекту не состоится — цена +названа здесь, а не подразумевается. + +**С280. Отказ нигде не хранится, и похожее предложение придёт снова.** Это прямое +следствие Р316 и сознательный размен: журнал отвергнутого сам стал бы каноном, +который никто не заказывал. В `av-dev:code-deep-review` разбор устроен иначе — +там отказ уезжает в `docs/review.md`, потому что прогон затевается ради разговора +и его исход и есть артефакт. + +**С281. Хвост подорожал только на задачах, где что-то заводится.** Второй запуск +агента идёт лишь после непустой реплики; задача без нового кончается первым +тактом, и по цене хвост у неё прежний. diff --git a/decisions/README.md b/decisions/README.md index b4a0dc9..5087629 100644 --- a/decisions/README.md +++ b/decisions/README.md @@ -129,3 +129,4 @@ | 75 | [Хвост задачи — один агент: архивация и синк вместе](75-tail-in-one-agent.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 | +| 78 | [Хвост задачи: отражение молча, новое — по слову](78-tail-reflection-silent-new-by-word.md) | 2026-08-23 |