задачи: починена смена стадии, разобраны находки ревью плагина
Команда stage была дефектна по шести пунктам, и все шесть подтверждены прогоном: не звала raw_last (переход оставлял каталог красным), не переписывала шапку беклога (индекс продолжал объявлять прежнюю стадию), шла в обход write_config, молча пропускала файлы с непересобираемой метой, ломалась на беклоге без заголовков и схлопывала полки при первом объявлении стадии. Объявление и смена разведены: объявление беклога не трогает вовсе, смена трогает состав секций только по явному --sections, а слить полки скрипт не берётся ни в одном случае. Абзац шапки размечен парой «стадия», и расхождение с конфигом стало обычным дрейфом. Отказ по недостающей строке индекса запирал запись, пережившую упразднение роадмапа: edit, close и reopen теперь заводят или пропускают строку сами. Прочее: регистр stage нормализуется при чтении; --fix снимает мёртвые теги и у неразобранных записей; move отказывает переставлять сырьё; adopt держит место сырья; docs.py bump двигает одну запись журнала за раз; tasks.py получил перечень упразднённых адресов, и гейт наконец видит собственное упразднение ROADMAP.md. Запись «Версия 3» переписана по прогону на игрушечном проекте: прежний порядок шагов был неисполним. Закрыты дыры модели стадий (пересмотр плана стройки стал сценарием, приёмка отвязана от груминга, from-review, research и adopt получили развилку по стадии, перечень осей пересчитан) и находки, старшие этой сессии: review-triage получил режим без метки, три списка проектных копий сведены к дому с проверяемыми копиями, пять пересказов правил стали помеченными копиями или ссылками, language.md перестал объявлять юрисдикцию над чужим плагином.
This commit is contained in:
@@ -255,10 +255,11 @@ capability), `openspec/config.yaml`.
|
||||
|
||||
**Задачи `docs.py` не проверяет** — их ведёт другой скилл, и согласованность
|
||||
каталога показывает только `tasks.py check`. Позвал на шаге 5 скилл задач —
|
||||
его отчёт идёт в доклад отдельной строкой, и пункт «задачи без цели» в нём
|
||||
зелёным не станет: цели не сочиняются адаптацией (запрет записан у того, кто
|
||||
ведёт задачи), их проставляет человек порциями переоценки на первом груминге —
|
||||
скилл `av-dev:task-groom`.
|
||||
его отчёт идёт в доклад отдельной строкой, и зелёным он сразу не станет:
|
||||
у перенесённых записей нет критериев приёмки, а `check` без объявленной
|
||||
**стадии** отказывает вовсе. Стадию называет человек (`tasks.py stage
|
||||
build|support`) — машина её не выводит: список пунктов одинаково выглядит и
|
||||
планом стройки, и очередью правок.
|
||||
|
||||
### 5. Объяви переходное состояние
|
||||
|
||||
|
||||
@@ -351,9 +351,10 @@ kebab-case.** Причина не эстетическая: имя файла с
|
||||
скриптом и своими проверками; где каталог лежит и как названы его части, говорит
|
||||
секция `[tasks]` в `.av-dev.toml`. Версия там одна на всю раскладку: канон и
|
||||
каталог задач двигаются вместе, потому что ведёт их один плагин.
|
||||
Канон **резервирует место** в `docs/` и внутрь не смотрит:
|
||||
`docs.py` каталог не открывает, его отсутствия не считает дрейфом и согласованность
|
||||
задач не проверяет. Проект, не заведший каталог задач, их не ведёт
|
||||
Каталог лежит **в корне репозитория, вне `docs/`** — места в `docs/` канон ему
|
||||
больше не резервирует (переезд — запись 11 закрытого журнала), а внутрь не
|
||||
смотрит и подавно: `docs.py` каталог не открывает, его отсутствия не считает
|
||||
дрейфом и согласованность задач не проверяет. Проект, не заведший каталог задач, их не ведёт
|
||||
вовсе, и отказом это быть не может.
|
||||
|
||||
Раскладку, форму записи и команды держит скилл `av-dev:task-track`. Ниже — то,
|
||||
|
||||
@@ -40,27 +40,60 @@
|
||||
`[tasks] completion_heading` — тоже. Появились ключ `[tasks] stage`, команда
|
||||
`tasks.py stage` и флаги `init --stage`, `adopt scan --stage`.
|
||||
|
||||
**Что сделать проекту.**
|
||||
**Что сделать проекту. Порядок шагов обязателен**, и первый шаг — не команда:
|
||||
пока в `[tasks]` лежит упразднённый ключ, **любая** подкоманда `tasks.py`
|
||||
отвечает кодом 3 и работать нечем.
|
||||
|
||||
1. **Разобрать цели.** У каждой записи типа `goal` в `tasks/items/` два исхода, и
|
||||
выбирает человек: она становится обычной задачей (`edit <слаг> --type
|
||||
feature|fix|chore|research`) либо уходит (`close <слаг> --reason …`). Задачи,
|
||||
носившие её тег, живут дальше сами по себе. Скрипт этого не решает и говорит
|
||||
1. **Вычистить конфиг руками.** Из секции `[tasks]` в `.av-dev.toml` удалить
|
||||
ключи `roadmap` (или `plan`) и `completion_heading`. Каждый из них — код 3 на
|
||||
любой команде, и названы они здесь оба: второй легко пропустить, потому что
|
||||
его упразднение не видно по имени файла.
|
||||
2. **Удалить `tasks/ROADMAP.md`.** Секция `Готово` уходит вместе с ним и **не
|
||||
переносится**: «что приложение умеет» отвечают спеки, «когда это появилось» —
|
||||
`git log` беклога. Проект без `openspec/specs/` теряет здесь единственный
|
||||
связный перечень достигнутого — если он нужен, сохрани его сам до удаления
|
||||
(документом проекта, не задачами).
|
||||
3. **Прогнать `tasks.py check --fix`.** Он снимет теги `goal:<слаг>` и
|
||||
`decomposed`, переименует поле `Секция` → `Категория` и перепишет старую
|
||||
форму меты — **в том числе у самих записей типа `goal`**. Записи `goal` при
|
||||
этом останутся: во что превращается цель, машина не решает и говорит
|
||||
`НЕОДНОЗНАЧНО`.
|
||||
2. **Перенести содержимое `ROADMAP.md`.** Секция `Готово` **удаляется**: «что
|
||||
приложение умеет» отвечают спеки, «когда это появилось» — `git log`. Строки
|
||||
`Запланировано`, `Направления` и `Сопровождение` — это цели, и они разбираются
|
||||
шагом 1. Затем удалить сам файл и ключ `roadmap` из `.av-dev.toml`, если он там
|
||||
был.
|
||||
3. **Объявить стадию** — `tasks.py stage build` или `tasks.py stage support`.
|
||||
4. **Разобрать цели поштучно.** У каждой два исхода, и выбирает человек: она
|
||||
становится задачей (`edit <слаг> --type feature|fix|chore|research`) либо
|
||||
уходит (`close <слаг> --reason …`). Строки в беклоге у неё нет — её жильём
|
||||
был роадмап, — и `edit --type` заведёт её сам, в первую секцию и в конец,
|
||||
сказав об этом; место назначь потом. Раздел `Завершение` в теле переехавшей
|
||||
записи **удали руками**: схеме нового типа он не принадлежит, и `check`
|
||||
оставит о нём замечание. Задачи, носившие тег цели, живут дальше сами по
|
||||
себе — разбирать их не нужно.
|
||||
5. **Объявить стадию** — `tasks.py stage build` или `tasks.py stage support`.
|
||||
Приложение ещё строится и список работ линеен по зависимости — `build`;
|
||||
работает и правится точечно — `support`. Без ключа `check` отказывает: порядок
|
||||
строк нечем прочитать. На `build` секция беклога обязана остаться **одна** —
|
||||
слить полки надо руками, порядок строк в слитом списке знает только человек.
|
||||
4. **Поднять версию** — `docs.py bump`. Последним шагом.
|
||||
5. `docs.py check` и `tasks.py check --dir <каталог задач>` — до отсутствия
|
||||
дрейфа. Теги `goal:` и `decomposed`, поле `Секция` и старую форму меты снимет
|
||||
`tasks.py check --fix`.
|
||||
строк нечем прочитать.
|
||||
|
||||
**Объявление беклог не трогает** — ни секций, ни файлов: оно называет то, что
|
||||
уже верно. Поэтому проекту с несколькими полками, объявляющему `build`,
|
||||
команда откажет и назовёт выход: слить полки самому (`move <слаг> --section
|
||||
<куда> --reason …`), потому что порядок строк в слитом списке знает только
|
||||
человек. Флаг `--sections` при объявлении не принимается — он для **смены**
|
||||
стадии, где сливать просят явно.
|
||||
6. **Поправить шапку `BACKLOG.md`.** Абзац про стадию теперь размечен парой
|
||||
`<!-- стадия -->` … `<!-- /стадия -->`, и по нему `check` сверяет шапку с
|
||||
конфигом. В беклоге, заведённом до этой версии, разметки нет — `stage` об
|
||||
этом скажет. Возьми готовый абзац из свежего каталога (`tasks.py init` во
|
||||
временном месте) или напиши сам: он объясняет, что значит порядок строк, и
|
||||
читают вместо документации именно его.
|
||||
7. **Поднять версию** — `docs.py bump`. Последним шагом. Он двигает **одну**
|
||||
запись за раз: отставшему на две записи проекту зовётся дважды, следом за
|
||||
шагами каждой.
|
||||
8. `docs.py check` и `tasks.py check --dir <каталог задач>` — до отсутствия
|
||||
дрейфа.
|
||||
|
||||
**Проект, не прошедший записи 1 и 2, начинает с этой.** Их собственные шаги
|
||||
велят гонять `tasks.py check` до зелёного, а он на упразднённом ключе отвечает
|
||||
кодом 3 — то есть пройти их сегодня нельзя, не сделав шаг 1 отсюда. Записи от
|
||||
этого не переписываются: порядок между ними прежний, добавлено одно условие
|
||||
входа.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -702,9 +702,22 @@ def cmd_bump(args: argparse.Namespace) -> int:
|
||||
if was is not None and was > LAYOUT_VERSION:
|
||||
fail(ENV, f"проект на версии {was}, скрипт знает {LAYOUT_VERSION}:"
|
||||
f" устарел плагин, обнови маркетплейс")
|
||||
conf.set_version(root, LAYOUT_VERSION)
|
||||
# Двигается **одна** запись за раз, а не сразу до текущей: число объявляет
|
||||
# пройденными шаги журнала, и прыжок через запись объявил бы пройденным то,
|
||||
# чего никто не делал. Отставшему на три записи проекту `bump` зовётся три
|
||||
# раза — по разу на запись, следом за её шагами.
|
||||
#
|
||||
# Версии нет вовсе — случай другой: проект не жил ни одной записью журнала,
|
||||
# его раскладку только что вывели сегодняшним форматом (`adopt`), и
|
||||
# объявлять ему нечего, кроме текущего числа.
|
||||
target = LAYOUT_VERSION if was is None else was + 1
|
||||
conf.set_version(root, target)
|
||||
print(f"версия раскладки: {was if was is not None else 'не была объявлена'}"
|
||||
f" → {LAYOUT_VERSION} в {CONFIG}")
|
||||
f" → {target} в {CONFIG}")
|
||||
if target < LAYOUT_VERSION:
|
||||
print(f" до текущей ({LAYOUT_VERSION}) осталось записей журнала:"
|
||||
f" {LAYOUT_VERSION - target}. Пройди шаги следующей и позови bump"
|
||||
f" снова — по разу на запись")
|
||||
return OK
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user