границы плагинов: путь в чужое дерево, безымянные стыки, звонящий у вычитки
Правило границы моё, копий восемь — и нарушал его я же. - путь в дерево чужого плагина снят из пяти мест; маркер копии, уезжающий в проект скелетом, оставлен, но сказано, что сама пара маркеров не едет - короткое имя чужого скилла в четырёх местах стало полным - стык «урожай ревью → задачи» не был назван ни с одной стороны, хотя механика написана с обеих; теперь назван, с веткой «плагина нет» - resolve звал av-dev-git:commit без строки доклада и пересказывал формат коммита, нарушая собственное «ссылайся, не пересказывай» - doc-wording обещал момент вызова, которого не исполнял никто. Правило: звонящий — тот, кто только что писал текст. Вызов появился шагом в docs, init, adopt и upgrade; healthcheck по-прежнему его не зовёт - openspec.py искал SHALL по всему файлу, а образец даёт его в context — проверка молчала ровно в том случае, ради которого написана - фаза 2 review-rubric была недостижима; проход стал судить задуманное, а не код, и это сходится с тем, что о нём говорит конвейер - rules.tasks в образце конфига, ветка «записи задачи нет» у review-scope, возвраты на чекпоинт в схеме resolve, старшинство правила дельта-спек Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: review-adversary
|
name: review-adversary
|
||||||
description: "Враждебный проход ревью — не проверяет свойства, а строит путь: «ты контролируешь вход целиком — выведи запись за пределы песочницы»; «ты шлёшь запрос и хочешь, чтобы данные не доехали или испортились — построй такой вход»; «ты можешь повторить и переставить любую операцию — что ломается»; «доведи чувствительное до места, где его быть не должно». Находка — построенный путь с шагами, а не наблюдение. Свойства без пути идут в отдельную секцию и не получают critical. Модель угроз берётся из docs/security.md проекта. Только чтение."
|
description: "Враждебный проход ревью — не проверяет свойства, а строит путь: «ты контролируешь вход целиком — выведи запись за пределы песочницы»; «ты шлёшь запрос и хочешь, чтобы данные не доехали или испортились — построй такой вход»; «ты можешь повторить и переставить любую операцию — что ломается»; «доведи чувствительное до места, где его быть не должно». Находка — построенный путь с шагами, а не наблюдение. Свойства без пути идут в отдельную секцию и не получают critical. Модель угроз берётся из docs/security.md проекта. Запускается только с меткой large — на изменении, которое не крупное и не незнакомое, построенного пути он не находит, а стоит дорого. Только чтение."
|
||||||
tools: Read, Grep, Glob, Bash
|
tools: Read, Grep, Glob, Bash
|
||||||
model: opus
|
model: opus
|
||||||
color: yellow
|
color: yellow
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ color: green
|
|||||||
просило: она может стоить минут и трогать данные.
|
просило: она может стоить минут и трогать данные.
|
||||||
- **Правило есть в конвенциях, но не в линтере.** Если по ходу видно, что отказ
|
- **Правило есть в конвенциях, но не в линтере.** Если по ходу видно, что отказ
|
||||||
или замечание могло быть поймано правилом, — пиши `Promote candidate` по
|
или замечание могло быть поймано правилом, — пиши `Promote candidate` по
|
||||||
процедуре `references/promote.md`.
|
процедуре `${CLAUDE_PLUGIN_ROOT}/skills/review/references/promote.md`.
|
||||||
|
|
||||||
## Что читать не нужно
|
## Что читать не нужно
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: review-ops
|
name: review-ops
|
||||||
description: "Эксплуатационный проход ревью — пишет постмортем «это упало через неделю на проде» от симптома у владельца сервиса к строке кода. Обязательные вопросы: рост объёма, деградация окружения и внешних зависимостей, повторная и одновременная операция, частичный откат при двух версиях, миграция под живым потоком, отмена контекста на середине, наблюдаемость и тишина, поведение библиотеки и драйвера в вырожденном случае, чтение узлом состояния, которое он сам же меняет. Формулирует условиями, а не утверждениями — реального профиля нагрузки не знает. Только чтение."
|
description: "Эксплуатационный проход ревью — пишет постмортем «это упало через неделю на проде» от симптома у владельца сервиса к строке кода. Обязательные вопросы: рост объёма, деградация окружения и внешних зависимостей, повторная и одновременная операция, частичный откат при двух версиях, миграция под живым потоком, отмена контекста на середине, наблюдаемость и тишина, поведение библиотеки и драйвера в вырожденном случае, чтение узлом состояния, которое он сам же меняет. Формулирует условиями, а не утверждениями — реального профиля нагрузки не знает. Запускается только с меткой large: постмортем на малом знакомом изменении пишется по общей практике, а не по этому проекту. Только чтение."
|
||||||
tools: Read, Grep, Glob, Bash
|
tools: Read, Grep, Glob, Bash
|
||||||
model: sonnet
|
model: sonnet
|
||||||
color: green
|
color: green
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: review-rubric
|
name: review-rubric
|
||||||
description: "Generative-проход ревью — сперва, НЕ ВИДЯ КОДА, порождает 8–12 проверяемых свойств, по которым сильный инженер судит узел такого назначения (парсер входного формата, HTTP-обработчик, репозиторий, воркер, клиент внешнего сервиса, CLI-команда, файловое хранилище), и только потом читает код и оценивает по этой рубрике. Достаёт слой, которого нет ни в одной конвенции. Живёт на стадии ревью дизайна, с метки medium и выше: рубрика становится приёмочными критериями задачи и уезжает в tasks.md. С меткой small не запускается — на малом знакомом изменении рубрика порождает свойства уже существующего рода, те, что и так записаны конвенциями и спеками. Только чтение."
|
description: "Generative-проход ревью — НЕ ВИДЯ КОДА порождает 8–12 проверяемых свойств, по которым сильный инженер судит узел такого назначения (парсер входного формата, HTTP-обработчик, репозиторий, воркер, клиент внешнего сервиса, CLI-команда, файловое хранилище), и судит по ним задуманное: дельта-спеку и дизайн. Достаёт слой, которого нет ни в одной конвенции. Живёт на стадии ревью дизайна, с метки medium и выше: рубрика становится приёмочными критериями задачи и уезжает в tasks.md. Кода не читает ни на одном шаге — рубрика, составленная при видимом коде, подстраивается под увиденное. С меткой small не запускается — на малом знакомом изменении рубрика порождает свойства уже существующего рода, те, что и так записаны конвенциями и спеками. Только чтение."
|
||||||
tools: Read, Grep, Glob, Bash
|
tools: Read, Grep, Glob, Bash
|
||||||
model: opus
|
model: opus
|
||||||
color: yellow
|
color: yellow
|
||||||
@@ -31,13 +31,11 @@ color: yellow
|
|||||||
**Документа нет — строка на каждый, отдельно.** Нет `docs/review.md`: «рода
|
**Документа нет — строка на каждый, отдельно.** Нет `docs/review.md`: «рода
|
||||||
узлов и прецеденты неизвестны; требование „минимум три пункта специфичны для
|
узлов и прецеденты неизвестны; требование „минимум три пункта специфичны для
|
||||||
типа узла" выполнено по общей практике, а не по этому проекту». Нет инвариантов
|
типа узла" выполнено по общей практике, а не по этому проекту». Нет инвариантов
|
||||||
в `CLAUDE.md`: `critical` по основанию «нарушен инвариант проекта» в фазе 2 не
|
в `CLAUDE.md`: `critical` по основанию «нарушен инвариант проекта» не присваивай
|
||||||
присваивай и скажи об этом. Одной строкой за два документа не отделывайся —
|
и скажи об этом. Одной строкой за два документа не отделывайся — чинятся они
|
||||||
чинятся они разным.
|
разным.
|
||||||
|
|
||||||
## Порядок фаз обязателен
|
## Рубрика. Код читать ЗАПРЕЩЕНО
|
||||||
|
|
||||||
### Фаза 1 — рубрика. Код читать ЗАПРЕЩЕНО
|
|
||||||
|
|
||||||
Тебе дают только: назначение узла (одна-две фразы), его тип, сигнатуры на входе и
|
Тебе дают только: назначение узла (одна-две фразы), его тип, сигнатуры на входе и
|
||||||
выходе, соответствующие требования из дельта-спеки. **Не открывай файлы
|
выходе, соответствующие требования из дельта-спеки. **Не открывай файлы
|
||||||
@@ -86,28 +84,29 @@ color: yellow
|
|||||||
Тот же вопрос на **готовом коде** задаёт эксплуатационный проход
|
Тот же вопрос на **готовом коде** задаёт эксплуатационный проход
|
||||||
(вопрос 9); здесь он задаётся дизайну.
|
(вопрос 9); здесь он задаётся дизайну.
|
||||||
|
|
||||||
Выведи рубрику **до** любых находок. Она — часть результата, даже если код
|
Выведи рубрику **до** любых находок. Она — часть результата, даже если
|
||||||
окажется идеальным.
|
задуманное окажется безупречным.
|
||||||
|
|
||||||
### Фаза 2 — оценка
|
## По рубрике судится задуманное, а не код
|
||||||
|
|
||||||
Выполняется только если тебя позвали на готовый код (вне стадии ревью дизайна).
|
Пройди рубрику против **дельта-спеки и дизайна**. Находка — там, где задуманное
|
||||||
Читай код и оцени **по каждому пункту рубрики**: соблюдено / нарушено /
|
пункту прямо противоречит либо оставляет его неопределённым в месте, где
|
||||||
неприменимо, с файлом и строкой.
|
определённость обязательна («что происходит при перекрытии тиков» не сказано ни
|
||||||
|
в спеке, ни в дизайне). Остальные пункты уезжают приёмочными критериями в
|
||||||
|
`tasks.md` change: там их и проверит приёмка.
|
||||||
|
|
||||||
**Новые критерии на этой фазе не добавляются.** Если по ходу чтения возник
|
**Оценки кода у этого прохода нет, и это решение, а не пробел.** Судить код по
|
||||||
критерий, которого не было в рубрике, — вынеси его в отдельную секцию «Появилось
|
критерию, под который он писался, — корреляция по построению, и потому проход
|
||||||
при чтении кода» и пометь `Confidence: low`: он подстроен под увиденное и потому
|
живёт только на стадии ревью дизайна, где кода ещё нет. Позвали на готовый
|
||||||
слабее.
|
код — это ошибка вызова: скажи об этом строкой и рубрику всё равно не подгоняй
|
||||||
|
под увиденное.
|
||||||
|
|
||||||
## Что делать с рубрикой дальше
|
## Что делать с рубрикой дальше
|
||||||
|
|
||||||
Пункты рубрики, которых **нет в конвенциях проекта**, — кандидаты на промоут: это
|
Пункты рубрики, которых **нет в конвенциях проекта**, — кандидаты на промоут: это
|
||||||
и есть неявный слой, ради которого проход существует. Выведи их отдельной секцией
|
и есть неявный слой, ради которого проход существует. Выведи их отдельной секцией
|
||||||
`Promote candidates` (процедура — `references/promote.md`).
|
`Promote candidates` (процедура —
|
||||||
|
`${CLAUDE_PLUGIN_ROOT}/skills/review/references/promote.md`).
|
||||||
На стадии ревью дизайна (кода ещё нет) фаза 2 не выполняется: рубрика уезжает в
|
|
||||||
`tasks.md` change как приёмочные критерии.
|
|
||||||
|
|
||||||
## Чего этот проход принципиально не может поймать
|
## Чего этот проход принципиально не может поймать
|
||||||
|
|
||||||
@@ -122,22 +121,21 @@ color: yellow
|
|||||||
|
|
||||||
## Формат вывода
|
## Формат вывода
|
||||||
|
|
||||||
1. `## Рубрика` — нумерованный список свойств (порождена до чтения кода).
|
1. `## Рубрика` — нумерованный список свойств (порождена до чтения спеки).
|
||||||
2. `## Оценка` — по каждому пункту: соблюдено/нарушено/неприменимо + файл:строка
|
2. `## Разбор` — по каждому пункту: покрыт задуманным / противоречие /
|
||||||
(только вне стадии ревью дизайна).
|
не определён / неприменим, со ссылкой на требование или раздел дизайна.
|
||||||
3. Находки по контракту — только по нарушенным пунктам.
|
3. Находки по контракту — только по пунктам с противоречием и неопределённостью.
|
||||||
4. `## Появилось при чтении кода` — если было.
|
4. `## Promote candidates`.
|
||||||
5. `## Promote candidates`.
|
5. Обязательный блок:
|
||||||
6. Обязательный блок:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
## Coverage of this pass
|
## Coverage of this pass
|
||||||
- проверено: <какие пункты рубрики против каких файлов>
|
- проверено: <какие пункты рубрики против каких требований и разделов дизайна>
|
||||||
- не проверялось и почему: ...
|
- не проверялось и почему: ...
|
||||||
- принципиально недоступно этому проходу: рантайм, сверка со спекой, межмодульные связи
|
- принципиально недоступно этому проходу: код, рантайм, сверка со спекой, межмодульные связи
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ограничения
|
## Ограничения
|
||||||
|
|
||||||
Только чтение. В фазе 1 — не читать реализацию вообще; если задание не дало
|
Только чтение, и реализацию не читать вообще; если задание не дало назначения и
|
||||||
назначения и сигнатур, попроси их, а не иди смотреть код сам.
|
сигнатур, попроси их, а не иди смотреть код сам.
|
||||||
|
|||||||
@@ -74,6 +74,15 @@ color: green
|
|||||||
| **`tasks.md`** | число шагов и их разнородность: шаги, лежащие в разных узлах и слоях | шаг вида «разобраться», «выяснить», «попробовать» |
|
| **`tasks.md`** | число шагов и их разнородность: шаги, лежащие в разных узлах и слоях | шаг вида «разобраться», «выяснить», «попробовать» |
|
||||||
| **дельта-спеки** | сколько capability затронуто и сколько требований в каждой | `ADDED` целой capability — поведения такого рода не было; только `MODIFIED` в одной — было |
|
| **дельта-спеки** | сколько capability затронуто и сколько требований в каждой | `ADDED` целой capability — поведения такого рода не было; только `MODIFIED` в одной — было |
|
||||||
|
|
||||||
|
**Записи задачи может не быть вовсе, и это не довод за незнакомое.** Задача
|
||||||
|
приходит текстом или из проекта без плагина задач — тогда раздела «Затрагивает»
|
||||||
|
нет **по построению**, а не потому, что границы не назвали. Отличай:
|
||||||
|
запись есть, а раздела в ней нет → незнакомое, как сказано в таблице; записи нет
|
||||||
|
→ строка источника снимается, обе оси выводятся из остальных четырёх, и это
|
||||||
|
называется в плане строкой «записи задачи нет, оси выведены по четырём
|
||||||
|
источникам». Иначе всякая задача без плагина задач систематически едет в `large`
|
||||||
|
за то, чего никто не терял.
|
||||||
|
|
||||||
**`design.md` информативен и своим отсутствием.** Его нет — либо задача
|
**`design.md` информативен и своим отсутствием.** Его нет — либо задача
|
||||||
тривиальна (тогда это подтверждает малое и знакомое), либо нетривиальную завели
|
тривиальна (тогда это подтверждает малое и знакомое), либо нетривиальную завели
|
||||||
без разбора решения, и тогда «форму знали заранее» ничем не подтверждено: считай
|
без разбора решения, и тогда «форму знали заранее» ничем не подтверждено: считай
|
||||||
|
|||||||
@@ -78,11 +78,14 @@ python3 $os form # слепок формы против жив
|
|||||||
Различать 1 и 3 обязательно: «форма разошлась» — рабочая ситуация, «openspec не
|
Различать 1 и 3 обязательно: «форма разошлась» — рабочая ситуация, «openspec не
|
||||||
отвечает» — нерабочая.
|
отвечает» — нерабочая.
|
||||||
|
|
||||||
`check` проверяет пять вещей, и каждая — про молчащий пробел, а не про вкус:
|
`check` проверяет форму, и каждая проверка — про молчащий пробел, а не про вкус:
|
||||||
каталог есть; имя именно `config.yaml` (`config.yml` OpenSpec не читает и об этом
|
каталог есть; имя именно `config.yaml` (`config.yml` OpenSpec не читает и об этом
|
||||||
не сообщает); `context` и `rules.specs` не остались примером, а правила называют
|
не сообщает); ключ `schema` называет ту схему, для которой форма описана;
|
||||||
`SHALL`; `context` называет паспорт и `CLAUDE.md`; ключи под `rules:` — имена
|
`context` и `rules.specs` не остались примером, **а `SHALL` назван именно внутри
|
||||||
артефактов схемы, а не свободные слова.
|
`rules.specs`** (в `context` он стоит и в образце, поэтому греп по файлу здесь
|
||||||
|
ничего не значит); `context` называет паспорт и `CLAUDE.md`; ключи под `rules:` —
|
||||||
|
имена артефактов схемы, а не свободные слова. Числа проверок здесь нет намеренно:
|
||||||
|
оно протухает от каждой добавленной.
|
||||||
|
|
||||||
**Адреса требуются только к тем документам, которые в проекте есть.** Канон
|
**Адреса требуются только к тем документам, которые в проекте есть.** Канон
|
||||||
документов ставится отдельным плагином и может быть не подключён; требовать
|
документов ставится отдельным плагином и может быть не подключён; требовать
|
||||||
@@ -116,6 +119,9 @@ python3 $os form # слепок формы против жив
|
|||||||
- `av-dev-docs:init` — шагом заведения нового проекта, до первого документа;
|
- `av-dev-docs:init` — шагом заведения нового проекта, до первого документа;
|
||||||
- `av-dev-docs:canon` в режиме `adopt` — если на переводимом проекте каталога нет
|
- `av-dev-docs:canon` в режиме `adopt` — если на переводимом проекте каталога нет
|
||||||
или `config.yaml` остался примером;
|
или `config.yaml` остался примером;
|
||||||
|
- `av-dev-code:resolve` и `av-dev-code:review` — не вызовом по ходу, а отсылкой:
|
||||||
|
OpenSpec у обоих жёсткая предпосылка, и на проекте без каталога оба посылают
|
||||||
|
сюда вместо того, чтобы заводить его руками;
|
||||||
- человек — когда конвейер отказался работать без источника требований.
|
- человек — когда конвейер отказался работать без источника требований.
|
||||||
|
|
||||||
**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов.
|
**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов.
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ rules:
|
|||||||
- "Сценарий — ровно #### (четыре решётки); три или список молча теряются"
|
- "Сценарий — ровно #### (четыре решётки); три или список молча теряются"
|
||||||
- "SHALL/MUST должно стоять в ПЕРВОМ абзаце требования: валидатор смотрит только его"
|
- "SHALL/MUST должно стоять в ПЕРВОМ абзаце требования: валидатор смотрит только его"
|
||||||
- "Заголовки и WHEN/THEN/GIVEN — на английском, остальной текст на русском"
|
- "Заголовки и WHEN/THEN/GIVEN — на английском, остальной текст на русском"
|
||||||
|
tasks:
|
||||||
|
- "Критерии приёмки задачи — отдельным блоком и дословно: файл задачи закрытие удалит, критерии обязаны его пережить"
|
||||||
|
- "Рубрика ревью дизайна, если оно её дало, идёт в тот же блок: приёмка судится по одному списку, а не по двум"
|
||||||
|
- "Шаг плана формулируется проверяемо — по нему видно «сделано / не сделано» без суждения"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Четыре правила для `specs` сняты отказами валидатора, а не выведены из
|
**Четыре правила для `specs` сняты отказами валидатора, а не выведены из
|
||||||
@@ -79,7 +83,14 @@ rules:
|
|||||||
артефактов**, а не сочиняется заново: третий пересказ одного и того же разошёлся
|
артефактов**, а не сочиняется заново: третий пересказ одного и того же разошёлся
|
||||||
бы с обоими. Требование поэтому стоит здесь, в момент порождения артефакта, а не
|
бы с обоими. Требование поэтому стоит здесь, в момент порождения артефакта, а не
|
||||||
в скилле, который спохватится позже. `design.md` при этом ещё и **сырьё для
|
в скилле, который спохватится позже. `design.md` при этом ещё и **сырьё для
|
||||||
ADR** — отвергнутый вариант с названной причиной и есть половина будущей записи. Блок `context` проект
|
ADR** — отвергнутый вариант с названной причиной и есть половина будущей записи.
|
||||||
|
|
||||||
|
**Правила для `tasks` держит тот же скилл, и по той же причине — момент
|
||||||
|
порождения.** `tasks.md` — единственное, что переживает задачу: файл задачи
|
||||||
|
закрытие удаляет, а приёмка потом судится по критериям, которые в него
|
||||||
|
скопированы. Туда же ложится рубрика ревью дизайна, если оно её дало. Записанное
|
||||||
|
в момент порождения не приходится вспоминать шагом позже, когда артефакт уже
|
||||||
|
написан. Блок `context` проект
|
||||||
дополняет своим (стек, разведка, особенности домена), но **адреса паспорта и
|
дополняет своим (стек, разведка, особенности домена), но **адреса паспорта и
|
||||||
`CLAUDE.md` обязательны** — отсутствие адреса к существующему документу
|
`CLAUDE.md` обязательны** — отсутствие адреса к существующему документу
|
||||||
`openspec.py check` называет отказом.
|
`openspec.py check` называет отказом.
|
||||||
|
|||||||
@@ -134,6 +134,35 @@ def rules_keys(live: str) -> list[str]:
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def rules_block(live: str, name: str) -> str:
|
||||||
|
"""Строки правил, адресованных одному артефакту.
|
||||||
|
|
||||||
|
Обход тот же, что у `rules_keys`, и по той же причине: искать по всему файлу
|
||||||
|
нельзя. Литеральный скаляр `context` называет `SHALL` уже в образце, поэтому
|
||||||
|
проверка «правила называют SHALL» грепом по файлу проходила при **пустом**
|
||||||
|
`rules.specs` — то есть молчала ровно в том случае, ради которого написана.
|
||||||
|
"""
|
||||||
|
out: list[str] = []
|
||||||
|
in_rules = False
|
||||||
|
in_name = False
|
||||||
|
for line in live.splitlines():
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
if not line[0].isspace():
|
||||||
|
in_rules = line.startswith("rules:")
|
||||||
|
in_name = False
|
||||||
|
continue
|
||||||
|
if not in_rules:
|
||||||
|
continue
|
||||||
|
m = re.fullmatch(r" ([A-Za-z_-]+):\s*", line)
|
||||||
|
if m:
|
||||||
|
in_name = m.group(1) == name
|
||||||
|
continue
|
||||||
|
if in_name:
|
||||||
|
out.append(line)
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
def check_form(root: Path, rep: Report) -> None:
|
def check_form(root: Path, rep: Report) -> None:
|
||||||
"""Настройка заведена и не осталась примером из коробки."""
|
"""Настройка заведена и не осталась примером из коробки."""
|
||||||
os_dir = root / "openspec"
|
os_dir = root / "openspec"
|
||||||
@@ -197,12 +226,12 @@ def check_form(root: Path, rep: Report) -> None:
|
|||||||
if pointer not in live:
|
if pointer not in live:
|
||||||
rep.error(f"openspec/config.yaml не называет {pointer} — {why}")
|
rep.error(f"openspec/config.yaml не называет {pointer} — {why}")
|
||||||
|
|
||||||
if "rules" not in keys or "specs:" not in live:
|
if "rules" not in keys or "specs" not in rules_keys(live):
|
||||||
rep.error(
|
rep.error(
|
||||||
"в openspec/config.yaml нет rules.specs — придирки валидатора "
|
"в openspec/config.yaml нет rules.specs — придирки валидатора "
|
||||||
"нигде не записаны, и каждое предложение узнаёт их отказом"
|
"нигде не записаны, и каждое предложение узнаёт их отказом"
|
||||||
)
|
)
|
||||||
elif "SHALL" not in live:
|
elif "SHALL" not in rules_block(live, "specs"):
|
||||||
rep.error(
|
rep.error(
|
||||||
"rules.specs в openspec/config.yaml не называет SHALL — "
|
"rules.specs в openspec/config.yaml не называет SHALL — "
|
||||||
"требование без этого литерала валидатор отвергает, а правило "
|
"требование без этого литерала валидатор отвергает, а правило "
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ description: "Решить одну задачу от постановки до
|
|||||||
## Предпосылки
|
## Предпосылки
|
||||||
|
|
||||||
- **OpenSpec и скиллы `opsx:*` — жёсткая предпосылка, а не опция.** На них стоят
|
- **OpenSpec и скиллы `opsx:*` — жёсткая предпосылка, а не опция.** На них стоят
|
||||||
шаги 2, 6 и 8, проход `review-specs` и ревью дизайна (они завязаны на
|
шаги 2, 6 и 8, шаг Р2 разведки, проход `review-specs` и ревью дизайна (они
|
||||||
`openspec/changes/<id>/specs/*/spec.md` и на `openspec validate --strict`).
|
завязаны на `openspec/changes/<id>/specs/*/spec.md` и на
|
||||||
**Проект без OpenSpec этим скиллом не ведётся** — подключай OpenSpec, а не
|
`openspec validate --strict`). **Проект без OpenSpec этим скиллом не ведётся** —
|
||||||
вырождай цикл: ветка деградации здесь не пишется, потому что непроверенная
|
подключай OpenSpec, а не вырождай цикл: ветка деградации здесь не пишется,
|
||||||
ветка деградации хуже честного отказа.
|
потому что непроверенная ветка деградации хуже честного отказа. Заводить
|
||||||
|
руками не надо: каталог и настройку в `config.yaml` делает скилл
|
||||||
|
`av-dev-code:openspec`.
|
||||||
- **Проектные копии этих скиллов и агентов удаляются при установке плагина**
|
- **Проектные копии этих скиллов и агентов удаляются при установке плагина**
|
||||||
(`.claude/skills/` — голые имена `resolve`, `review`, а у проектов прошлого
|
(`.claude/skills/` — голые имена `resolve`, `review`, а у проектов прошлого
|
||||||
поколения ещё `task-pipeline`, `review-pipeline`, `task-batch`, и с префиксом
|
поколения ещё `task-pipeline`, `review-pipeline`, `task-batch`, и с префиксом
|
||||||
@@ -136,7 +138,8 @@ flowchart TD
|
|||||||
r3 -.->|"кода не будет"| rout
|
r3 -.->|"кода не будет"| rout
|
||||||
s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10 --> s11
|
s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10 --> s11
|
||||||
s3 -.->|"план задачи: та же метка"| s7
|
s3 -.->|"план задачи: та же метка"| s7
|
||||||
s7 -.->|"находка отменяет дизайн"| s5
|
s5 -.->|"скорректировать:<br/>меняются дельта-спеки"| s3
|
||||||
|
s7 -.->|"находка отменяет дизайн:<br/>меняются дельта-спеки"| s3
|
||||||
```
|
```
|
||||||
|
|
||||||
Схема — **сводка**: содержание каждого шага в его разделе ниже, и при
|
Схема — **сводка**: содержание каждого шага в его разделе ниже, и при
|
||||||
@@ -213,7 +216,9 @@ flowchart TD
|
|||||||
возвращает задачу `reopen` с причиной, а доклад по критериям приёмки становится
|
возвращает задачу `reopen` с причиной, а доклад по критериям приёмки становится
|
||||||
единственным, по чему приёмка вообще возможна.
|
единственным, по чему приёмка вообще возможна.
|
||||||
- **Заведением задач из урожая ревью.** Отложенные находки отдаются **списком**;
|
- **Заведением задач из урожая ревью.** Отложенные находки отдаются **списком**;
|
||||||
превращать их в задачи — работа того, кто ведёт задачи проекта.
|
превращать их в задачи — работа `av-dev-tasks:tasks`, у него на этот вход
|
||||||
|
отдельный сценарий «задачи из ревью и аудита». Плагина нет — урожай остаётся
|
||||||
|
списком в докладе, и это говорится строкой.
|
||||||
- **Определением ценности.** «Нужна ли эта функциональность» — не вопрос этого
|
- **Определением ценности.** «Нужна ли эта функциональность» — не вопрос этого
|
||||||
скилла ни на одном шаге. Чекпоинт спрашивает «так ли решаем», а не «надо ли».
|
скилла ни на одном шаге. Чекпоинт спрашивает «так ли решаем», а не «надо ли».
|
||||||
|
|
||||||
@@ -519,6 +524,11 @@ flowchart TD
|
|||||||
(разметка выведена из дельта-спек) и **вернись на чекпоинт шага 5** с тем, что
|
(разметка выведена из дельта-спек) и **вернись на чекпоинт шага 5** с тем, что
|
||||||
изменилось и почему.
|
изменилось и почему.
|
||||||
|
|
||||||
|
**Это правило старше правила о развилке.** Находка класса `развилка`, чьё
|
||||||
|
основание — «надо менять спеку», подпадает под оба; побеждает возврат на
|
||||||
|
чекпоинт, а вопрос в запись при нём остаётся, но возврата не заменяет. Иначе
|
||||||
|
одобренный дизайн переделывался бы записанным вопросом, то есть молча.
|
||||||
|
|
||||||
Тихо переделать утверждённое нельзя. Чекпоинт, который можно обойти находкой
|
Тихо переделать утверждённое нельзя. Чекпоинт, который можно обойти находкой
|
||||||
ревью, не значит ничего, а человек при этом уверен, что одобрил именно то, что
|
ревью, не значит ничего, а человек при этом уверен, что одобрил именно то, что
|
||||||
уехало в коммит.
|
уехало в коммит.
|
||||||
@@ -526,8 +536,9 @@ flowchart TD
|
|||||||
**Урожай — списком, не задачами.** Отложенные находки (реальный `major` не для
|
**Урожай — списком, не задачами.** Отложенные находки (реальный `major` не для
|
||||||
этого мерджа, развилка, решённая «потом», пачка `nit`) собери в секцию доклада
|
этого мерджа, развилка, решённая «потом», пачка `nit`) собери в секцию доклада
|
||||||
`Урожай`: формулировка, оракул, провенанс. Задачи из него **заводит не этот
|
`Урожай`: формулировка, оракул, провенанс. Задачи из него **заводит не этот
|
||||||
скилл** — у того, кто ведёт задачи проекта, своя нарезка, свой формат и свои
|
скилл** — их заводит `av-dev-tasks:tasks` своим сценарием «задачи из ревью и
|
||||||
правила дублей. Твоя обязанность — не потерять и передать.
|
аудита»: своя нарезка, свой формат, свои правила дублей. Твоя обязанность — не
|
||||||
|
потерять и передать.
|
||||||
|
|
||||||
**Границы покрытия из отчёта не выбрасывай** — они уезжают в финальный доклад
|
**Границы покрытия из отчёта не выбрасывай** — они уезжают в финальный доклад
|
||||||
сжатой строкой. Отчёт, из которого исчезло «что проверить было невозможно»,
|
сжатой строкой. Отчёт, из которого исчезло «что проверить было невозможно»,
|
||||||
@@ -564,6 +575,13 @@ flowchart TD
|
|||||||
[references/project-facts.md](../review/references/project-facts.md)
|
[references/project-facts.md](../review/references/project-facts.md)
|
||||||
конвейера ревью перечисляет все документы канона с их предметом. Пройди по этому
|
конвейера ревью перечисляет все документы канона с их предметом. Пройди по этому
|
||||||
перечню — каждый документ получает строку, отрицание остаётся обязательным.
|
перечню — каждый документ получает строку, отрицание остаётся обязательным.
|
||||||
|
|
||||||
|
**Двух домов в том перечне нет намеренно, а синку они нужны: `docs/adr/` и
|
||||||
|
`docs/research/`.** Проход ревью их не открывает — процессные, — но ADR как раз
|
||||||
|
**главный выход синка**: решение, принятое по ходу задачи, без этой строки
|
||||||
|
теряется систематически. Добавь их к перечню руками: `adr/` — решение с ценой,
|
||||||
|
принятое в этой задаче; `research/` — записка разведки, если ветка была
|
||||||
|
исследовательской.
|
||||||
Триггеры при этом ты знаешь хуже, и это называется в докладе строкой: «синк
|
Триггеры при этом ты знаешь хуже, и это называется в докладе строкой: «синк
|
||||||
сделан по перечню документов, без списка триггеров — плагина `av-dev-docs` нет».
|
сделан по перечню документов, без списка триггеров — плагина `av-dev-docs` нет».
|
||||||
Канона в проекте тоже нет — назови это исходом и предложи `av-dev-docs:canon`.
|
Канона в проекте тоже нет — назови это исходом и предложи `av-dev-docs:canon`.
|
||||||
@@ -573,9 +591,10 @@ flowchart TD
|
|||||||
Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не
|
Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не
|
||||||
создавай и не переключай, ничего не пушь.
|
создавай и не переключай, ничего не пушь.
|
||||||
|
|
||||||
Сообщение — по-русски, скиллом `av-dev-git:commit`, если он подключён (первая
|
Сообщение — по-русски, **скиллом `av-dev-git:commit`**: форму сообщения держит
|
||||||
строка «что сделано», тело списком 1–3 пункта, без трейлеров). Одна задача — один
|
он, и здесь она не пересказывается. Вызов не разрешился — плагина в проекте нет:
|
||||||
осмысленный коммит.
|
напиши сообщение сам и скажи строкой доклада, что форму коммита не сверял никто.
|
||||||
|
Одна задача — один осмысленный коммит.
|
||||||
|
|
||||||
### 11. Закрыть задачу — **после коммита, не раньше**
|
### 11. Закрыть задачу — **после коммита, не раньше**
|
||||||
|
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ description: "Конвейер ревью изменения, устроенны
|
|||||||
непроверенная ветка деградации хуже честного отказа. Заводить руками не надо:
|
непроверенная ветка деградации хуже честного отказа. Заводить руками не надо:
|
||||||
этим владеет скилл `av-dev-code:openspec` — он заводит каталог и заменяет
|
этим владеет скилл `av-dev-code:openspec` — он заводит каталог и заменяет
|
||||||
пример в `config.yaml` настройкой. Его же зовут `av-dev-docs:init` на новом
|
пример в `config.yaml` настройкой. Его же зовут `av-dev-docs:init` на новом
|
||||||
проекте и `canon adopt` на переводимом.
|
проекте и `av-dev-docs:canon` в режиме `adopt` — на переводимом.
|
||||||
- **Документы канона** — см. следующий раздел.
|
- **Документы канона** — см. следующий раздел.
|
||||||
- **Проектные копии этих скиллов и агентов удаляются при установке.** Если в
|
- **Проектные копии этих скиллов и агентов удаляются при установке.** Если в
|
||||||
проекте уже лежат свои `.claude/skills/review`,
|
проекте уже лежат свои `.claude/skills/review`,
|
||||||
`.claude/skills/review-pipeline`, `.claude/skills/task-pipeline`,
|
`.claude/skills/review-pipeline`, `.claude/skills/task-pipeline`,
|
||||||
`.claude/skills/resolve` или
|
`.claude/skills/task-batch`, `.claude/skills/resolve` или
|
||||||
`.claude/agents/<проект>-review-*.md` — снеси их. Иначе короткое имя разрешится
|
`.claude/agents/<проект>-review-*.md` — снеси их. Иначе короткое имя разрешится
|
||||||
в устаревшую проектную копию, молча и без признаков подмены.
|
в устаревшую проектную копию, молча и без признаков подмены.
|
||||||
|
|
||||||
@@ -121,8 +121,8 @@ description: "Конвейер ревью изменения, устроенны
|
|||||||
критерий, по которому судит изменение. `adr.*`, `research.*` и `tasks/` не
|
критерий, по которому судит изменение. `adr.*`, `research.*` и `tasks/` не
|
||||||
открывает никто.
|
открывает никто.
|
||||||
|
|
||||||
Дом канона этой раскладки — `av-dev-docs`, `references/canon.md`, раздел «Три
|
Дом канона этой раскладки — скилл `av-dev-docs:canon`, раздел «Три категории
|
||||||
категории документов». Конвейер её **читатель**: категории и имена тем он берёт
|
документов». Конвейер её **читатель**: категории и имена тем он берёт
|
||||||
оттуда и своих не заводит.
|
оттуда и своих не заводит.
|
||||||
|
|
||||||
Отсюда то, ради чего правило и заведено: **`docs/` перестаёт быть просто
|
Отсюда то, ради чего правило и заведено: **`docs/` перестаёт быть просто
|
||||||
@@ -866,8 +866,9 @@ Recall темы `conventions` равен длине конвенций прое
|
|||||||
- **всегда** — `review-specs` в режиме «дизайн ДО кода». Дельта-спеки сверяются
|
- **всегда** — `review-specs` в режиме «дизайн ДО кода». Дельта-спеки сверяются
|
||||||
на каждой задаче: это самый дешёвый чекпоинт конвейера, и он ловит то, что на
|
на каждой задаче: это самый дешёвый чекпоинт конвейера, и он ловит то, что на
|
||||||
готовом коде уже не чинят;
|
готовом коде уже не чинят;
|
||||||
- **со `medium`** — `review-rubric` (фаза 1 без фазы 2: рубрика на задуманный
|
- **со `medium`** — `review-rubric`: рубрика на задуманный узел, по ней же
|
||||||
узел становится приёмочными критериями и уезжает в `tasks.md`);
|
разбирается дельта-спека, а сами пункты уезжают приёмочными критериями в
|
||||||
|
`tasks.md`;
|
||||||
- **только в `large`** — `review-architecture` на предложении: можно ли выразить
|
- **только в `large`** — `review-architecture` на предложении: можно ли выразить
|
||||||
существующими понятиями — **включая конструкции стандартной библиотеки**, — не
|
существующими понятиями — **включая конструкции стандартной библиотеки**, — не
|
||||||
появляется ли второй способ. Вопрос «не изобретаем ли то, что уже есть в
|
появляется ли второй способ. Вопрос «не изобретаем ли то, что уже есть в
|
||||||
@@ -900,7 +901,7 @@ flowchart TD
|
|||||||
plan[/"план разметки задачи:<br/>размер, сложность, метка"/]
|
plan[/"план разметки задачи:<br/>размер, сложность, метка"/]
|
||||||
proposal["предложение: proposal.md + дельта-спеки"]
|
proposal["предложение: proposal.md + дельта-спеки"]
|
||||||
specs["specs (режим «дизайн ДО кода») — всегда"]
|
specs["specs (режим «дизайн ДО кода») — всегда"]
|
||||||
rubric["rubric, фаза 1 → приёмочные критерии в tasks.md"]
|
rubric["rubric → приёмочные критерии в tasks.md"]
|
||||||
arch["architecture на предложении"]
|
arch["architecture на предложении"]
|
||||||
author["вопрос автору: три формы решения и компромисс каждой"]
|
author["вопрос автору: три формы решения и компромисс каждой"]
|
||||||
fix["шаг пайплайна: правка спек, развилки — вопросом в запись"]
|
fix["шаг пайплайна: правка спек, развилки — вопросом в запись"]
|
||||||
@@ -942,8 +943,11 @@ flowchart TD
|
|||||||
- Находка не для этого мерджа, но реальная (отложенный `major`, развилка,
|
- Находка не для этого мерджа, но реальная (отложенный `major`, развилка,
|
||||||
решённая «потом»), — не теряется, но **и не заводится здесь**. Конвейер отдаёт
|
решённая «потом»), — не теряется, но **и не заводится здесь**. Конвейер отдаёт
|
||||||
её **списком урожая** в отчёте: формулировка, оракул, провенанс (какой проход,
|
её **списком урожая** в отчёте: формулировка, оракул, провенанс (какой проход,
|
||||||
какой change). Заведение задач принадлежит тому, кто ведёт задачи проекта, —
|
какой change). Заведение задач принадлежит `av-dev-tasks:tasks` — зови его со
|
||||||
у него свой формат, своя нарезка и свои правила дублей. Мелочь класса `nit`
|
списком урожая, у него на этот вход отдельный сценарий «задачи из ревью и
|
||||||
|
аудита»: свой формат, кластеризация по причине, дедуп против беклога и
|
||||||
|
кладбища. Плагина нет — урожай остаётся списком в отчёте, и это говорится
|
||||||
|
строкой доклада: задачи из него не заведёт никто. Мелочь класса `nit`
|
||||||
идёт в урожай одной пачкой, а не записью на находку.
|
идёт в урожай одной пачкой, а не записью на находку.
|
||||||
- `Promote candidates` — по процедуре [references/promote.md](references/promote.md):
|
- `Promote candidates` — по процедуре [references/promote.md](references/promote.md):
|
||||||
находка → конвенция → правило линтера → **удаление формулировки из конвенций**.
|
находка → конвенция → правило линтера → **удаление формулировки из конвенций**.
|
||||||
|
|||||||
@@ -8,9 +8,8 @@
|
|||||||
`av-dev-docs`, и проход читает их напрямую: пути жёсткие, посредник не нужен, а
|
`av-dev-docs`, и проход читает их напрямую: пути жёсткие, посредник не нужен, а
|
||||||
второй дом для тех же фактов разошёлся бы и выглядел актуальным.
|
второй дом для тех же фактов разошёлся бы и выглядел актуальным.
|
||||||
|
|
||||||
Определение канона — в плагине `av-dev-docs`,
|
Определение канона держит скилл `av-dev-docs:canon`. Здесь только карта «тема →
|
||||||
`skills/canon/references/canon.md`. Здесь только карта «тема → её дом → что
|
её дом → что оттуда берётся».
|
||||||
оттуда берётся».
|
|
||||||
|
|
||||||
## Карта тем
|
## Карта тем
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,7 @@
|
|||||||
## Форма записи
|
## Форма записи
|
||||||
|
|
||||||
**Это дом формы, и у него есть копия.** Скелет `docs/review.md`, который кладёт
|
**Это дом формы, и у него есть копия.** Скелет `docs/review.md`, который кладёт
|
||||||
в проект `av-dev-docs` (`skills/canon/references/skeletons.md`), повторяет её
|
в проект `av-dev-docs:canon`, повторяет её дословно — он уезжает в репозиторий и обязан там что-то говорить. Правка формы
|
||||||
дословно — он уезжает в репозиторий и обязан там что-то говорить. Правка формы
|
|
||||||
здесь **обязана** тянуть правку скелета и запись в журнал версий канона; иначе
|
здесь **обязана** тянуть правку скелета и запись в журнал версий канона; иначе
|
||||||
проекты продолжат писать по старой форме, а конвейер — ждать поля, которого нет.
|
проекты продолжат писать по старой форме, а конвейер — ждать поля, которого нет.
|
||||||
Дословность сверяет `scripts/copies.py` маркетплейса по маркерам ниже — но
|
Дословность сверяет `scripts/copies.py` маркетплейса по маркерам ниже — но
|
||||||
|
|||||||
@@ -94,9 +94,9 @@
|
|||||||
костяк — гейт, спеки, код, триаж**. Разрезать задачу, обе половины которой
|
костяк — гейт, спеки, код, триаж**. Разрезать задачу, обе половины которой
|
||||||
остаются в одной метке, значит заплатить костяк дважды за ту же проверку.
|
остаются в одной метке, значит заплатить костяк дважды за ту же проверку.
|
||||||
Резать стоит там, где разрез **снимает доказательство с большей части диффа**.
|
Резать стоит там, где разрез **снимает доказательство с большей части диффа**.
|
||||||
Шов и правило нарезки живут у того, кто ведёт задачи, — скилл `av-dev-tasks:tasks`,
|
Шов и правило нарезки живут у того, кто ведёт задачи, — скилл
|
||||||
его `references/split.md`. Пути туда конвейер не выносит: за пределы своего
|
`av-dev-tasks:tasks`, его раздел о нарезке. Пути туда конвейер не выносит: за
|
||||||
плагина он ходит вызовом скилла, а не файлом.
|
пределы своего плагина он ходит вызовом скилла, а не файлом.
|
||||||
|
|
||||||
Разметка в костяк не входит — она платится один раз на задачу, а не один раз на
|
Разметка в костяк не входит — она платится один раз на задачу, а не один раз на
|
||||||
прогон, и потому **разрез задачи её не удваивает**. Это единственное, что стало
|
прогон, и потому **разрез задачи её не удваивает**. Это единственное, что стало
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: doc-wording
|
name: doc-wording
|
||||||
description: "Вычитка языка документов проекта по информационному стилю — паспорт, архитектура, конвенции, безопасность, решения ADR, записки разведки, CLAUDE.md. Смотрит отглагольные существительные и страдательный залог, оценку без факта, стоп-слова и канцелярит, «одна мысль — одно предложение», англицизм при живом русском слове, жаргон и метафоры вместо прямого называния, термин, которого нет в документах проекта, транслит в имени файла. Отдаёт готовые формулировки на замену и ничего не правит сам. Записи каталога задач вычитывает отдельный агент task-wording, их форму — task-form. Использовать после правки документов, после adopt и после повышения версии канона. Только чтение."
|
description: "Вычитка языка документов проекта по информационному стилю — паспорт, архитектура, конвенции, безопасность, решения ADR, записки разведки, CLAUDE.md. Смотрит отглагольные существительные и страдательный залог, оценку без факта, стоп-слова и канцелярит, «одна мысль — одно предложение», англицизм при живом русском слове, жаргон и метафоры вместо прямого называния, термин, которого нет в документах проекта, транслит в имени файла. Отдаёт готовые формулировки на замену и ничего не правит сам. Записи каталога задач вычитывает отдельный агент task-wording, их форму — task-form. Зовётся по названной пачке правленных документов, а не на весь канон: последним шагом синка документации (av-dev-docs:docs), шагом заведения проекта (av-dev-docs:init), шагами adopt и upgrade скилла av-dev-docs:canon. Скилл healthcheck его не зовёт — там сверка утверждений, а не языка. Только чтение."
|
||||||
tools: Read, Grep, Glob
|
tools: Read, Grep, Glob
|
||||||
model: sonnet
|
model: sonnet
|
||||||
color: green
|
color: green
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ python3 $ds version --dir <корень> # версия кано
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Формы `openspec/config.yaml` здесь больше нет.** Каталог принадлежит конвейеру,
|
**Формы `openspec/config.yaml` здесь больше нет.** Каталог принадлежит конвейеру,
|
||||||
и форму смотрит его скрипт — `av-dev-code`, скилл `openspec`, команда
|
и форму смотрит его скрипт — скилл `av-dev-code:openspec`, команда
|
||||||
`openspec.py check`. Проект работает по OpenSpec, а плагина конвейера нет — форму
|
`openspec.py check`. Проект работает по OpenSpec, а плагина конвейера нет — форму
|
||||||
не проверяет никто, и это надо сказать строкой доклада, а не считать, что она
|
не проверяет никто, и это надо сказать строкой доклада, а не считать, что она
|
||||||
верна.
|
верна.
|
||||||
@@ -244,6 +244,18 @@ capability), `openspec/config.yaml`.
|
|||||||
**Передай им объявленное переходное состояние из шага 5** — иначе честная строка
|
**Передай им объявленное переходное состояние из шага 5** — иначе честная строка
|
||||||
в незаполненном слоте вернётся находкой, а это не поломка, а объявленный долг.
|
в незаполненном слоте вернётся находкой, а это не поломка, а объявленный долг.
|
||||||
|
|
||||||
|
### 7. Вычитай написанное — агент `doc-wording`
|
||||||
|
|
||||||
|
Судьи смотрят утверждения, а `adopt` только что **писал текст**: честные строки
|
||||||
|
в пустые слоты, переписанные при переносе абзацы, шапки перенесённых документов.
|
||||||
|
Язык этого текста не проверяет никто другой, а зовущий здесь по определению тот,
|
||||||
|
кто его и написал.
|
||||||
|
|
||||||
|
Позови агента **по названной пачке** — документы, которые ты завёл или правил,
|
||||||
|
плюс перенесённые целиком. Весь канон ему не нужен: он работает по списку, и
|
||||||
|
список же служит ему словарём терминов. Находки — готовые формулировки,
|
||||||
|
подставляешь их ты.
|
||||||
|
|
||||||
## `upgrade` — канон вырос
|
## `upgrade` — канон вырос
|
||||||
|
|
||||||
1. `docs.py version` — версия проекта и версия скрипта.
|
1. `docs.py version` — версия проекта и версия скрипта.
|
||||||
@@ -255,6 +267,10 @@ capability), `openspec/config.yaml`.
|
|||||||
4. Подними `canon` в `docs/.pm.json` до текущей.
|
4. Подними `canon` в `docs/.pm.json` до текущей.
|
||||||
5. `docs.py check`.
|
5. `docs.py check`.
|
||||||
6. **Позови судей** — Skill `av-dev-docs:healthcheck`.
|
6. **Позови судей** — Skill `av-dev-docs:healthcheck`.
|
||||||
|
7. **Позови вычитку** — агент `doc-wording`, но **только по тем документам,
|
||||||
|
которых записи журнала коснулись**, и только если правка была текстовой, а не
|
||||||
|
переименованием файла. Записи журнала пишутся руками в проектной прозе, и
|
||||||
|
дописанный по журналу раздел — такой же свежий текст, как на синке.
|
||||||
|
|
||||||
Записи журнала описывают **что сделать проекту**. Если запись этого не говорит —
|
Записи журнала описывают **что сделать проекту**. Если запись этого не говорит —
|
||||||
это дефект журнала, и о нём надо сказать, а не догадываться.
|
это дефект журнала, и о нём надо сказать, а не догадываться.
|
||||||
|
|||||||
@@ -402,7 +402,8 @@ kebab-case.** Причина не эстетическая: имя файла с
|
|||||||
род работы, и называется оно **`research` без раздела «Вопрос»**. Такая запись в
|
род работы, и называется оно **`research` без раздела «Вопрос»**. Такая запись в
|
||||||
работу не берётся и лежит в конце своей категории.
|
работу не берётся и лежит в конце своей категории.
|
||||||
|
|
||||||
Раскладку, форму записи и алгоритм работы над каждым типом держит скилл `tasks`.
|
Раскладку, форму записи и алгоритм работы над каждым типом держит скилл
|
||||||
|
`av-dev-tasks:tasks`.
|
||||||
|
|
||||||
### `CLAUDE.md`
|
### `CLAUDE.md`
|
||||||
|
|
||||||
@@ -432,8 +433,8 @@ kebab-case.** Причина не эстетическая: имя файла с
|
|||||||
**Файл канону не принадлежит, и проверяет его тоже не канон.** Каталог
|
**Файл канону не принадлежит, и проверяет его тоже не канон.** Каталог
|
||||||
`openspec/` — предпосылка конвейера: без него не работают ни `opsx:propose`, ни
|
`openspec/` — предпосылка конвейера: без него не работают ни `opsx:propose`, ни
|
||||||
ревью дизайна, ни сверка требований. Заводит его, настраивает и **проверяет
|
ревью дизайна, ни сверка требований. Заводит его, настраивает и **проверяет
|
||||||
форму** плагин `av-dev-code`, скилл `openspec`: там образец файла, там же
|
форму** скилл `av-dev-code:openspec`: там образец файла, там же скрипт
|
||||||
скрипт `openspec.py check`. `docs.py` о файле не говорит ничего.
|
`openspec.py check`. `docs.py` о файле не говорит ничего.
|
||||||
|
|
||||||
Канон называет его здесь по одной причине: `openspec/specs/` — **дом темы
|
Канон называет его здесь по одной причине: `openspec/specs/` — **дом темы
|
||||||
`requirements`**, и без этой строки карта тем неполна. На форму самого
|
`requirements`**, и без этой строки карта тем неполна. На форму самого
|
||||||
|
|||||||
@@ -19,9 +19,12 @@
|
|||||||
`<!-- дом: <id> -->` … `<!-- /дом: <id> -->`, копия —
|
`<!-- дом: <id> -->` … `<!-- /дом: <id> -->`, копия —
|
||||||
`<!-- копия: <id> из <путь> -->` … `<!-- /копия: <id> -->`;
|
`<!-- копия: <id> из <путь> -->` … `<!-- /копия: <id> -->`;
|
||||||
`scripts/copies.py` маркетплейса требует дословного
|
`scripts/copies.py` маркетплейса требует дословного
|
||||||
совпадения. Комментарии невидимы в отрендеренном markdown и уезжают в проект
|
совпадения. Правишь текст внутри маркеров — правь дом, а не копию.
|
||||||
вместе со скелетом — там они говорят читателю, что у текста есть дом. Правишь
|
|
||||||
текст внутри маркеров — правь дом, а не копию.
|
**Сама пара маркеров в проект не переносится.** Это машинерия маркетплейса:
|
||||||
|
путь в ней ведёт в дерево плагина, и в репозитории проекта он не разрешится ни
|
||||||
|
во что. Кладя скелет, копируй содержимое между маркерами, а строки
|
||||||
|
`<!-- копия: … -->` и `<!-- /копия: … -->` оставляй здесь.
|
||||||
|
|
||||||
## `docs/passport.md`
|
## `docs/passport.md`
|
||||||
|
|
||||||
@@ -354,6 +357,9 @@
|
|||||||
<!-- /копия: журнал-дефектов-форма -->
|
<!-- /копия: журнал-дефектов-форма -->
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Пара маркеров `копия:` внутри — машинерия маркетплейса; в `docs/review.md`
|
||||||
|
проекта уезжает только содержимое между ними (см. выше).
|
||||||
|
|
||||||
Новый проект: «Дефектов пока не было. Настройка конвейера появится с первым
|
Новый проект: «Дефектов пока не было. Настройка конвейера появится с первым
|
||||||
ревью.»
|
ревью.»
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,19 @@ description: Вести содержимое документов канона
|
|||||||
которых работа не касалась, — расхождение, внесённое правкой в одном месте, там
|
которых работа не касалась, — расхождение, внесённое правкой в одном месте, там
|
||||||
и живёт.
|
и живёт.
|
||||||
|
|
||||||
|
## Вычитка — наоборот, здесь
|
||||||
|
|
||||||
|
**Язык правленого вычитывается на синке, и зовёшь агента `doc-wording` ты.**
|
||||||
|
Довод обратный доводу про судей: он читает **только названную пачку**, стоит
|
||||||
|
дёшево и ищет ровно то, что портится в момент письма, — залог, оценку без факта,
|
||||||
|
жаргон, термин без ввода. Ждать сессии здесь нечего: через месяц никто уже не
|
||||||
|
помнит, какую фразу имел в виду автор.
|
||||||
|
|
||||||
|
Позови его **последним шагом синка**, отдав список файлов, которых чек-лист
|
||||||
|
коснулся, — и назови этот список в промпте: по нему же он судит, известен ли
|
||||||
|
термин. Ничего не правивший синк агента не зовёт. Находки он отдаёт готовыми
|
||||||
|
формулировками, подставляешь их ты.
|
||||||
|
|
||||||
## ADR — промоут, а не второе сочинение
|
## ADR — промоут, а не второе сочинение
|
||||||
|
|
||||||
Обоснование уже написано: `opsx:propose` кладёт `design.md` в каждый change, и
|
Обоснование уже написано: `opsx:propose` кладёт `design.md` в каждый change, и
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: init
|
name: init
|
||||||
description: "Завести новый проект — сессия вопросов и ответов по свободному описанию замысла, из которой рождается первичная документация по канону av-dev: паспорт, CLAUDE.md с инвариантами и командами, модель угроз с периметром, первые цели в роадмапе и скелет остальных документов. OpenSpec заводит не сам, а вызовом скилла av-dev-code:openspec — каталог принадлежит конвейеру; плагина конвейера нет — шаг пропускается строкой доклада. Использовать, когда начинают новый проект с нуля, когда есть только текст «что мне нужно и почему» и надо превратить его в рабочую документацию, когда просят провести стартовое интервью по брифу. Проект, где документация уже как-то ведётся, переводит скилл canon."
|
description: "Завести новый проект — сессия вопросов и ответов по свободному описанию замысла, из которой рождается первичная документация по канону av-dev: паспорт, CLAUDE.md с инвариантами и командами, модель угроз с периметром и скелет остальных документов; первые цели собирает интервью, а записывает их вызовом скилла av-dev-tasks:tasks — роадмап принадлежит плагину задач. OpenSpec заводит не сам, а вызовом скилла av-dev-code:openspec — каталог принадлежит конвейеру; плагина конвейера нет — шаг пропускается строкой доклада. Использовать, когда начинают новый проект с нуля, когда есть только текст «что мне нужно и почему» и надо превратить его в рабочую документацию, когда просят провести стартовое интервью по брифу. Проект, где документация уже как-то ведётся, переводит скилл canon."
|
||||||
---
|
---
|
||||||
|
|
||||||
# Заведение нового проекта
|
# Заведение нового проекта
|
||||||
@@ -26,12 +26,17 @@ description: "Завести новый проект — сессия вопро
|
|||||||
| `passport.md` | `architecture.md` |
|
| `passport.md` | `architecture.md` |
|
||||||
| `CLAUDE.md` | `database.md` |
|
| `CLAUDE.md` | `database.md` |
|
||||||
| `security.md` | `conventions/` |
|
| `security.md` | `conventions/` |
|
||||||
| `tasks/ROADMAP.md` — первые цели | `research/`, `adr/` |
|
| `docs/.pm.json` | `research/`, `adr/` |
|
||||||
| `docs/.pm.json` | `review.md` — журнал пуст, настройка появится с первым ревью |
|
| | `review.md` — журнал пуст, настройка появится с первым ревью |
|
||||||
|
|
||||||
Честная строка информативна, а не «TBD»: «архитектуры пока нет: кода нет,
|
Честная строка информативна, а не «TBD»: «архитектуры пока нет: кода нет,
|
||||||
заводится первой задачей». Проход читает её как факт.
|
заводится первой задачей». Проход читает её как факт.
|
||||||
|
|
||||||
|
**`tasks/ROADMAP.md` в таблице нет намеренно.** Первые цели `init` собирает
|
||||||
|
интервью (блок 6), но записывает их не он: каталогом задач и формой целей владеет
|
||||||
|
`av-dev-tasks:tasks`, и это шаг 7. Плагина нет — цели остаются списком в докладе,
|
||||||
|
роадмапа в проекте не появляется, и это говорится строкой.
|
||||||
|
|
||||||
## Порядок интервью — зависимость, а не удобство
|
## Порядок интервью — зависимость, а не удобство
|
||||||
|
|
||||||
Каждый блок опирается на ответ предыдущего; переставлять нельзя.
|
Каждый блок опирается на ответ предыдущего; переставлять нельзя.
|
||||||
@@ -66,7 +71,7 @@ description: "Завести новый проект — сессия вопро
|
|||||||
|
|
||||||
## Обращение к соседним плагинам
|
## Обращение к соседним плагинам
|
||||||
|
|
||||||
Два шага из девяти — вызовы чужого: OpenSpec заводит конвейер, каталог задач
|
Два шага порядка работы — вызовы чужого: OpenSpec заводит конвейер, каталог задач
|
||||||
ведёт плагин задач. Ни того, ни другого `init` не делает руками.
|
ведёт плагин задач. Ни того, ни другого `init` не делает руками.
|
||||||
|
|
||||||
**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов.
|
**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов.
|
||||||
@@ -123,7 +128,13 @@ description: "Завести новый проект — сессия вопро
|
|||||||
тоже строка доклада.
|
тоже строка доклада.
|
||||||
8. `docs.py check` из скилла `canon` — до отсутствия дрейфа. Замечания о
|
8. `docs.py check` из скилла `canon` — до отсутствия дрейфа. Замечания о
|
||||||
незаполненных плейсхолдерах остаются: их закрывает не `init`, а работа.
|
незаполненных плейсхолдерах остаются: их закрывает не `init`, а работа.
|
||||||
9. Покажи человеку, что получилось, и **отдельным списком** — что выведено из
|
9. **Вычитай написанное — агент `doc-wording`**, по пачке заполненных документов
|
||||||
|
(`passport.md`, `CLAUDE.md`, `security.md`). Здесь он нужен сильнее, чем где
|
||||||
|
бы то ни было: весь текст сочинён только что и по свободному брифу человека, а
|
||||||
|
бриф — это как раз залог, оценки без факта и жаргон. Скелеты с честной строкой
|
||||||
|
в пачку не клади, вычитывать в них нечего. Находки — готовые формулировки,
|
||||||
|
подставляешь их ты.
|
||||||
|
10. Покажи человеку, что получилось, и **отдельным списком** — что выведено из
|
||||||
брифа, что предположено, что осталось неизвестным. Правят по этим строкам.
|
брифа, что предположено, что осталось неизвестным. Правят по этим строкам.
|
||||||
|
|
||||||
## Что дальше
|
## Что дальше
|
||||||
|
|||||||
@@ -12,6 +12,12 @@
|
|||||||
не файл-на-находку.** Если у ревью был триаж — половина работы уже сделана, бери
|
не файл-на-находку.** Если у ревью был триаж — половина работы уже сделана, бери
|
||||||
его выход. Если нет — триажируй сам, прежде чем заводить.
|
его выход. Если нет — триажируй сам, прежде чем заводить.
|
||||||
|
|
||||||
|
**Штатный отправитель — `av-dev-code:review`** (и `av-dev-code:resolve`, который
|
||||||
|
его вызывает): задач он не заводит сам, а отдаёт отложенные находки **списком
|
||||||
|
урожая** — формулировка, оракул, провенанс — и хранит отчёт триажа вместе с
|
||||||
|
изменением. Приходит и любой другой разбор, вплоть до пересказа человеком; тогда
|
||||||
|
триажа нет и шаг 1 порядка делается руками.
|
||||||
|
|
||||||
## Находка агента — не задача
|
## Находка агента — не задача
|
||||||
|
|
||||||
Мнение агента — **гипотеза, пока у неё нет свидетельства** (падающий тест,
|
Мнение агента — **гипотеза, пока у неё нет свидетельства** (падающий тест,
|
||||||
|
|||||||
Reference in New Issue
Block a user