Commit Graph

2042 Commits

Author SHA1 Message Date
Дмитрий aa94dabc5b docs(router-mentor): план реализации блока H (карточки + конфликт-рёбра)
Bite-sized TDD-план: Task1 G-E мех-правка, Task2 чистый чекер card-coverage,
Tasks 3.1-3.20 авторинг 86 карточек по батчам, Task4 конфликт-рёбра (§9+ADR),
Task5 живой инвариант m3e (последним → GREEN), Task6 гейт закрытия.
Исполнение инлайн (субагенты запрещены). commit-not-push.

coverage: skill:writing-plans
2026-06-08 18:07:22 +03:00
Дмитрий 48d0594a39 docs(router-mentor): H-design — вложены находки аудита достаточности (G-A/B/E/G/H)
Аудит «достаточно ли паспорта для роутера и судьи» (audit-context →
variant-analysis → sharp-edges → verification). Вердикт: схема достаточна,
новое поле не нужно. Вложены 5 находок: G-E (страж дрейфа инертен при
path=="" — точечная мех-правка), G-A (разделитель близнецов в capabilities),
G-B (инвариант «минимум содержания»), G-G (норма вход/выход), G-H (инвариант
резолв+симметрия). G-F/G-C/G-D отложены. commit-not-push.

coverage: direct:brainstorming-author
2026-06-08 18:03:17 +03:00
Дмитрий ce8d9c3bd8 docs(router-mentor): H-block design — node cards (R-11) + conflict edges (R-12)
Дизайн блока H реестра хвостов эпика «роутер-наставник»: наполнение графа
скилов данными — 86 карточек-контрактов (per-node, skill=slug) + явные
конфликт-рёбра (Tooling §9 + ADR, двусторонние) + инвариант покрытия (TDD).
Механику 3-A/3-B/3-C/3-D не трогаем. commit-not-push.

