Обкатка скилла tasks на выдуманном проекте — консольные крестики-нолики на JavaScript, каталог заведён с нуля тем же скриптом. Форма вылезла раньше содержания, и правки все про неё. Заголовок отвечает на вопрос типа записи, и форм три: цель — утверждение о возможности, задача — глагол в неопределённой форме (допускается «не» перед ним), идея — назывное, без обещания. Причина не стилистическая: описательный заголовок называет состояние, а из состояния не видно, чего от работы ждут — «Ничья объявляется, пока клетки есть» одинаково читается как жалоба и как задание. Отсюда же разница индексов: роадмап — список возможностей, беклог — список работ, и перепутанные формы делают каждый похожим на другой. Механизировано ровно то, что механизируется: check считает заголовки, где первое слово не на -ть/-ти/-чь, и печатает число в блоке здоровья. Замечанием на файл нельзя — эвристика грубая, а на 97 записях двух живых проектов это поток одинаковых строк, после которого пропускают весь блок. Годность формулировки судит отдельный агент task-wording, а не чек-лист в скилле: сейчас формулировку пишет и проверяет один агент в одном контексте, а самопроверка текста слабее всего там, где формулировка казалась удачной при написании. Он ничего не правит — возвращает готовые формулировки, и заголовок с «зачем» показываются человеку, потому что по ним задачу выбирают. Ничего из того, что ловит tasks.py check, он не трогает намеренно: это был бы второй дом для правила. Заголовки секций — с прописной, после заголовка пустая строка, во всех индексах. Канонические имена стали Готово | Запланировано | Направления | Разработка (англ. Done | Planned | Directions | Tooling), сверка везде по нижнему регистру, так что старые индексы читаются по-прежнему. Отбивка живёт на записи, а не на вставке: через Plan.index проходит каждая правка индекса, а мест вставки три. Имя секции принадлежит заголовку индекса, файл на неё только ссылается. Это разрешает единственную неоднозначность починки — расхождение в одном регистре правится в пользу заголовка. Без него переезд на канон оставил бы «Готово» в роадмапе и «готово» в каждом файле цели, и свести это было бы некому. Регистр правится только у канонических секций: имена секций беклога выбирает проект. Обкатка нашла два дефекта, которых не находили ни линтеры, ни свои проверки. Вставка в пустую секцию съедала отбивку перед следующим заголовком — пропуск пустых строк теперь идёт только до первой непустой. Мета, разорванная пустой строкой, теряла поля молча: check видел лишь следствие («без рода работы») и советовал edit --kind, который дописывал второе такое же поле. Поле меты в теле стало ошибкой с названной причиной, и --fix её намеренно не чинит — какое из двух значений верное, знает человек. DECISIONS тема 20 (ЕЕЕ–ККК, следствия 82–85), changelog канона v3 пополнен двумя пунктами и двумя шагами переезда, TODO — два шага для healthlog и jellybit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
124 lines
10 KiB
Markdown
124 lines
10 KiB
Markdown
# Адаптация каталога задач
|
||
|
||
Проект, где задачи уже как-то ведутся, и из имеющегося материала **выводится**
|
||
заполненный каталог задач: цели, задачи, кладбище, индексы. Операция разовая —
|
||
после неё проект живёт скиллами `tasks` и `session`.
|
||
|
||
**Это часть приведения проекта к канону.** Раскладку `docs/` целиком ведёт скилл
|
||
`av-dev-pm:canon`; он же зовёт этот сценарий на шаге «каталог задач», потому что
|
||
форматом задач владеет `tasks`, а не `canon`. Отдельно сценарий вызывается,
|
||
когда переводить надо **только** задачи.
|
||
|
||
Вход какой угодно: старая раскладка `av-dev-backlog` (индекс `README.md`,
|
||
кладбище `CLOSED.md`, приоритеты секциями, транслитные слаги, файлы рядом с
|
||
индексом), `TODO.md`, россыпь заметок, раздел «планы» в `README.md`, список
|
||
шагов роадмапа проекта.
|
||
|
||
## Три правила, из которых всё следует
|
||
|
||
1. **Сперва карта, потом файлы.** Человеку показывается, что найдено, как
|
||
разложилось по целям и **что не разложилось**, — и только после подтверждения
|
||
пишется хоть один файл. Это то же правило, что у интейка находок ревью:
|
||
массовое заведение записей без подтверждения — самый дорогой отказ, потому
|
||
что разгребает его потом переоценка.
|
||
2. **Ничего не терять.** Исходный текст переезжает в тело, «зачем» и причина
|
||
сохраняются, кладбище переносится строка в строку. Переименование слага —
|
||
не правка, а **перенос ссылок**: он делается одним проходом вместе с
|
||
переименованием, иначе останутся битые ссылки, которых никто не проверяет.
|
||
3. **Что не классифицировалось — назвать поимённо.** Проглоченный пункт
|
||
выглядит как «всё перенеслось». Список «не разложилось» идёт в доклад
|
||
целиком, с причиной по каждому пункту.
|
||
|
||
## Форма: карта — суждение — запись
|
||
|
||
Механику несёт `tasks.py adopt`, суждение — ты. Разделено ровно по границе
|
||
«машина умеет / не умеет»:
|
||
|
||
```
|
||
tk="$CLAUDE_PLUGIN_ROOT/skills/tasks/scripts/tasks.py"
|
||
|
||
python3 $tk adopt scan --from docs/backlog docs/plan.md TODO.md \
|
||
--target docs/tasks --out tasks-adopt-plan.json # только чтение
|
||
python3 $tk adopt apply --plan tasks-adopt-plan.json \
|
||
--refs docs openspec CLAUDE.md README.md # запись
|
||
```
|
||
|
||
`scan` ничего не пишет, кроме карты: он распознаёт раскладку, собирает записи,
|
||
поля «зачем», причины, кладбище, помечает похожее на транслит и на открытый вопрос в
|
||
прозе, и **называет поимённо** то, что не разложилось. `apply` пишет каталог
|
||
целиком одним проходом и чинит перекрёстные ссылки.
|
||
|
||
Между ними — твоя работа, которую машина не сделает:
|
||
|
||
- **английские слаги.** Перевести `taj-brejk-pri-ravnoj-polnote` в
|
||
`tie-break-equal-completeness` может только тот, кто понимает смысл. `scan`
|
||
честно говорит: проверить надо **все** слаги, признаки транслита — эвристика;
|
||
- **цели.** Шаги роадмапа — готовые цели из **«порядка»** (очередь и обоснование у
|
||
них уже есть); тематические скопления задач — **«темы»** («прочность слияния»,
|
||
«журнал и пересборка»). Предлагаешь ты, назначает человек;
|
||
- **что вообще не задача.** Обоснование порядка шагов, абзац прозой, заголовок
|
||
раздела — это не пункты беклога, и они уходят в «не разложилось» с причиной.
|
||
|
||
## Порядок
|
||
|
||
1. **Осмотрись.** Где лежат задачи, роадмап, заметки. Каталог задач по канону —
|
||
всегда `docs/tasks`. Секции беклога (`--sections`) — по умолчанию
|
||
`Ядро,Инфра`; если у проекта деление другое по существу, оно называется
|
||
здесь, а не подгоняется под умолчание, и становится **заголовками `##`
|
||
индекса** — их единственным домом. В `docs/.pm.json` секции не пишутся.
|
||
2. **`adopt scan`** по всем источникам разом. Один прогон, одна карта: два
|
||
прохода дадут два несогласованных состояния.
|
||
3. **Заполни карту**: `slug` (английский), `section`, `goal` у каждой записи;
|
||
список `goals` — из шагов роадмапа и из тем. Закрытый шаг целью не
|
||
заводится. Пустой `goal` — законный исход только у идеи.
|
||
4. **Покажи человеку карту** через `AskUserQuestion`, ≤3 вопроса за итерацию,
|
||
рекомендация первым вариантом. Показывается: сколько записей, предлагаемые
|
||
цели (порядок и темы) с обоснованием, спорные отнесения, список «не
|
||
разложилось». Массовые механические решения (слаги, порядок строк) не
|
||
выносятся — это механика.
|
||
5. **`adopt apply`.** `--refs` перечисляет **всё**, где могут стоять ссылки на
|
||
слаги: документация, архив изменений, `CLAUDE.md`, `README.md`. Скрипт
|
||
посчитает и покажет, сколько ссылок поправлено и по каким слагам.
|
||
6. **`tasks.py check`** и доклад.
|
||
|
||
`apply` отказывается писать поверх живого каталога и проверяет карту целиком
|
||
**до** первой записи: неверная секция, дубль слага, цель, которой нет в карте —
|
||
всё это отказ до того, как на диске появился хотя бы один файл.
|
||
|
||
## Переходное состояние — объявляется, а не заминается
|
||
|
||
Сразу после адаптации задачи в большинстве своём **не готовы к взятию**: у них
|
||
нет критериев приёмки, а у части может не быть цели. Это нормально, но обязано
|
||
быть названо, иначе следующий агент примет пустой беклог за поломку.
|
||
|
||
`apply` печатает состояние по факту: сколько задач без цели (это **ошибки**
|
||
`check`) и сколько без критериев (`check` их ошибкой не считает, но `sprint
|
||
take` такую задачу не возьмёт). Закрывается это **порциями переоценки** — шаг 3
|
||
скилла `session`, 5–8 задач за порцию: проставить цели, превратить «готово,
|
||
когда» в критерии с оракулами, вынуть вопросы из прозы в раздел «Вопросы».
|
||
|
||
Готовность к первому спринту — не «`check` зелёный», а «есть 2–5 критериев хотя
|
||
бы у набора под одну цель».
|
||
|
||
## Чего адаптация не делает
|
||
|
||
- **Не удаляет источники.** Старый каталог остаётся на месте: сверить и убрать —
|
||
дело человека, удалять чужое молча нельзя. В доклад идёт готовая команда.
|
||
- **Не переписывает подписи ссылок.** `[docs/backlog](docs/tasks/BACKLOG.md)` —
|
||
цель поправлена, текст остался; это правится глазами, и таких мест немного.
|
||
- **Не сочиняет критерии приёмки и не придумывает цели**, которых в материале
|
||
нет. Придуманная цель хуже отсутствующей: под неё соберут спринт.
|
||
- **Не трогает историю.** В коммитах старые слаги остаются, и это нормально.
|
||
|
||
## Доклад
|
||
|
||
- Источники и что в каждом распознано (раскладка, индекс, кладбище, секции).
|
||
- Сколько записей перенесено, сколько целей заведено (порядок / темы) и откуда
|
||
каждая выведена.
|
||
- **Переименования**: сколько слагов, сколько ссылок поправлено и в скольких
|
||
файлах — числом, а не «поправлены ссылки».
|
||
- **Не разложилось**: поимённо, с причиной.
|
||
- Переходное состояние: сколько задач без цели, сколько без критериев, чем и за
|
||
сколько порций закрывается.
|
||
- `tasks.py check` — результат строкой.
|