PROCESS.md §11.5: перед стабильным релизом — одно ревью поверхностей всей
линии бет «с нуля», без ТЗ и документов раундов, по SCOPE и USER-GUIDE.
- scripts/release-review.mjs: вход линии — прошлый стабильный тег, issue по
трейлерам в схеме RELEASE-MEMBERSHIP.json, продуктовые файлы; бриф промпта.
- .github/workflows/release-review.yml (workflow_dispatch, исполняется с dev):
prepare → model_review (модель без прав на запись, github_token #556) →
publish (docs/reviews/RELEASE-REVIEW-vX.Y.Z.md в dev токеном процесса,
индекс тем же коммитом, review-doc-guard). Повтор на тот же тег не тратит
модель, если документ уже в dev.
- release.yml: job independent-review ставит ревью в очередь сразу после
candidate, continue-on-error; ни один job выпуска от него не зависит
(решение владельца 2026-09-25).
- REVIEWER.md, AGENTS.md, DEVELOPMENT.md; тесты и четыре мутанта.
Issue: #638
User-Visible: no
- scripts/no-new-private-writes.mjs: смоки и demo/helpers/** не добавляют
записей в приватное состояние карточки (присваивание, ++/--, delete по
цепочке с сегментом _x; от this — нет) и вызовов _setMode/_openRoomEdit/
_openMarkerDialog/_openSpaceDialog. Зачёт правки по полю, перенос блока —
movedLinesByFile из no-new-any; исключение // private-ok: <причина>.
--count — остаток на HEAD. Подключён в gate:small и в шаг frontend рядом с
no-new-any, с той же базой.
- demo/helpers/hp-test.mjs: 10 операций через контрактные хуки и события
фикстуры (setMode, setTool, switchSpace, openRoomEdit, openMarkerDialog,
openSpaceDialog, setServerConfig, setLayout, input, close); ставится
launch*() из demo/serve.mjs. В бандле фасада нет.
- demo/srv/demo.html: доставка houseplan_config_updated/_layout_updated,
__pushServerConfig/__pushServerLayout; после доставки запись со старым
expected_rev — conflict, как у настоящего сервера.
- HP_SMOKE_CHECKS=1 печатает имена проверок в finish().
- smoke_area_relocation, smoke_glow, smoke_grid_snap переведены на фасад без
потери утверждений; новый smoke_test_facade доказывает каждую операцию.
- 7 мутантов, docs/TESTING.md (раздел + правило №6), PROCESS.md §2.7, AGENTS.md.
Issue: #629
User-Visible: no
Six workflows run from the default branch (issues, schedule, workflow_run):
process, process-resume, process-reconcile, mutation-gate, nightly,
process-metrics. Their bodies move to _<name>.yml (on: workflow_call); the
original files keep only triggers, run-name, permissions, concurrency and one
job `uses: Matysh/houseplan-card/.github/workflows/_<name>.yml@dev` with
`secrets: inherit`. A pipeline change becomes one commit to dev.
- caller job permissions = union of body job permissions (#556 minimum kept
per job inside the body); caller `if` repeats the body guard for process and
process-resume so unrelated events stay skipped;
- dispatch inputs forwarded via workflow_call inputs of the same names;
- _mutation-gate.yml keys evidence/marker on job.workflow_sha (the body SHA):
in a called workflow github.workflow_sha belongs to the caller in main;
- action-pins: narrow exception for this repo's _*.yml at @dev with a reason;
- preflight workflow_sync compares all six thin callers (was 3 of 6);
performance.yml excluded: its schedule judges main with main's own body;
- tests read bodies from _*.yml; new test/default-branch-workflows.test.mjs;
six mutants; PROCESS.md §10.4, AGENTS.md, REVIEWER.md updated.
Issue: #623
User-Visible: no
A pipeline doc commit carries the review document and the rebuilt
INDEX.md; while the task waits, dev receives other tasks' documents with
their own INDEX.md, and the rebase of the branch conflicts in the index
every time. 24.09 this bounced green #617, #618, #629, #642 to S6.
scripts/rebase-generated.mjs: shared rebase helper. At every stop, if ALL
conflicting paths are docs/reviews/INDEX.md (or paths the caller
resolves itself), the index is rebuilt from the directory in the stop
tree, staged, and the rebase continues; any other path aborts and
returns the full list. CLI exit 3 = refusal with paths on stdout.
Wired into process.yml «Привести ветку к dev» (helper taken from dev via
git archive; conflict/conflicts outputs, lease, ref wait and
--commit-if-stale kept), merge-candidate rebaseOnto (claude[bot]
identity, --commit-if-stale kept) and rebase-on-dev.mjs (index next to
GENERATED_ROOTS; bundle still dev copy + rebuild).
Issue: #643
User-Visible: no
Вход агента до первого файла кода стоил ≈ 26 700 слов (аудит 22.09).
- docs/process/AUTHOR.md и REVIEWER.md — выжимки PROCESS.md: каждый пункт
ссылается на раздел канона, ключевые формулировки дословные;
test/process-digests.test.mjs сверяет якоря, ссылки и правила.
- scripts/entry-cost.mjs — маршрут чтения по роли и бюджет (автор ≤ 12 000
слов, AC1); AGENTS.md «Read this first» называет те же маршруты.
- docs/STATUS.md: блок Snapshot генерирует scripts/status-snapshot.mjs
(версии — release-contract, счётчики — inventory, теги — git); feature
surface и ранние milestones перенесены дословно в docs/STATUS-FEATURES.md.
- docs/TESTING.md — действующая инструкция (684 строки, AC3); ручные
чек-листы и приложения по issue перенесены дословно в docs/testing-notes/
с индексом и тестом на полноту.
- Промпт ревьюера в process.yml читает конспект вместо пересказа правил;
машинные требования (строка вердикта, REVIEW_DOC, запрет fetch, таблица
«чем краснеет», разделы повторного раунда) сохранены и закреплены тестом.
- PROCESS.md: правила не менялись; добавлены ссылка на конспекты в шапке и
уточнение в §10.4, что ревьюер конвейера читает конспект.
- 7 мутантов в реестре.
Issue: #634
User-Visible: no
Карточка и редакторский рантайм держали ≈380 неиспользуемых импортов, 56
мёртвых объявлений и дублей типов (warm-boot, LS_*, GLOW_*, debounce,
navigate, lruRead — копии карточки в рантайме) и 112 приватных членов
карточки, которых не читал никто — делегаты `_editorRuntimeOrThrow()._x()`,
оставшиеся от выноса #425, и аксессоры glow-состояния. Всё это снято; в 9
других файлах — по одиночной ошибке. Делегаты и поля, которых касаются
браузерные смоки (`card._x(...)`), оставлены и посчитаны отдельно.
Гейт `npm run lint:unused` (scripts/unused-locals-gate.mjs, в gate:small и
Validate после сборки): `tsc --noUnusedLocals` чист, кроме приватных членов
карточки из порта HouseplanEditorHostPort / `host.` (portPrivates) и членов,
которых зовёт харнесс (harnessPrivates); храповик по шести числам
scripts/monolith-metrics.mjs против scripts/monolith-baseline.json —
delegates 260→159, portMembers 350, hostRefs 4948, portPrivates 96,
harnessPrivates 107, bundleBytes 2 510 141→2 500 387. `npm run inventory`
печатает те же числа. Заморозка 54 тестов, читающих монолит как текст
(test/monolith-text-anchors.test.mjs); PROCESS.md §2.7 — правило.
Логический исходник для контрактных тестов (test/houseplan-source.mjs)
дописывает члены рантайма без делегата в карточке — контракт продукта не
зависит от наличия заглушки. Потолки ядер и initial gzip опущены на выигрыш
(292 000 → 290 400). Бандл пересобран, три копии синхронны.
Issue: #624
User-Visible: no
Прогон 35870123732 на 49bae62e: тест «индекс свеж» покраснел на материале,
который конвейер сам же ребейзнул на dev (#614) — process.yml исполняется из
main и о `--commit-if-stale` ещё не знает; так красился бы любой раунд, пока
правка не отзеркалена, а на issue-ветках коммиты конвейера индекс ветки знать
не обязан. Свежесть судится там, где её держит конвейер: шаг preflight
`reviews-index --check` только на push в dev, в вердикте предполёта; skipped
не считается отказом. Юнит-тест байтовой свежести снят, вместо него — свидетель
на проводке. PROCESS.md §2.10: правка docs/reviews руками сопровождается
пересборкой в том же коммите. INDEX.md пересобран на текущем дереве.
Issue: #635
User-Visible: no
r2 H1: INDEX.md — снимок каталога, и ребейз ветки на dev, получивший чужие
документы ревью, устаревал его молча. Теперь `--commit-if-stale` пересобирает
и коммитит индекс коммитом конвейера после приведения к dev (process.yml) и
после ребейза кандидата (merge-candidate.mjs); тест «индекс свеж» сравнивает
закоммиченный файл с пересборкой и красит Validate при расхождении.
r2 M1: находка без заголовка — первый абзац секции, склеенный из перенесённых
строк, без маркера буллета и кода `**M1.**`; «не найдено», служебные скобки
«(унаследовано…)» — не находка. Нумерованные пункты тоже забирают перенесённые
строки. Мутант reviews-index-paragraph-tail. PROCESS.md §2.10 дополнен.
Issue: #635
User-Visible: no
scripts/reviews-index.mjs собирает docs/reviews/INDEX.md: одна строка на
документ — issue, этап, раунд, вердикт (явная строка, раздел «Вердикт»,
свободная форма хвоста; 936 из 986 распознаны), High/Medium по строке вердикта
или заголовкам находок, до шести заголовков находок. Индекс детерминирован,
не индексирует сам себя, перечисляет файлы вне схемы имён; `--check` — гейт
свежести. process.yml публикует INDEX.md тем же коммитом, что документ ревью.
docs/LESSONS.md — датированные уроки со ссылками на источники (12 записей из
аудитов и разборов недели). PROCESS.md §2.10 — где искать решения.
Тесты: разбор имён, вердиктов, счётчиков, находок; фикстурный каталог;
живой каталог (100 % покрытие, >90 % вердиктов); контракт шага конвейера.
Мутанты reviews-index-skips-self-check, reviews-index-verdict-substring.
Issue: #635
User-Visible: no
Стадия prepare спала ≈ 28 минут на раунд, пока шёл Validate с мутантами на
материале (модель работает 10–12); за неделю ≈ 420–500 job-минут простоя и
потолок бюджета стадии 55 минут.
- validate-gate.mjs: `--no-wait` — гейт диспатчит прогон, убеждается, что тот
встал на материал (#539 сохранён), и возвращает `pending` (код 2) вместо
ожидания; завершённый зелёный/красный отдаёт сразу, как прежде.
- process.yml prepare: третий исход `proceed=pending`: запечатанный маркер
`review-pending-<issue>-<run>-<attempt>` (issue, stage, branch, material_sha,
validate run) и выход; модель и интеграция не запускаются; возврат автору —
только на явном `false`.
- process-resume.yml + scripts/process-resume.mjs: на `workflow_run: completed`
Validate по ветке issue/* — если метка S7 стоит, активного прогона нет и
последний прогон оставил маркер на этот SHA, переставить S7 (HP_PROCESS_TOKEN);
новый прогон находит завершённый dispatch сразу. Без маркера не будит.
- process-reconcile.mjs: читает маркер и состояние Validate на материале;
идёт — wait, завершился/пропал без продолжения — retry; без маркера — прежний
escalate. Общий loadSealedArtifact, экспорт processRuns/artifactNames.
- preflight сверяет process-resume.yml между main и dev наравне с process.yml.
- Тесты: validate-gate (4), process-resume (8, включая контракт трёх workflow),
process-reconcile (2); мутанты gate-no-wait-still-sleeps,
resume-wakes-round-without-marker, resume-ignores-active-run,
reconcile-wakes-pending-while-validate-active. PROCESS.md §10.4, AGENTS.md.
Issue: #636
User-Visible: no
`mutantsRequested` отвечает true лишь на PR и `workflow_dispatch mutants=true`
(конвейер ревью, слияние кандидата). Трейлер `Release:` и `full=true` включают
тяжёлые гейты — смоки, golden, performance_smoke — но не мутантов: к бете каждая
задача прогнана ими на ревью и на слитом после ребейза кандидате, ночь покрыта
полным реестром (mutation-gate.yml, #513), а ручной полный прогон ради
артефакта эталонов и приёмка эталонов с трейлером на ветке задачи платили
шестью job впустую. `schedule` мутантов тоже не запрашивает.
Политика release в ci-proof — `mutants: false`: иначе proof кандидата беты
без запрошенных mutant-jobs объявлялся бы stale. review и merge по-прежнему
требуют шесть исполненных job (#541).
Тесты: #510 AC1 переписан под новый список, ci-proof — release без мутантов
green, лёгкий stale, review/merge без запроса stale. Мутанты протокола:
`mutants-run-on-every-push` перепривязан, новые `mutants-run-on-beta-candidate`,
`mutants-run-on-full-dispatch`, `release-proof-demands-mutant-jobs`.
PROCESS.md §10.4, AGENTS.md, docs/TESTING.md, комментарии workflow.
Issue: #601
User-Visible: no
`release-zip.yml` выкладывал `houseplan.zip` в ту же секунду, когда релиз
становился публичным — до Validate, Full Performance и E2E; `release.yml`
параллельно пересобирал `houseplan-card.js`, а E2E требовал публичного ZIP,
чтобы вообще начаться. Публикаторов было четыре, порядок — ни одного.
Теперь публикатор стабильных один — `release.yml`: закрепить SHA → релиз в
черновике (опубликованный руками немедленно возвращается в черновик) → гейты
на SHA (трейлер `Release: <tag>`, контракт `--stable`, Validate, Full
Performance, E2E на коммите-кандидате через tarball codeload) → одна сборка,
`git archive` ZIP из того же дерева, `SHA256SUMS` → загрузка в черновик →
публикация → скачать публичное и сверить с паспортом → анонс. Dispatch на
публичный тег — ремонт: догружается только недостающее, расходящийся хеш —
отказ. Беты кладут тот же паспорт; локальный публикатор больше не ждёт
републикаторов — их нет.
- `.github/workflows/release-zip.yml` удалён
- `scripts/release-assets.mjs` — паспорт ассетов (`sums`/`check`), чистые
функции под юнитами
- `scripts/e2e-gate.mjs --ref=<sha>` — под тестом кандидат, `--tag` только
для выбора `upgrade_from`
- `scripts/release-contract.mjs --stable`
- мутанты: независимый публикатор, снятая зависимость от гейта, релиз без
возврата в черновик, `--clobber` в ремонте, E2E на теге, слепой паспорт
Issue: #540
User-Visible: no
The spec file solved exactly one problem — proving that a review verdict
was passed on a given text — and created two: docs/specs/README.md
conflicted between parallel tasks and served as a second, stale status
dictionary, and every spec edit cost a commit, a push and a label. The
proof moves into the pipeline.
- review-doc-guard: normalizeIssueBody / issueBodyDigest (CRLF, trailing
whitespace, trailing newlines), the anchor line `Тело issue: <sha256>`,
anchorIssueBodyFrom, and issueBodyChanged — the finding "the spec
changed after a green spec review", judged against the pipeline's own
record in the last green SPEC-REVIEW, never against prose.
- reusableGreenVerdict takes the current digest: reuse (#499) skips the
model entirely, so without this a spec edit between rounds would pass
unseen. Documents without the record (the whole backlog) keep judging
by tree.
- process.yml: the material step reads the body with `gh issue view` in
the same run that fixes the material — the event snapshot describes a
text the reviewer may never see; the digest goes into the anchors, into
reuse and, when it differs, into the reviewer's prompt.
- process-gate: rule 3 judges the text (a `## ТЗ` heading or an AC1) with
the archived file still accepted; adding a new file under docs/specs/
warns — the directory is frozen.
- task-packet reads AC from the body first, the archived file second.
- PROCESS.md §2.3/§5/§7.1/§7.3/§10.5, AGENTS.md and docs/specs/README.md
say so; the index table is gone with the long-standing §7.3 debt.
Mutants: review-anchor-drops-issue-body, review-ignores-changed-spec-body,
reuse-ignores-changed-issue-body, process-gate-requires-spec-file.
Issue: #517
User-Visible: no
Code review r3 (M1): realOps.releases() swallowed a failing `gh release
list` into an empty list, so a fine-grained token scoped to houseplan-e2e
alone would have dispatched with upgrade_from=stable — the tag onto
itself — and the red run would look like the bug 4143f998 already fixed.
The call now throws like dispatch() and lands in the same catch: result
`error` with the token hint, which now names both repositories. L4:
PROCESS.md says who dispatches and who waits.
Issue: #514
User-Visible: no
The stable gate proved Validate and Full Performance on the exact SHA but
never ran the release in Home Assistant itself. houseplan-e2e installs
the release's houseplan.zip — the bytes HACS ships — into HA in docker
and walks the sidebar page, dashboards, roles, PDF, restart and the
stable→tag upgrade. release.yml now dispatches e2e.yml on the tag for
`!prerelease` releases and waits for it (scripts/e2e-gate.mjs, modelled
on validate-gate.mjs): the gate recognises its own run by `HP <tag>` in
the job names, ignores foreign dispatches, and reports red / missing /
cancelled / token error with the run link. Betas are untouched.
Mutants: release-ships-on-red-e2e, release-trusts-foreign-e2e-run.
Issue: #514
User-Visible: no
Golden frames carried the card version text (about, version banner,
support/export previews), so every beta bump re-accepted up to 20
baselines that had not visually changed. The version now reaches the DOM
and stand requests through displayVersion() (src/card-version.ts); the
golden harness pins window.__HP_VERSION_OVERRIDE__ = '0.0.0-golden'
before the card is created. CARD_VERSION literals stay where the release
contract reads them; cache-busting and the console banner keep the literal.
Docs screenshots: `npm run docs:accept -- --identical` re-captures
locally, compares decoded RGBA pixels with the committed frames inside
Chromium (scripts/png-identical.mjs) and, only when every frame is
identical, refreshes the manifest fingerprints and captureScriptSha256;
bytes stay, any difference refuses with a per-frame count. First run on
this tree: 11/11 identical, manifest refreshed.
Mutants: version-seam-ignores-override, docs-identical-accepts-any-frame.
Issue: #512
User-Visible: no
Validate ran the three "Мутанты по диффу" shards on every push of every
branch: 48 of 56 job-hours on 08–09.09, most of them cancelled by the
next push. Mutants now run when asked — pull requests, the nightly
schedule, a push carrying a `Release:` trailer, or a dispatch with
`mutants=true` (classify-changes.mjs → `mutants_requested`); an ordinary
push runs the light checks only.
The proof moves to where it is consumed. process.yml gets a gate after
the #499 reuse step: on the code stage it looks for a dispatch Validate
run on the exact material SHA whose mutant jobs executed and passed
(scripts/validate-gate.mjs); none → it dispatches one and waits; red or
missing → the task goes back S7→S6 with the run link and the review
cycle is not spent. Spec stage and the reuse fast-path skip the gate
(`proceed=true`); all later steps branch on `proceed` in place of the
old conflict conjunct only. merge-candidate.mjs dispatches Validate on
the pushed candidate and waits for that dispatch run.
PROCESS.md/AGENTS.md: review does not start on red code; one handoff —
one push.
Mutants: mutants-run-on-every-push, review-starts-on-red-validate,
review-trusts-push-run-without-mutants, merge-waits-push-run-without-mutants.
Issue: #510
User-Visible: no
Windows portability (the three red tests on the owner's machine at green CI):
- scripts/spawn-portable.mjs: isMainModule via pathToFileURL (the
`file://${argv[1]}` form gives file:///C:/C:/... and the CLI stays silent);
portableCommand — a shell only for npm/npx/.cmd, node and git run directly
(spawn via shell dropped the quotes of `node -e "…"`). Applied to
classify-changes, mutation-gate-report, review-doc-guard, check-inputs,
merge-candidate, gate-small, rebase-on-dev.
- the rebase-on-dev test pins core.autocrlf=false / core.eol=lf through
GIT_CONFIG_* for its temp repository instead of touching the user's git
config; test/windows-portability.test.mjs forbids both anti-patterns.
Pins: scripts/toolchain-pins.mjs reads Node/Python from validate.yml, the HA
stack from tests_backend/requirements.txt, Playwright/Chromium from the
lockfile — no second dictionary; `npm run toolchain:check` compares the
machine; .nvmrc/.python-version are derived and tested equal;
scripts/wsl-setup.sh provisions WSL/Linux with those pins.
scripts/task-packet.mjs: one derived view of an issue (status, rights, owner
decisions, branch vs dev, Validate on the tip, previous verdict with recorded
tree, AC → evidence, unwitnessed). scripts/wait-verdict.mjs: polls labels,
pipeline comments and optionally Validate, prints only on state change, exit
0/3/4, writes nothing.
gate:small --smokes: after build the browser phase runs bundle-sync and then
the directly matched and registered smokes, two at a time; broad matches stay
with the reviewer. package.json changed, so the bundle is rebuilt here.
Issue: #496
User-Visible: no
Review pipeline (process.yml):
- concurrency moves from the workflow to the guard/review jobs and the guard
runs only for S4-spec-review / S7-code-review. Any other label used to enter
the issue's concurrency group and evict the pending review run (sample of
150 runs since 2026-09-01: 92 empty guard-only runs, 30 cancelled).
- the guard reads the issue's current labels instead of the event snapshot; a
label removed before the run starts is a withdrawn request, no comment.
- a green verdict is re-applied without calling the model when the latest
review document carries the pipeline-recorded verdict `green`/High 0 and the
tree differs from its anchor in nothing outside docs/reviews/** (#437 r4
re-reviewed an unchanged tree for 7 minutes). The verdict from
structured_output is now written into the anchor block for that purpose.
- the reviewer is pinned to the captured material SHA in the prompt; the
broken escaping in the "merge cancelled" comment (empty SHAs) is fixed.
Mutation gate: nine browser guards started with `npm run bundle:sync` although
the runner already builds the mutant bundle — a second rollup plus a
`tsc --noEmit` that fails on a non-strict mutant before the smoke even runs.
Prefix removed; `--check` refuses guards that build the bundle themselves.
Docs: SCOPE (Project v2 dropped, three editors), STATUS (#437 merged, HACS zip
automated), USER-GUIDE ru/en (static card shows live states; kiosk double tap
on free background fits all), #34 → #425 references, #367 named as closed in
bundle-budget messages, PROCESS §10.4 and AGENTS.md describe the controller.
Issue: #499
User-Visible: no
Классификация changes вынесена в scripts/classify-changes.mjs (выходы
perf_iso/perf_interaction, fallback --all). performance_smoke добавляет
large-house-isometric-v1 при правке src/iso-* и large-house-interaction-v1
при правке живого пути, по 3 образца против hardMaxMs полных профилей
(budgets-*-smoke.json). Набор профилей входит в ключ reuse. PROCESS.md §8.
Issue: #473
User-Visible: no
Канон требовал назвать SHA предыдущего раунда и считал ненайденный SHA
находкой. Механика теперь даёт больше: конвейер дописывает в документ дерево
материала и блоб каждого ТЗ — их ребейз не меняет, потому что git адресует их
содержимым (issue #416).
Отсюда правка по существу: неразрешимый SHA сам по себе перестаёт быть
находкой. Ветку задачи между раундами перебазируют, сквошат или удаляют — по
корпусу ревью таких объявлений 98 из 804, и объявлять это дефектом значит
объявлять дефектом обычную работу. Материал в таком случае берётся по якорям,
и команды приведены прямо в пункте.
Находкой осталось то, чем #413 и был: SHA, мёртвый уже в момент публикации.
Он означает, что значение сняли до amend или rebase и не сверили перед выводом
отчёта, как требует §7.2. Такую публикацию конвейер теперь останавливает сам.
Issue: #416
User-Visible: no
В src/** сейчас 1034 вхождения явного any в 49 файлах — больше, чем называл
аудит (330), потому что монолит с тех пор разделился и его обвязка уехала в
houseplan-editor-runtime.ts. Разовая замена такого объёма — месяц риска ради
нуля пользовательской ценности, поэтому долг снимается при плановом извлечении
подсистем (#34). Задача гейта одна: не давать долгу расти.
Судятся только добавленные строки диапазона. Изменённая строка со старым any
выглядит в диффе добавленной, и это намеренно: тронул — либо типизируй, либо
обоснуй на той же строке `// any-ok: <причина>`. Голый маркер, пустая причина и
шаблоны вроде todo, hack, потом не проходят.
Ложных срабатываний нет по построению, а не по старанию: текст разбирается
парсером TypeScript, и нарушением считается узел AnyKeyword. Регулярка по строке
ловила бы слово any в прозе внутри шаблона html и в комментариях; здесь
комментарии, строковые литералы, многострочные шаблоны и идентификаторы
company, anyOf, manyRooms узлами такого вида не являются вовсе.
Проверено исполнением на настоящем дереве, а не только юнитами: пробные коммиты
в src/wall-thickness.ts показали, что добавленный any падает с файлом и строкой,
типизированная строка в файле с 122 старыми any проходит, any-ok с конкретной
причиной проходит, а голый и «todo» — нет, и что any в прозе, строке и
идентификаторах не даёт ни одного срабатывания.
В job frontend checkout получил полную историю без блобов: diff-aware проверке
нужен диапазон, а содержимое старых ревизий — нет.
Заодно закрыта ловушка в test/validate-workflow.test.mjs: имя job искалось через
indexOf(' frontend:'), а эта строка встречается внутри ` frontend: ${{ ...
}}` в outputs job changes, поэтому срез уходил не туда. Теперь имя ищется с
начала строки.
Четыре мутанта проверены руками, два добавлены в реестр: гейт, судящий все
строки, и гейт, принимающий голый маркер.
Issue: #342
User-Visible: no
Прежде полный трек был бесплатен, а выбор лёгкого требовал обоснования. Цена —
2.9 ревью-документа на задачу и до шести на одну issue (#329, #316, #290), при
том что Medium-находки всё равно чинятся в той же задаче без отдельного цикла.
Порог не изменился: критерии §5 те же и обязательны все одновременно. Изменилась
сторона доказательства — в S2-analysis называется критерий, который задача НЕ
проходит, если идёт полным треком. «Обычный трек» без названного критерия
обоснованием не является.
Правка идёт и в AGENTS.md: там трек описан как «shortcut для мелкой работы», а
это ровно та формулировка, из-за которой полный трек остаётся умолчанием на
практике. AGENTS.md стоит вторым в порядке доверия, поэтому без него правка
канона поведение не меняет.
Бюджет четырёх циклов, арбитраж владельца, обязательность ТЗ на полном треке и
правило «ревью до мержа» не тронуты.
Issue: #338
User-Visible: no
Правило 10 гейта (#311): DoR сверяется с моментом НАПИСАНИЯ кода — authorDate
коммита класса A не может предшествовать первому labeled-событию S5-ready+
из timeline issue; продвижение метки больше не прячет нарушение, ребейзы
конвейера его не смывают (authorDate переживает их). Проверка вторичная к
правилу 8: недоступный timeline — warn, правило 8 остаётся fail-closed.
LOG_FORMAT несёт authorDate третьим полем (append-совместимо).
Шаг слияния конвейера (#312): сливается только проверенный SHA — вершина
ветки сверяется с материалом ревью (допустим ровно один doc-коммит публикации
с диффом только docs/reviews/ поверх); расхождение отменяет слияние с
возвратом в S6-in-progress тем же путём, что конфликт (инвариант «метка
меняется всегда» сохранён). PROCESS.md §2.7 фиксирует правило «вердикт
привязан к SHA» и для ревьюера.
Issue: #311
Issue: #312
User-Visible: no
Section 4 now says what the pipeline does: a cycle is a verdict with
blocking findings followed by a return to the author, so a green verdict
consumes nothing — the case that cost #225 an arbitration after a failed
merge forced a rebase and a third attempt.
The canon also separates the two quantities the verdict line carries. The
attempt number names the review document, because two runs sharing a
number would overwrite each other's artefact; the budget counts blocking
cycles only. That is why the document threshold in the process gate sits
above the cycle limit, and why the guard reports a recount of review-4
rather than removing the label itself.
Issue: #227
User-Visible: no
The reviewer prompt was identical for every round, and the canon said
nothing about the scope of a repeat pass, so r2 re-derived the product
framing and re-checked acceptance criteria the fix never touched: the r2
pass on #150 cost a full pipeline run over one line in a test fixture.
From the second cycle on, the subject is the delta against the SHA the
previous verdict was given on: each earlier finding must be shown closed
by a line of code or text, only the criteria the delta can reach are
re-verified, and whatever is carried over is listed with the round and SHA
it came from. Cheap gates still run every round.
The scope shrinks, the strictness does not. A fix can break a criterion an
earlier round accepted — that is how regression #102 happened — so the
boundary is the findings plus everything the delta can reach, and a
non-local delta (a rebase onto a moved dev, a behaviour contract change, a
new subsystem) still gets the full pass.
Issue: #214
User-Visible: no
Filing and servicing a separate issue costs far more than fixing a small
problem in place — the owner's call of 2026-08-19 (#202). A Medium finding
inside the task's scope no longer becomes its own issue: with no High
findings the verdict is yellow, the author fixes it and the fix passes
another review cycle. Only an out-of-scope Medium is still filed
separately, because foreign scope is never patched from a task branch.
Applied to the canon (PROCESS.md), the reviewer prompt in process.yml and
AGENTS.md; the verdict format now writes "Medium: N -> in-task | #NN".
Issue: #202
User-Visible: no
The analyst used to ask the owner to confirm every estimate and waited for an
answer on each point. Most issues are unambiguous, and most of that waiting
changed nothing — the owner's own measure is that seven issues in ten should
travel from S1-new to a finished spec without a single question.
Section 2.2 flips the default. Estimates, type, priority and track go on as
labels immediately; the analysis comment is a notification, not a request —
the owner's silence is consent, his disagreement is a label edit, and neither
stops the work. The analyst moves the issue to S3-spec himself. The only
questions that ever reach the owner are product questions, asked at the spec
stage in one batch with defaults and blocked, and only when the spec cannot be
written without the answer; anything that can wait for the spec waits, anything
that does not block it becomes a recorded assumption instead. The one full stop
left in analysis is a genuine SCOPE conflict, where the analyst proposes
rejection and the owner decides.
Issue: #114
User-Visible: no