coverage: skill:brainstorming
2026-06-08 17:43:03 +03:00
Дмитрий c6ceee8ac5 docs(router-mentor): сводный реестр хвостов эпика до боевого режима
Свод всех отложенных пунктов «роутер-наставник / реинжиниринг мозга»
(7 машин + router-discipline + периферия мозга + граф скилов): блоки
H/A/B/C/E/F/G, критический путь к продакшену, колонка «кто закрывает»
(Claude / владелец). Read-only сбор, ничего не чинится. Главный
недостающий кусок — карточки узлов (2 из ~86) + конфликт-рёбра (0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:40:40 +03:00
Дмитрий f69c98e274 docs(m7): build-handoff #5 — Фазы 4/5/6/7-код СОБРАНЫ, остались шаги владельца + переезд Ф8
Сменяет handoff #4. Готовый промт для новой сессии + полное состояние: 15 коммитов
764a4192..fc4ee350 (Ф4 8 / Ф5 2 / Ф6 2 / Ф7 3), регрессия 3090→3163+2 без регрессий,
commit-not-push. Детальные шаги ВЛАДЕЛЬЦА: (А) завершить ИИ-проводку судьи (реальный
транспорт runJudgeGate + ключ/флаг/обкатка shadow→block), (Б) Фаза 8 переезд (регистрация
М1–М6 в settings.json + увольнение v4-зоопарка + тест-гейт §9.2 + откат). Цепочка скилов,
квирки, якоря коммитов — для подхвата следующей сессией.
2026-06-08 15:07:01 +03:00
Дмитрий fc4ee35021 feat(m7-phase7): доска Ф6 — judgeMode ← judgeGateMode() (реальный режим судьи: inert до активации)
CLI status-md-generator передаёт в доску «кто на посту» реальный режим судьи через
judgeGateMode() вместо хардкода 'inert'. До активации владельцем (флаг+ключ) → 'inert'
(видимое поведение не меняется); после активации доска покажет shadow/live-block.
Структурный тест фиксирует проводку (импорт + judgeMode: judgeGateMode(), не хардкод). 51/51 GREEN.
2026-06-08 14:46:12 +03:00
Дмитрий 7b46bb26a2 feat(m7-phase7): enforce-judge-gate mode-aware + finalGate + runJudgeGate seam + live fail-CLOSE (§8)
Обёртка судьи переписана с {active}-shadow-заглушки на mode-aware: decide({mode,verdict,
floorBlocked}) — inert/shadow → allow ($0/D28 тихий); live-block → finalGate (судья GO И пол
чист → allow; иначе block; битый вердикт → NO-GO, сомнение→блок). runJudgeGate — owner-seam
(§8 последняя фаза: реальный llmCall-транспорт + извлечение продукта подключает владелец; до
этого нейтральный GO wired:false — flip mode=block без транспорта НЕ кирпичит). main:
inert/shadow → allow fail-open ($0); live-block → exitDisciplineDecision (fail-CLOSE, судья жив).
7/7 GREEN. Инертно до активации владельцем.
2026-06-08 14:44:35 +03:00
Дмитрий cd69bea572 feat(m7-phase7): judgeGateMode — inert/shadow/live-block (§8, default shadow D28; рубильник важнее режима)
Новый резолвер режима судьи М4 в judge-gate-config: inert ($0, нет флага/ключа) / shadow
(active, логирует не блокирует — D28 «сперва тихо») / live-block (active + ROUTER_MENTOR_JUDGE_
MODE=block, блокирует на NO-GO). Рубильник judgeActive важнее режима: MODE=block без флага/ключа
→ всё равно inert. Default при активации — shadow (рекомендуемая обкатка §11). 9/9 GREEN.
2026-06-08 14:42:52 +03:00
Дмитрий 1227ec6668 feat(m7-phase6): доска «кто на посту» (computeGuardBoardBlock) — манифест М1–М6 + режим судьи + ПОСТ ПУСТОЙ (§7)
Новый чистый computeGuardBoardBlock в status-md-generator: read-only снимок обороны М1–М6 из
checkManifest (registered/missing) — missing → «⚠️ ПОСТ ПУСТОЙ» (нельзя ложно объявить protected,
SE-B), + режим судьи М4 (пока inert; live — Ф7) + счётчики недавних escape/блоков. Врезан в
renderStatus сразу после таблицы контролёров C1–C6; CLI читает .claude/settings.json (fail-quiet
→ {}). GUARD_LABELS маппит хуки на машины М1–М6. Read-only, ничего не блокирует. 49/49 GREEN.
2026-06-08 14:28:56 +03:00
Дмитрий 02eae97026 feat(m7-phase6): SE-B — DEFAULT_REQUIRED_HOOKS до полного М1–М6 (+М4 judge-gate, М6 snapshot/escape, М1 журналер)
floor-manifest-check.DEFAULT_REQUIRED_HOOKS расширен с 5 (пол+стена+3 exfil-стража) до 9 —
+enforce-judge-gate (М4), +enforce-snapshot и +enforce-floor-escape-consume (М6), +enforce-
skill-journaler (М1). Раньше доска рапортовала бы «protected» при незарегистрированных М4/М6
(SE-B). Теперь «ПОСТ ПОЛНЫЙ» = весь контур М1–М6. WARN-only (сигнал, не блок, Δ8). 13/13 GREEN.
2026-06-08 14:26:57 +03:00
Дмитрий b8b1601b51 feat(m7-phase5): decide §6 — ЗАКОН требует escape владельца, КАРТА — claude-md-management (build-loop SE-D)
decide переорганизован: escape-allow → контент-слои (recovery/suspicious/fake-rule, defense
для всей нормативки, сохраняют reason) → §6 classification (LAW non-escaped → block «требует
escape владельца, скил недостаточен») → CARD-поток (skillActive + judge + H3-degradation).
ЗАКОН (Pravila/PSR/Tooling + ad-hoc дисциплинарный исходник + контент-правка правил) больше НЕ
проходит по одному claude-md-management-скилу — только escape. КАРТА (CLAUDE.md/memory) —
прежний скил-канал. build-loop sealedPlanCoversEdit (Ф8 live через plan-lock). Tooling-тест
обновлён под §6; +4 §6-теста. 48/48 GREEN.
2026-06-08 12:49:01 +03:00
Дмитрий f3d91cfce5 feat(m7-phase5): classifyNormative — детерминированный КАРТА/ЗАКОН + build-loop SE-D (§6)
Новые чистые экспорты в enforce-normative-content-rules: isDisciplineSourcePath (исходники
машин М1–М6 по префиксам enforce-/judge-/floor-/escape-grant/action-journal/receipt-/
shell-content-rules/plan-lock/classify-destructive/path-normalization), contentTouchesLaw
(контент правит правила/дисциплину), classifyNormative → {kind:'CARD'|'LAW'}. КАРТА =
CLAUDE.md/MEMORY.md/memory; ЗАКОН = Pravila/PSR/Tooling + дисциплинарный исходник ВНЕ плана +
контент-правка правил; build-loop: дисциплинарный исходник ПОД sealed-планом → КАРТА; сомнение
→ ЗАКОН. Тотален (null guard). Интеграция в decide — Task 2. 44/44 GREEN.
2026-06-08 12:46:46 +03:00
Дмитрий 392a1aaeba test(m7-phase4): §12 whole-phase инвариант-гейт — анти-регресс поглощённой дисциплины
Lock-in тест над поглощённой дисциплиной Фазы 4a/4b (coverage/todowrite/rationalization +
self-debrief в манифесте): fail-CLOSE (exitDisciplineDecision, нет fail-open catch→block:false),
escape≠override (нет findOverride-вокабуляра), нет controller-text→allow (text-bypass вырезан,
Класс 1), манифест-членство (Ф6 self-check). Scope только поглощённые 4a/4b — не ещё-не-
поглощённые (memory-coverage/branch-switch/verify-* retire Ф8). 16/16 GREEN. Закрывает Фазу 4.
2026-06-08 12:28:31 +03:00
Дмитрий 3d3cc41215 feat(m7-phase4c): Гейт-2 planGateSteps/runPlanGate (sealed план-требование) + Гейт-3 verify absorption proof (§4.2)
Гейт-2 combiner (зеркало criterionGateSteps): runPlanGate = specToPlanCoverage + k5CriterionCheck
через runGateLadder. Поглощает tdd-gate Rule #6 «план перед prod-кодом» в ЗАПЕЧАТАННОЙ форме
(покрытие sealed-плана + критерий значимого шага), без Класс-1 text-mention hasPlanIndicator.
Синергия с М2-стеной. Гейт-3 absorption-proof: runCriterionGate засчитывает только ПОДПИСАННЫЙ
зелёный по критерию (расписка М5), отвергает само-написанный sentinel. Live-wiring обоих — Ф7;
retire tdd-gate/verify-* — Ф8. 43/43 GREEN.
2026-06-08 12:26:34 +03:00
Дмитрий a67d2014fa test(m7-phase4b): decomposition покрыт existenceCheck Гейт-1 через журнал (§5 coverage-map)
Proof покрытия: обещанный планировочный навык, не вызванный по журналу (extractSkillCalls),
→ existenceCheck.missingSkills непуст → NO-GO. Доказывает, что Гейт-1 М4 ловит скрытое
дробление через журнал-факт ДО retire no-op enforce-decomposition-detector (Ф8). Live-wiring
«обещанные навыки ← журнал» в judge-gate — Фаза 7. 39/39 GREEN (примитивы уже построены).
2026-06-08 12:21:12 +03:00
Дмитрий e048072093 feat(m7-phase4b): enforce-rationalization-audit fail-OPEN → fail-CLOSE (exitDisciplineDecision, §2.1 Класс 2)
main конвертирован с fail-OPEN (catch→block:false) на fail-CLOSE через exitDisciplineDecision
(throw/малформ → блок, анти-SE2). decide/audit/паттерны/halt-counter (priorFlagCount≥2) —
без изменений; язык-детектор остаётся мягким сигналом (flags), блок только halt-counter'ом.
Структурный тест сверяет наличие exitDisciplineDecision + отсутствие fail-open catch. 37/37 GREEN.
2026-06-08 12:20:10 +03:00
Дмитрий bc5a111dca feat(m7-phase4b): rationalization + self-debrief в FAIL_CLOSE_DISCIPLINE_HOOKS (манифест Ф6)
Обе Stop-дисциплины Фазы 4b зарегистрированы в манифесте fail-CLOSE. self-debrief уже
fail-CLOSE поведенчески; rationalization конвертируется отдельным коммитом (Task 2).
Манифест-тест (for-of) сверяет наличие обоих. 89/89 тестов хелперов GREEN.
2026-06-08 12:18:51 +03:00
Дмитрий 6616cdfe14 feat(m7-phase4a): coverage-verify + todowrite-skill-verifier в FAIL_CLOSE_DISCIPLINE_HOOKS (манифест Ф6)
Оба поглощённых дисциплинарных стража Фазы 4a добавлены в FAIL_CLOSE_DISCIPLINE_HOOKS —
манифест-самопроверка Фазы 6 потребует их регистрации. Манифест-тест (for-of) сверяет
наличие обоих. 87/87 тестов хелперов GREEN.
2026-06-08 11:10:41 +03:00
Дмитрий 7f5dee880f feat(m7-phase4a): todowrite-skill-verifier — журнал-факт session-scope + fail-CLOSE + PreToolUse (§4.2)
Выполненный todo, claim'ящий Skill, теперь сверяется с ЖУРНАЛОМ вызовов (extractSkillCalls,
канал М1) вместо transcript-извлечения. Session-scope осознанно (выполненный todo мог
закрыться в прошлом ходе — отличие от coverage, которое turn-scoped). decide получает
journalSkillCalls; main грузит журнал через loadJournal+extractSkillCalls, обёрнут
exitDisciplineDecision (fail-CLOSE Фазы 0). Переориентирован на PreToolUse-семантику
(предотвращение, §4.2 [Pre]; регистрация matcher — шаг владельца Ф8). 5/5 тестов GREEN.
2026-06-08 11:08:56 +03:00
Дмитрий 764a419219 feat(m7-phase4a): coverage-verify — журнал-факт K2 (turn∩journal) + fail-CLOSE + снят override (§4.2)
coverage skill:X теперь требует X в ПЕРЕСЕЧЕНИИ «Skill-tool_use этого хода ∩ журнал
вызовов» (turn-scope от границы хода transcript, факт от журнала М1 через skillTakenByJournal
K2). Не по строке coverage: — Класс 1 закрыт; turn-scoping без false-pass (X из прошлого хода
в журнале, но не в transcript этого хода → block). direct/node/chain/hook/agent приняты на
этом слое (журналом не верифицируемы, §4.2). main обёрнут exitDisciplineDecision (fail-CLOSE
Фазы 0). Override-вокабуляр снят (§12 escape≠override). 9/9 тестов GREEN.
2026-06-08 11:07:35 +03:00
Дмитрий 33cf0f7db5 docs(m7): build-handoff #4 — Фазы 0/2/3 собраны + Фаза 4 SCOPED, промт для новой сессии 2026-06-08 10:47:41 +03:00
Дмитрий a10e671cef docs(m7): SCOPED план Фазы 4 — поглощение дисциплины в М4 (§4.2, под-фазы 4a/4b/4c) 2026-06-08 10:42:15 +03:00
Дмитрий b69fdc5dfc docs(m7): план Фазы 3 — skill-журналер + seed-allow реактивных навыков (SE-K, §4.2/§12) 2026-06-08 10:37:32 +03:00
Дмитрий d030fe82b9 feat(m7-phase3): enforce-skill-journaler в FAIL_CLOSE_DISCIPLINE_HOOKS (P-7, манифест Фазы 6) 2026-06-08 10:36:42 +03:00
Дмитрий a9a43ed71a feat(m7-phase3): SEED_SKILLS +реактивные дисциплинарные навыки (SE-K — стена не рубит вне плана) 2026-06-08 10:35:33 +03:00
Дмитрий 1b66fd2076 feat(m7-phase3): enforce-skill-journaler — PostToolUse(Skill) журнал op:Skill + мост K2 (SE-K) 2026-06-08 10:34:19 +03:00
Дмитрий 467f2edddf docs(m7): план Фазы 2 — escape-survivability полная (правило 7б,в + §6 escape-honor) 2026-06-08 10:30:00 +03:00
Дмитрий 199dc04db0 feat(m7-phase2): supreme-gate panicEscapeDecision — escape переживает сбой сетапа main (правило 7б) 2026-06-08 10:28:43 +03:00
Дмитрий 4a383c5465 feat(m7-phase2): normative-content-rules чтит escape — §6 канал правки ЗАКОНА (правило 7в) 2026-06-08 10:25:00 +03:00
Дмитрий 7b51f54f1c feat(m7-phase2): read-path-deny чтит escape владельца (правило 7в) 2026-06-08 10:21:34 +03:00
Дмитрий 2294ed4ef8 feat(m7-phase2): enforce-floor panic-ветка — escape переживает throw floorDecide (правило 7б) 2026-06-08 10:19:48 +03:00
Дмитрий 2ae40924eb feat(m7-phase2): escapeAllowsEvent — panic-предикат escape-survivability (правило 7б) 2026-06-08 10:17:43 +03:00
Дмитрий b7a89e783f docs(m7): план Фазы 0 — fail-CLOSE-карвут + escape-survivability примитивы 2026-06-08 10:08:09 +03:00
Дмитрий a80c6098d5 fix(m7-phase0): disciplineOutcome строгий fail-CLOSE на малформ-возврат (sharp-edges) 2026-06-08 10:07:52 +03:00
Дмитрий 6ef4fe95b9 feat(m7-phase0): disciplineOutcome fail-CLOSE + P-7 списки + контракт helpers:7 (правило 1) 2026-06-08 10:02:43 +03:00
Дмитрий d1ff6019de feat(m7-phase0): canonicalAction тотальна — внешний try + pathNormalizeSafe (правило 7а) 2026-06-08 09:59:29 +03:00
Дмитрий 90f723732e feat(m7-phase0): pathNormalizeSafe — тотальный normalize (правило 7а) 2026-06-08 09:57:41 +03:00
Дмитрий 2365262848 docs(m7): build-handoff #3 — Фаза 1 content-floor собрана + PS single-source (HEAD 8a35f641)
Сменяет build-handoff #2. Фиксирует: Фаза 1 (content-floor V1/V1-PS) реализована
полностью (11 коммитов 4e7d32d4..8a35f641), регрессия 3044+2 GREEN 0 регрессий,
commit-not-push. Готовый промт новой сессии + цепочка скилов (executing-plans драйвер,
per-Task audit→TDD→systematic-debugging→verification, строгий sharp-edges после опасных
Task, гейт закрытия audit→sharp-edges→variant-analysis→regression→verification) +
квирки (vitest фильтры раздельно, гейты блокируют rm/git rm, tdd-real-test-verifier diff
требует expect, for-of не it.each) + отложенное в Фазу 8 (удаление powershell-destructive,
полная PS enumeration). Следующий шаг — Фаза 0 через writing-plans по команде владельца.
2026-06-08 09:40:25 +03:00
Дмитрий 8a35f64192 refactor(m7-floor): PS-content единый источник — matchPsHardBlacklist в shell-content-rules (variant-analysis)
Закрывающий variant-analysis-гейт Фазы 1 вскрыл класс P-1 для PowerShell: у
powershell-gate был СВОЙ PS_HARD_BLACKLIST (29 паттернов), а пол использовал
отдельный узкий psContentBlock (7) — подмножество, которое дрейфовало бы (та же
проблема, что P-1 для Bash). После Фазы 8 (увольнение powershell-gate) пол оказался
бы слабее гейта, который он заменяет. Решение владельца: исправить сейчас.

