From 95fed623e7e4cce1b2597291cc5f5881f8171fa9 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Thu, 13 Aug 2026 09:30:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BE=D0=B1=D1=81=D0=BB=D1=83=D0=B6=D0=B8?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5:=20=D0=BD=D0=B0=D0=B9=D0=B4?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D0=B0=D1=8F=20=D0=B4=D0=B5=D0=BB=D1=8C=D1=82?= =?UTF-8?q?=D0=B0=20=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2=D0=BB=D0=B8?= =?UTF-8?q?=D0=B2=D0=B0=D0=B5=D1=82=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=83?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B5=D0=B4=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=D0=BC,=20=D0=B0=20=D0=BD=D0=B5=20=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=B0=D0=B7=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Стоп по найденной дельта-спеке говорил только «поведение меняется, дальше идёт решение». Классификация при этом падала на человека в момент, когда весь материал для неё у исполнителя, а задача выглядела сломанной, хотя она просто оказалась шире своего типа. Порядок теперь из трёх шагов: назвать тип, которым задача оказалась (fix — расходится с заявленным, feature — снаружи появляется то, чего не было), объяснить простым языком, что нашлось, и дать два решения — переформулировать запись и решать процессом того типа следующим прогоном либо прекратить работу. Третьего решения, «доделать как обслуживание», нет. Тип исполнитель предлагает, меняет его av-dev-tasks:tasks и только после ответа: переклеенный на ходу тип назначает себе другой процесс и другую глубину проверки. Сделанное при любом решении остаётся в рабочем дереве незакоммиченным. --- DECISIONS.md | 15 ++++ README.md | 6 +- av-dev-code/skills/resolve/SKILL.md | 19 +++-- .../skills/resolve/references/maintain.md | 83 ++++++++++++++++--- .../skills/tasks/references/task-chore.md | 7 ++ 5 files changed, 114 insertions(+), 16 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index 9b4819f..1eca2c2 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -3857,6 +3857,16 @@ change по нему не будет никогда, — и такое реше на то, что она собирается. `requirements` и `security` не смотрит никто, и это строка границ покрытия, а не умолчание. +**Найденная дельта — не поломка задачи, а обнаружение более широкого типа.** +Стоп поэтому устроен как три шага, а не как доклад об отказе: назвать тип, +которым задача оказалась (`fix` — расходится с заявленным, `feature` — снаружи +появляется то, чего не было), объяснить человеку простым языком, что нашлось, и +дать **два** решения — переформулировать запись и решать её процессом того типа +следующим прогоном либо прекратить работу. Третьего решения, «доделать как +обслуживание», нет: оно и есть молчаливое изменение поведения. Тип при этом +исполнитель **предлагает**, а меняет `av-dev-tasks:tasks` и только после ответа +— иначе исполнитель назначает себе другой процесс и другую глубину проверки сам. + **Триггеры ADR у обслуживания работают стоп-признаком, а не поводом завести запись.** Список источников ADR канон закрыл двумя — архивный `design.md` и записка разведки, — и обслуживание не производит ни того ни другого. Значит @@ -3904,3 +3914,8 @@ change по нему не будет никогда, — и такое реше 216. **Место для нового документа ищется не по теме, а по бездомному факту.** Тема «тулчейн» звучит убедительно, а фактов без дома за ней не оказалось — значит документ был бы вторым домом четырёх чужих. +217. **Работа, переросшая свой тип, останавливается предложением, а не отказом.** + «Здесь нужно менять спеки» перекладывает классификацию на человека в момент, + когда весь материал для неё у исполнителя. Стоп обязан принести названный + тип, объяснение и закрытый список решений — иначе выбор делается вслепую или + не делается вовсе, и работа доезжает до коммита не тем процессом. diff --git a/README.md b/README.md index cdefb3d..5a4eb81 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,11 @@ и `operations`, плюс `conventions` с техническим разбором, если дифф трогает код; главный шаг сценария — синк документации, потому что обслуживание чаще прочих двигает как раз те факты, которые сверяются с кодом. Правка гейта - сверяется по составу проверок, а не по цвету. + сверяется по составу проверок, а не по цвету. Нашлась дельта-спека — задача + **оказалась шире своего типа**: работа останавливается, тип называется + (`fix` или `feature`), человек получает объяснение простым языком и два + решения — переформулировать запись и решать её процессом того типа следующим + прогоном либо прекратить; «доделать как обслуживание» решением не является. **Разведка** (тип `research`, сырая идея, мутная постановка) кода не пишет вовсе: её чекпоинт — варианты, 2–4 способа решить с ценой каждого, — стоит до первого написанного требования, а исход уезжает в документы канона и в diff --git a/av-dev-code/skills/resolve/SKILL.md b/av-dev-code/skills/resolve/SKILL.md index 01ec165..22d7666 100644 --- a/av-dev-code/skills/resolve/SKILL.md +++ b/av-dev-code/skills/resolve/SKILL.md @@ -1,6 +1,6 @@ --- name: resolve -description: "Взять одну задачу и довести её до закрытия. Одна точка входа, три сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ известен и меняется поведение — сценарий решения: цикл Spec Driven Development (opsx propose → разметка → ревью дизайна → чекпоинт с объяснением человеческим языком → opsx apply → ревью кода → archive → синк документации → коммит → закрытие). Способ известен, а спека не меняется (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) — сценарий обслуживания: правка → гейт со сверкой состава проверок → ревью фиксированным планом без change (autotests, operations, плюс conventions, если тронут код) → синк документации → коммит → закрытие; планового стопа нет, change не заводится. Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → вычитка написанного → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст. Использовать, когда просят взять, сделать или решить задачу, обновить зависимости или сборку, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога." +description: "Взять одну задачу и довести её до закрытия. Одна точка входа, три сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ известен и меняется поведение — сценарий решения: цикл Spec Driven Development (opsx propose → разметка → ревью дизайна → чекпоинт с объяснением человеческим языком → opsx apply → ревью кода → archive → синк документации → коммит → закрытие). Способ известен, а спека не меняется (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) — сценарий обслуживания: правка → гейт со сверкой состава проверок → ревью фиксированным планом без change (autotests, operations, плюс conventions, если тронут код) → синк документации → коммит → закрытие; планового стопа нет, change не заводится. Нашлась дельта-спека — задача оказалась шире своего типа: стоп с объяснением простым языком и двумя решениями человека, переформулировать запись в fix или feature и решать её процессом того типа следующим прогоном либо прекратить работу. Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → вычитка написанного → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст. Использовать, когда просят взять, сделать или решить задачу, обновить зависимости или сборку, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога." --- # Работа над одной задачей @@ -165,9 +165,15 @@ description: "Взять одну задачу и довести её до за с исходом «нужна разведка»: назови, что именно неясно, и не продолжай. Кода к этому моменту не написано, и писать его «пока разбираемся» нельзя; - **обслуживание → решение**: нашлась дельта-спека, то есть поведение всё-таки - меняется. **Стоп** с исходом «меняется спека». Сделанное не выбрасывается, но - и не коммитится: оно уезжает в change следующим прогоном. Коммит обслуживания - заявляет «поведение не менялось» — под ним поведение меняется молча; + меняется. Задача не сломалась — она **оказалась шире своего типа**, и стоп + здесь несёт человеку выбор: назови тип, которым она оказалась (`fix` — + расходится с заявленным, `feature` — снаружи появляется то, чего не было), + объясни простым языком, что нашлось, и дай два решения — **переформулировать + запись и решать процессом того типа следующим прогоном** либо **прекратить + работу**. Третьего — «доделать как обслуживание» — нет. Исход в обоих случаях + «меняется спека»; сделанное остаётся в рабочем дереве незакоммиченным, тип + меняет `av-dev-tasks:tasks` и только после ответа. Подробно — + [maintain.md](references/maintain.md), раздел «Дельта нашлась по ходу»; - **обслуживание → разведка**: форма правки неизвестна (мажорное обновление, смена сборщика). **Стоп** с исходом «нужна разведка», по тому же основанию, что и у решения; @@ -202,7 +208,7 @@ flowchart TD fork2 -->|"да"| solve fork2 -->|"нет: тип chore"| main solve -.->|"способа всё же нет:
стоп, кода не написано"| res - main -.->|"нашлась дельта:
стоп, следующим прогоном"| solve + main -.->|"нашлась дельта: стоп,
тип на fix или feature,
следующим прогоном"| solve main -.->|"форма неизвестна:
стоп"| res res -.->|"способ выбран:
следующим прогоном,
зовёт человек"| solve ``` @@ -217,6 +223,9 @@ flowchart TD написанного требования. Правило вокруг них общее. **У обслуживания планового стопа нет вовсе, и это следствие, а не поблажка.** +Один стоп с ожиданием ответа у него всё же есть — по найденной дельта-спеке, — но +плановым он не является: через него проходят только те прогоны, где задача +оказалась не тем, чем объявлена. Чекпоинт объясняет человеку **выбор**, а у обслуживания выбора нет по построению: что делать, сказано в записи, и объяснение свелось бы к пересказу задачи её же автору. Стоп, на котором нечего решать, вырождается в обряд diff --git a/av-dev-code/skills/resolve/references/maintain.md b/av-dev-code/skills/resolve/references/maintain.md index e55f24f..c2c9ae3 100644 --- a/av-dev-code/skills/resolve/references/maintain.md +++ b/av-dev-code/skills/resolve/references/maintain.md @@ -49,17 +49,67 @@ либо отправил бы в полный цикл ради пустого change, либо принял бы как исключение, а исключения не исполняются. -## Дельта нашлась по ходу — это стоп +## Дельта нашлась по ходу — стоп, и у него свой порядок Признак тот же, что на шаге 7 сценария решения: **меняется ли то, что записано в `openspec/specs/`**. Обнаружилось, что меняется, — работа перестала быть обслуживанием в ту же секунду, и продолжать её нельзя: коммит обслуживания заявляет «поведение не менялось», а оно меняется. -**Сделанное не выбрасывается.** Оно остаётся в рабочем дереве и уезжает в change -следующим прогоном, который идёт сценарием решения. Коммитить его сообщением про -обслуживание нельзя: так поведение меняется молча, и ни ревью дизайна, ни -чекпоинт по нему уже не пройдут никогда. +**Задача при этом не сломалась — она оказалась шире своего типа.** Поэтому стоп +здесь не «бросить и доложить», а три шага по порядку. + +**1. Назови тип, которым задача оказалась.** Разрез тот же, по которому типы и +разведены: + +- **`fix`** — поведение расходится с **заявленным**: спека уже описывает верное, + и правка возвращает систему к записанному; +- **`feature`** — снаружи появляется то, чего не было: спеке нужно новое + требование. + +Тип называется прямо и с причиной. «Нужно менять спеки» без имени типа +перекладывает классификацию на человека в тот момент, когда весь материал для неё +у тебя. + +**2. Объясни человеку простым языком.** Экран текста, не больше: + +- **что просили сделать** — одной фразой из записи; +- **что нашлось** — какое поведение меняется, словами домена, а не именами + файлов и функций; +- **почему это перестало быть обслуживанием** — одной фразой: у обслуживания + поведение не меняется по определению; +- **чем задача становится** — `fix` или `feature`, с причиной из разреза выше; +- **что уже сделано** и что из этого лежит в рабочем дереве. + +Проверка на простой язык та же, что у чекпоинтов двух других сценариев: **в +тексте нет `SHALL`, нет имён файлов и функций там, где вещь называется +по-русски, и нет слов, которых нет в паспорте проекта.** + +**3. Дай два решения и жди ответа.** Их ровно два, и оба законны: + +- **переформулировать запись** — тип меняется на названный, и дальше задача идёт + **процессом своего типа**: сценарием решения, следующим прогоном. Формат записи + правит `av-dev-tasks:tasks`, а не ты: у нового типа своя схема разделов, и + готовность её проверит `ready` — той же машиной, что и на входе. Прогон + обслуживания на этом кончается, исход — «меняется спека»; +- **прекратить работу** — человек не готов расширять задачу сейчас. Исход тот + же, запись остаётся как была, вопрос записывается там, где проект держит + вопросы. + +**Третьего решения — «доделать как обслуживание» — нет.** Оно и есть то самое +молчаливое изменение поведения, против которого стоит весь разрез: под коммитом, +заявляющим «поменяли оснастку», уехала бы правка, не прошедшая ни ревью дизайна, +ни чекпоинта, и не оставившая следа в спеках. + +**Сделанное не выбрасывается ни при каком из двух решений.** Оно остаётся в +рабочем дереве незакоммиченным: при переформулировке уезжает в change следующим +прогоном, при отказе — человек решает сам, откатить или оставить. Коммитить его +сообщением про обслуживание нельзя. + +**Это единственное место сценария, где ждут ответа**, и плановым стопом оно не +становится: плановый стоп проходят все прогоны, а этот — только те, где задача +оказалась не тем, чем объявлена. Прогон, дошедший до него, стоит дороже обычного +— и это довод за проверку признака на шаге 1, а не после написанного кода. ## OpenSpec здесь не предпосылка @@ -79,6 +129,10 @@ решать, вырождается в обряд одобрения и обесценивает те стопы, где решать есть что. +**Место, где ответа всё же ждут, одно, и плановым оно не является** — стоп по +найденной дельте (раздел «Дельта нашлась по ходу»). Через него проходят не все +прогоны, а только те, где задача оказалась не тем, чем объявлена. + **Правило необратимого при этом действует полностью** (SKILL.md, «Когда спрашивать вне чекпоинта»), и здесь оно опаснее, чем кажется. Единственный сценарий без планового стопа — ровно тот, чья работа чаще прочих лезет в @@ -114,9 +168,11 @@ flowchart TD - **сделана** — определение сделанного выполнено целиком; - **не доведена** — с причиной и с записанным вопросом; названо, что именно сделано и до какой границы; -- **меняется спека** — работа оказалась изменением поведения. Стоп; сделанное - остаётся в рабочем дереве и незакоммиченным, дальше идёт сценарий решения - следующим прогоном; +- **меняется спека** — работа оказалась шире своего типа. Стоп с объяснением и + двумя решениями человека: переформулировать запись в `fix` или `feature` и + решать её процессом того типа следующим прогоном — либо прекратить. Сделанное + остаётся в рабочем дереве незакоммиченным. Доклад называет **оба**: какой тип + предложен и что человек выбрал; - **нужна разведка** — форма правки неизвестна (мажорное обновление, смена сборщика, переезд гейта на другой инструмент) **или сработал триггер ADR**: дорогой откат, намеренный отказ от очевидного подхода, пересмотр прежнего @@ -284,8 +340,13 @@ Change ты не передаёшь — его нет. ## Границы: чего обслуживание не делает - **Не меняет поведения.** Обнаружилось, что меняет, — стоп с исходом «меняется - спека». Это единственная граница сценария, у которой есть проверяемый признак, - и она же единственная, которую выгодно нарушить молча. + спека»: назвать тип, объяснить, дать два решения. Это единственная граница + сценария, у которой есть проверяемый признак, и она же единственная, которую + выгодно нарушить молча. +- **Не переписывает запись задачи сам.** Тип ты **предлагаешь** с причиной, + меняет его `av-dev-tasks:tasks` и только после ответа человека: исполнитель, + переклеивший тип на ходу, назначает себе другой процесс и другую глубину + проверки. - **Не решает, нужна ли работа.** Как и оба соседних сценария: «надо ли» — вопрос человека. - **Не нарезает пачку на задачи.** «Обновить зависимости и переписать сборку» — @@ -301,6 +362,8 @@ Change ты не передаёшь — его нет. Общее ядро доклада — в SKILL.md; сверх него сценарий обязан назвать: - **что подтвердило признак** — тип записи и то, что дельта-спек не нашлось; + дельта нашлась — **какой тип предложен, с причиной, и что человек выбрал**: + переформулировать или прекратить; - **что стало иначе для разработчика** — одной фразой, адресуясь ему, а не выдуманному пользователю; - **состав гейта до и после**, если правка его трогала; не сверялся — почему; diff --git a/av-dev-tasks/skills/tasks/references/task-chore.md b/av-dev-tasks/skills/tasks/references/task-chore.md index a1cce80..91fd320 100644 --- a/av-dev-tasks/skills/tasks/references/task-chore.md +++ b/av-dev-tasks/skills/tasks/references/task-chore.md @@ -33,6 +33,13 @@ не `chore`. Тип, оставшийся от первой формулировки, врёт ровно там, где по нему отбирают. +**Обнаружилось это уже в работе — запись переформулируется, а не дорешивается.** +Исполнитель останавливается, называет тип, которым задача оказалась (`fix` — +поведение расходится с заявленным, `feature` — снаружи появляется то, чего не +было), и человек решает: сменить тип и решать процессом того типа — либо +прекратить. Тип меняет этот скилл, а не исполнитель по ходу: у нового типа своя +схема разделов, и `ready` проверит её заново. + ## Алгоритм 1. **Проверить, что поведение не меняется.** Меняется — это `feature` или `fix`,