docs(m6): DONE-handoff — пост-аудит правки FIX-1..4 + DOC-1 (escape не сквозной через зоопарк)

Зафиксированы 4 аудит-фикса и caveat DOC-1: escape чтут только стена М2/пол М5/egress; router-gate / runtime-write-deny / судья М4 escape не знают → реальные разрушительные не пройдут до М7 (растворение зоопарка). Ожидаемо по §7.
This commit is contained in:
Дмитрий
2026-06-07 19:43:18 +03:00
parent d221ba499d
commit 8bfef418c2
@@ -123,3 +123,40 @@ a5b99eaa feat(m6): snapshot-decide — триггер снимка + чисто
28b92d90 feat(m6): enforce-snapshot — git-точка возврата перед разрушительным (fail-close)
d0e0bd18 test(m6): сквозные инварианты escape + snapshot; регрессия зелёная (2834+2)
```
---
## Пост-аудит правки (2026-06-07, отдельная сессия — аудит М6 + 4 фикса; commit-not-push)
Аудит М6 шестью осями (`audit-context-building` + `sharp-edges` + корректность логики; +комплекс М1–М6).
Вывод: архитектурно верно, швы М1–М5 целы. Внесены 4 практичных фикса (TDD RED→GREEN, регрессия
tools-only **2843 passed + 2 skip**, +9 тестов, 0 регрессий):
- **FIX-1 (G-5 egress):** `enforce-mcp-classification` печатает в блок-сообщении точную канон-строку
`… ; FLOOR-ESCAPE: mcp:<tool>:<json>` (раньше токен выводил только пол Bash/Write; egress оставался
без точной строки для AskUser → владелец не получал, что вставлять).
- **FIX-2 (единый предикат свежести):** в `escape-grant` вынесен `findOpenGrant`; `escapeGrantOpen` и
`floor-escape-consume.consumeDecision` гасят ИМЕННО открывший грант. Раньше при дублях/future-ts
consume мог пометить «не тот» грант → утечка one-shot (тест воспроизводил баг → закрыт).
- **FIX-3 (журнал escape):** `enforce-supreme-gate.runGate` пишет escape best-effort в журнал
намерений (`escape:true`), указатель НЕ двигается; сбой/отсутствие журнала escape НЕ блокирует
(escape санкционирован владельцем). Снимает будущий false-positive реконсилера «action-without-record
(обход стены)» для легитимного escape.
- **FIX-4 (уникальный снимок):** `enforce-snapshot` дефолтный id = `ts-pid-счётчик` (раньше два
разрушительных в одну ms клобберили один `refs/floor-snapshots/<id>`).
**FIX-5 (подпись гранта) сознательно НЕ делали:** в штатном «без ключа» режиме reader обязан принимать
неподписанное (иначе escape ломается у всех) → защиты нет; protected-path уже гарантирует целостность.
Спек §6 пометил её «не обязательно».
### ⚠️ DOC-1 — escape НЕ сквозной через старый «зоопарк» (важно ПЕРЕД активацией)
escape чтут **только** стена М2 / пол М5 / egress. Параллельные стражи живой среды —
`enforce-router-gate` (default-deny whitelist; блокирует мутирующий git/bash — он в этой сессии
заблокировал даже `git log`), `enforce-runtime-write-deny` (блок Write в `~/.claude/runtime`) и судья
М4 (когда активируют) — escape **не знают** и заблокируют то же действие. Значит после активации М6
реальный `git push --force` / запись в `.env` всё равно не пройдут, пока эти хуки зарегистрированы.
Полностью «дверь открывается» только когда М7 растворит/научит зоопарк (или владелец деригистрирует
router-gate/runtime-write-deny). Это **ожидаемо по §7 (YAGNI→М7)**, но держать в голове: М6 — дверь в
стене М2/М5/egress, не во всей обороне.
**Изменённые файлы (10, commit-not-push):** `tools/{escape-grant,floor-escape-consume,enforce-mcp-classification,enforce-snapshot,enforce-supreme-gate}.mjs` + их `.test.mjs`.