Зеркало P-1:
- PS_HARD_BLACKLIST + matchPsHardBlacklist перенесены в единый дом shell-content-rules;
  powershell-gate ре-экспортирует (тест single-source-identity: ссылка gate === SCR).
- +bare-egress (Invoke-WebRequest/iwr/irm/curl/wget bare — floor НЕ default-deny, нужен
  в blacklist, не только в whitelist гейта) +rmdir +rm (алиасы Remove-Item, которые гейт
  ловил whitelist'ом default-deny — полу нужны явно).
- psContentBlock стал ТОНКИМ делегатом над matchPsHardBlacklist (симметрия с
  bashIsContentBlock); пол через него видит ТОТ ЖЕ набор, что гейт. Дрейф невозможен.
- Следствие (осознанно): floor теперь блокирует все Set-Content/sc/$env/Az/… как гейт
  (симметрия с Bash-полом, блокирующим все cp/mv/redirect). Escapable. FP-толерантность
  унаследована от гейта (например `sc query`/`del.txt` — gate-aligned, fail-safe).

powershell-destructive.mjs физически не удалён (живые gate'ы блокируют rm/git rm) —
оставлен тонким делегатом (НЕ второй источник). Удаление — follow-up по git-approval.

Регрессия tools-only: 3044 passed + 2 skip (baseline 2843+2, 0 регрессий).
2026-06-08 09:34:23 +03:00
Дмитрий e34b505f04 feat(m7-floor): §12 content-floor инвариант — весь BASH_HARD_BLACKLIST floored (P-6)
Task 1.6 Фазы 1 М7. Тест-генератор: КАЖДАЯ запись BASH_HARD_BLACKLIST рубится полом
даже как валидный шаг плана. Итерация по экспортированному списку → полнота порта ПО
КОНСТРУКЦИИ: новый паттерн без сэмпла → красный (drift-детектор), floor не рубит →
красный. Анти-регресс «непробиваемости» закреплён за Фазой 1 (P-6), не за §9.2-smokes.
+C16 stderr-redirect + #34 injection (отдельные ветки matchBashHardBlacklist).

Полная регрессия tools-only: 2997 passed + 2 skip (baseline 2843+2, +154 Фазы 1,
0 регрессий). 99 floor-decide GREEN.
2026-06-08 09:16:04 +03:00
Дмитрий 8152f8d4af test(m7-floor): инвариант escape снимает content-block (Bash+PS) + специфичность P-2
Task 1.5 Фазы 1 М7. Код уже escapable (1.3/1.4) — тесты фиксируют инвариант против
регресса. Покрыто: Bash node -e + PS Remove-Item + PS forge-write снимаются точным
грантом; P-2 специфичность (грант A не открывает команду B) для PS И Bash; кросс-shell
изоляция (Bash-грант не открывает PS-команду — разные canonicalAction-префиксы). 72 GREEN.
2026-06-08 09:13:55 +03:00
Дмитрий 6a9ac38b95 harden(m7-floor): PS-алиасы forge+delete (sharp-edges после 1.4)
Строгий sharp-edges-гейт после Task 1.4 вскрыл обход через PowerShell-алиасы:
- forge P-3: `sc`/`cpi`/`ni` (алиасы Set-Content/Copy-Item/New-Item) писали в
  ~/.claude/runtime/.env мимо литеральных глаголов → подделка escape-гранта.
  Закрытие: PS_WRITE_VERB_RE += sc/ac/cpi/copy/mi/move/ni/tee (path-gated, FP только
  с протектед-путём; контроль `sc query` не over-блокируется).
- delete: `del`/`ri`/`rd`/`rmdir`/`erase` -Recurse -Force обходили литеральный
  Remove-Item. Закрытие: PS_CONTENT_BLOCK_RE алиасы для long+short флагов.

154 GREEN (floor + powershell-destructive + enforce-floor + supreme-gate).
Отложено в Фазу 8 §5 (карты покрытия): `&` call-operator, Invoke-Command (icm),
PS sub-expression $(), полная enumeration алиасов — coverage, не структурный класс.
2026-06-08 09:12:38 +03:00
Дмитрий 5ab5383182 feat(m7-floor): floor-decide ветка PowerShell content-block + forge-страж (V1-PS, P-3)
Task 1.4 Фазы 1 М7. Ветка PowerShell пола (после Bash, до OBSERVE_TOOLS): psContentBlock
(Remove-Item/-Recurse/iwr/iex/Start-Process/Out-File/redirect) ИЛИ psProtectedWrite
(P-3 forge-страж: PS-запись в ~/.claude/runtime / .env / секрет — иначе Set-Content
подделывает escape-грант). Escapable owner-санкцией. Реоткрытие v3.8 F1. 60 GREEN.

НАХОДКА РЕАЛИЗАЦИИ: plan-версия psProtectedWrite тестила whole-string SECRET_PATH_RE
с $-якорем → `.env` в позиции аргумента (-Path app/.env -Value …) терялся. Робастнее:
проверяем каждый токен (без кавычек, \→/) против anchored RUNTIME_RE/SECRET_PATH_RE —
runtime (forge-вектор) И secret-write закрыты, обычная запись не over-блокируется.
2026-06-08 09:09:18 +03:00
Дмитрий 05c5dcb166 harden(m7-floor): bashIsContentBlock рубит sub-shell как класс (sharp-edges после 1.3)
Строгий sharp-edges-гейт после Task 1.3 вскрыл класс обхода: подстрочный
matchBashHardBlacklist не де-обфусцирует command-substitution. Split-assembly
`$(echo no)$(echo de) -e x` и backtick `echo node` собирают интерпретатор только
при shell-eval → в сырой строке 'node' нет → content-block FALSE → пол пропускал.
router-gate ловит сейчас, но Фаза 8 (увольнение router-gate) открыла бы класс.

Закрытие: bashIsContentBlock проверяет detectSubshell(raw).found ($()/backtick/
process-subst/heredoc) → любой sub-shell = произвольное исполнение → content-block.
Независимо от parse-успеха. Escapable; router-gate тоже блокирует все sub-shell →
0 новых FP. Подтверждено: per-segment токенайзер де-обфусцирует n''ode/no\de.
114 GREEN (floor + enforce-floor + supreme-gate).
2026-06-08 09:06:23 +03:00
Дмитрий f259267191 feat(m7-floor): floor-decide content-block ветка Bash (V1, escapable)
Task 1.3 Фазы 1 М7. bashIsContentBlock (whole+per-segment, паритет с bashIsFloor, P-4)
через единый matchBashHardBlacklist (P-1). floorDecide Bash-ветка зовёт content-block
ПЕРВЫМ (до bashIsFloor); escape снимает (owner-санкция). 44 GREEN.

НАХОДКА АУДИТА (задокументирована в коде+тесте): NB плана «echo "node -e foo" НЕ
over-блокируется» недостижим при подстрочном matchBashHardBlacklist (не отличает
опасную строку-аргумент echo от команды-интерпретатора). Решение — принять FP:
floor УЖЕ принял этот класс для `git push "--force"` (fail-safe, escapable);
under-block в полу страшнее over-block. Парсинг командной позиции НЕ вводим.
2026-06-08 09:01:04 +03:00
Дмитрий e5680c24d5 fix(m7-floor): canonicalAction +PowerShell — escape-привязка специфична (P-2)
Task 1.2b Фазы 1 М7 (КРИТ). canonicalAction получил ветку PowerShell:
`powershell:${normalizeCommand(command)}`. Без неё PS уходил в write-fallback,
пустой путь резолвился в cwd → один escape-грант разблокировал ЛЮБУЮ PS-команду
в окне (тест специфичности был зелёным ложно: a===b==='write:<cwd>').

Сквозной фикс: тот же canonicalAction зовут пол (Task 1.4), стена (enforce-supreme-gate)
и консьюмер. Bash/Write/mcp-ветки не задеты. 118 GREEN (escape-grant + 4 потребителя).
2026-06-08 08:56:44 +03:00
Дмитрий bfbf72f78e feat(m7-floor): powershell-destructive psContentBlock (V1-PS)
Task 1.2 Фазы 1 М7. Новый модуль tools/powershell-destructive.mjs — psContentBlock
для PowerShell-tool (PS-нативные глаголы Remove-Item/-Recurse/iwr/iex/Start-Process/
Out-File/redirect НЕ матчат unix-regex classify-destructive). Реоткрытие v3.8 F1:
PowerShell-tool был полностью вне scope content-floor. 16 GREEN.
2026-06-08 08:55:30 +03:00
Дмитрий 9555d02343 feat(m7-floor): classify-destructive +contentBlock (правило 8, V1 Bash)
Task 1.1 Фазы 1 М7. Поле contentBlock = matchBashHardBlacklist(cmd) !== null
(единый источник P-1, whole-string) рядом с floor/suspicious. suspicious ||=
contentBlock (P-5: голоса судьи М4 видят content-опасное). reason расширен.

Поле для видимости судьи; фактический блок пола — bashIsContentBlock
(whole+per-segment, Task 1.3). 71 GREEN (+38 content-block кейсов, incl.
P-1-пробелы env-prefix/--watch/2>file/cp/mv).
2026-06-08 08:53:53 +03:00
Дмитрий 4e7d32d40f refactor(m7-floor): matchBashHardBlacklist -> shell-content-rules (единый дом content-правил, P-1)
Task 1.0.5 Фазы 1 М7. Перенос BASH_HARD_BLACKLIST + stderrRedirectBlock +
matchBashHardBlacklist из enforce-router-gate.mjs в постоянный дом
shell-content-rules.mjs (там уже живут hasInjection + matchAny). router-gate
ре-экспортирует их для обратной совместимости (тесты + тело гейта).

Единый источник правды устраняет port-дрейф content-floor (М5) по конструкции:
content-block пола (Task 1.1/1.3) импортирует ТОТ ЖЕ матчер, а не ручную копию.

Тесты: +describe single-source identity (router-gate BASH_HARD_BLACKLIST ===
shell-content-rules ссылка) + matchBashHardBlacklist hosted-in-SCR. 233 GREEN.
Чистый рефактор-перенос, 0 изменений семантики.
2026-06-08 08:51:31 +03:00
Дмитрий 0f781f3707 docs(m7): build-handoff #2 — состояние после фолжа разбора плана (HEAD 41c6b78b)
Готовый промт для новой сессии: подтвердить HEAD 41c6b78b, прочитать
handoff#2 + спеку §13 addendum + план Фазу 1 (Task 1.0.5-1.6), спросить
владельца, НИЧЕГО не делать самому. Заменяет handoff#1 (stale HEAD 9d6e708c).
Карта правок P-1..P-8 (план↔спека). Код НЕ строили. commit-not-push.
2026-06-08 08:24:17 +03:00