Commit Graph

545 Commits

Author SHA1 Message Date
Дмитрий 52d500db5d feat(security): read-only доступ к проду через стену — ssh liderra-prod + gh GET
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 08:04:50 +03:00
Дмитрий cf813c1091 feat: wall - подписанные строки вердиктов роутера наставника и судьи во всплытии
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 13:16:32 +03:00
Дмитрий 77a16c07f7 chore(router): судья/наставник/роутер переведены на deepseek-v4-flash
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 11:08:15 +03:00
Дмитрий 9fe5b5f229 imitation phase1 merge
# Conflicts:
#	app/app/Console/Commands/PhoneRangesImportCommand.php
#	app/app/Jobs/RouteSupplierLeadJob.php
#	app/app/Services/LeadRegionResolver.php
#	app/database/migrations/2026_05_31_100000_create_phone_ranges_and_resolution_log.php
#	app/tests/Feature/Console/PhoneRangesImportCommandTest.php
#	app/tests/Feature/Jobs/RouteSupplierLeadJobTest.php
#	app/tests/Feature/PartitionsCreateMonthsTest.php
#	cspell-words.txt
#	docs/observer/STATUS.md
#	tools/enforce-powershell-gate.test.mjs
#	tools/enforce-router-gate.mjs
#	tools/enforce-router-gate.test.mjs
#	tools/enforce-tdd-gate.test.mjs
#	tools/enforce-tdd-real-test-verifier.mjs
#	tools/enforce-tdd-real-test-verifier.test.mjs
#	tools/enforce-verify-record.test.mjs
#	tools/mcp-tool-classifier.test.mjs
#	tools/shell-content-rules.test.mjs
2026-06-17 08:03:35 +03:00
Дмитрий 9ac6d96dee feat router-mentor: arbitration fixes 1+2+3 - verdict visibility, round-memory judge-self-history and mentor-re-eval, owner-seal arbitration; 29/29 tools green
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:13:52 +03:00
Дмитрий cc82665f5c fix router-mentor: router-classifier per-attempt timeout 30s -> 300s for DeepSeek; prevents Agent Router calls being truncated and hanging in aitunnel logs
Accessibility (Pa11y live) / a11y (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:32:06 +03:00
Дмитрий 73db27476e chore router-mentor: control LLM claude-sonnet-4-6 -> deepseek-v4-pro via aitunnel; HEAVY_LLM_TIMEOUT_MS 90s->300s; fix reasoning content-block text extraction in callAnthropicAPI
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:00:35 +03:00
Дмитрий 3aeedb8aea chore: prune brain test-layer to claude-brain
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 05:03:55 +03:00
Дмитрий d74d3113e5 feat: research-tooling Perplexity Pack #87-89 — registry/router/normative sync + ADR-019
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 15:44:42 +03:00
Дмитрий bfc1f5750d fix(research-tooling): gate read_only + perplexity via aitunnel base URL
Закрывает spec-gap Perplexity Pack — enforce-mcp-classification default-блокировал
неклассифицированные MCP-инструменты. Добавлены mcp__perplexity__*, mcp__exa__*,
mcp__firecrawl__* как read_only (ADR-019 постура, решение владельца 2026-06-14).
TDD RED-GREEN, регрессия tools-only 3931 passed / 2 skip.

.mcp.json: PERPLEXITY_BASE_URL=https://api.aitunnel.ru/v1 — роутинг sonar через AITUNNEL.
Live-smoke перезапуском: perplexity (sonar-pro), exa, firecrawl — все три GREEN.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 13:57:41 +03:00
Дмитрий bcf7ff6d74 fix(router-mentor): стена не двигает указатель на floor-блокируемый шаг (Δ7+)
floor-desync: supreme-gate Δ7 вето-без-сдвига смотрел только classifyDestructive.floor (rm-rf/force-push/migrate), а enforce-floor блокирует шире — content-block правило 8 (node -e/curl/eval), PowerShell, запись в runtime/секрет. Floor-блокируемый-не-destructive шаг (node -e) проскакивал со СДВИГОМ указателя, пол рубил исполнение → шаг терялся безвозвратно (desync, потеря safety-шага). Δ7 расширен на полный предикат floorDecide (пустой escape; escape обрабатывается в decideMode до decide). Order-independent. TDD RED→GREEN, регрессия tools-only 3930 passed + 2 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:58:14 +03:00
Дмитрий 13ddd156aa fix(router-mentor): per-attempt таймаут тяжёлых LLM-вызовов 30с→90с
Судья/наставник по большой спеке/плану отвечают 25-32с; дефолт callAnthropicAPI 30с давал таймаут→degraded→печать не вставала (спека не запечатывалась gate1 → план не мог встать gate2). HEAVY_LLM_TIMEOUT_MS=90с в router-config, проброшен в callJudgeModel (судья) и buildLlmCall (наставник). TDD RED→GREEN, регрессия tools-only 3928 passed + 2 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 09:54:04 +03:00
Дмитрий f3ac36bef1 revert(wall): откат Post-advance — PostToolUse не срабатывает на упавшем Bash
Live-смоук: PostToolUse не запускается на exit≠0 → Post не двигает указатель на RED-шагах. Код возвращён к Pre-advance (3928 GREEN). Спека/план помечены ОТВЕРГНУТО. Настоящий фикс desync = перестановка skill-discipline перед supreme-gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 06:11:11 +03:00
Дмитрий 820ff23ccc fix(wall): supreme-gate сдвигает указатель на PostToolUse (фикс рассинхрона)
Pre-такт = ворота + журнал-намерение (без сдвига); Post-такт = сдвиг по подтверждённому исполнению. Лечит desync при блоке поздним хуком / user-deny. +runGatePre/runGatePost/isPostEvent, runGate → compat-обёртка. Регрессия tools-only 3938 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 05:34:33 +03:00
Дмитрий e243b8f77b feat(mentor): тупой судья навыков + фикс роутера prefilter-bypass
- router: classify({skipPrefilter}) — наставник зовёт мозг роутера мимо detectMicro
  (ловил 'format' подстрокой в имени модуля → роутер не доходил до LLM); recommendedChainOf
  в on-plan-write маппит node/recommended_node/recommended_chain (рекомендация не теряется)
- skills в ПОДПИСАННУЮ печать (Вариант 1): sealablePlan/freezePlan/sealPlan
- стена: isPlanDeclaredSkill — объявленный в опломбированном плане навык вызываем (снимает дедлок)
- enforce-domain-skill-discipline (новый хук): объявил → обязан вызвать (журнал M1) до
  первого мутирующего шага; поверх готового domain-skill-discipline
- гайд docs/superpowers/router-mentor-wall-GUIDE.md + дизайн/план-доки
- регрессия tools-only 3928 passed + 2 skip, 0 регрессий

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 04:08:53 +03:00
Дмитрий e554725226 feat(wall): оркестратор наставник-судья - строгая последовательность печати
Новый enforce-mentor-then-judge.mjs запускает наставника дочерним процессом до конца, потом судью (свежий mentor-GO/вердикт) - убирает гонку параллельных PostToolUse-хуков. Машины enforce-mentor-on-plan-write/enforce-judge-gate байт-в-байт не тронуты. Зарегистрирован в settings.json. TDD +5 тестов.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 17:15:37 +03:00
Дмитрий db1eb8e337 fix(mentor): резолв ID узлов в имена в скил-контексте наставника
renderSkillContext резолвит #N -> '#N - имя' через registry.indexById (resolveNodeName, fail-safe -> голый #N); onPlanWrite прокидывает registry. Наставник видит рекомендацию роутера именами. TDD +4 теста, регрессия tools-only 3910 GREEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 17:15:14 +03:00
Дмитрий b739d5adad feat(mentor): мерж роутера в наставника — единый рецензент (спека+план+скилы) + decision GO/NO-GO
Болезни B (роутер в пустоту) + A (наставник не заворачивал) — лечение Р7/Р8 (Подход 1):
наставник — единый мозг-рецензент, зовёт classify() как функцию (3 слоя + граф nodes.yaml +
карточки — код не тронут, новый вызыватель), судит спеку+план+выбор скилов, заворачивает NO-GO.

- validateMentorVerdict + промпты (план/спека): явное decision GO|NO-GO (поглощённый Р7)
- plan-skills.mjs: parsePlanSkills (skills-json) + extractPlanGoal (зеркало extractGoal судьи)
- mentor-seam: renderSkillContext; onPlanWrite зовёт classifyImpl (fail-safe: сбой → без скил-сверки)
- decideMentorObjection: заворот на decision=NO-GO ИЛИ сломанный вердикт; mentor-GO только на чистом GO
- formatMentorObjection доносит суть (recommendation + reasoning + plan_points), GO -> пусто
- enforce-mentor main: loadRegistry + classify; счётчик L1 decision-aware (Р7/§3.4)
- скил-сверка — только план (gate2); спека (gate1) — по сути + decision
- включает redesign согласования L1->L2 (Фазы 0-6, способ B: наставник->судья->печать)
- регрессия tools-only 3901 passed + 2 skip (база 3877, +24 теста, 0 регрессий)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 11:38:09 +03:00
Дмитрий 9d8d3de782 feat(mentor): degraded-судья диагностируем — cause(no_key/transport_error)+errorType+at
Разбор «перемежающегося degraded судьи» по systematic-debugging: действующего
бага нет (ключ SET, 28/28 вердиктов чистые, degraded-строки несверяемы — at:null,
без парного WARN). Гипотеза «retry/таймаут» не подтверждена → таймаут не трогали.

Вместо этого закрыта слепота диагностики (TDD, под maintenance):
- callJudgeModel различает no_key vs transport_error+errorType (classifyLLMError);
- причина протекает в вердикт → warnJudgeUnavailable (+cause/error_type/at) и seal-запись;
- main() передаёт nowMs: Date.now() → seal/verdict/warn больше не at:null (логи сверяемы).

Файлы: tools/seal-log.mjs, tools/enforce-judge-gate.mjs. +9 тестов; 2 exact-match
приведены к новому контракту. Регрессия tools-only 3829 GREEN (база 3820), 0 регрессий.
cspell-words.txt +8 терминов. Роадмап: секция «Печать M7» + degraded-наблюдаемость.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 04:12:53 +03:00
Дмитрий d786c273ca fix(mentor): печать плана M7 — снять дедлок судья↔наставник + наблюдаемость seal-attempts 2026-06-13 03:40:20 +03:00
Дмитрий 4073164d0d feat(mentor): wire mentor surface + counter + escalation card (wave 7) 2026-06-12 19:09:59 +03:00
Дмитрий 9f939cd41f feat(mentor): wire judge escalation to arbitration card (wave 6) 2026-06-12 19:03:59 +03:00
Дмитрий eca9be46c8 feat(mentor): objection-format judge+mentor formatters (waves 4-5) - 9 tests green 2026-06-12 18:43:43 +03:00
Дмитрий 8918190bbe feat(mentor): negotiation-section parser (wave 3) - 4 tests green 2026-06-12 18:30:05 +03:00
Дмитрий 6c6d6d2e4c feat(mentor): arbitration-card pure builder (wave 2) - 6 tests green 2026-06-12 18:26:17 +03:00
Дмитрий 5a7370df76 fix(verify): produce-verify-receipt Windows execFileSync npx to execSync 2026-06-12 18:07:21 +03:00
Дмитрий 48e8111cc2 feat(mentor): mentor NO-GO counter L1 (wave 1) - 3 tests green 2026-06-12 17:59:24 +03:00
Дмитрий ebce8e5536 feat(m7): re-plan на ходу (impl-карвут) + эскалация судьи (escape-honor + счётчик NO-GO) + docs-хвост 2026-06-12 15:48:17 +03:00
Дмитрий 296ab4df63 feat(m7-phase8): sealedPlanCoversEdit live-wiring + matcher extension to discipline sources
planCoversAction (signed-plan + tree-valid + leaf-match, fail-CLOSED) wires the §6
build-loop differentiator live. main() matcher now fires for tools/enforce-*.mjs
(ad-hoc → LAW/escape; under sealed plan → CARD). decide() skips doc-malice prose
layers for code and allows build-loop CARD (M2/content-floor/TDD govern). Hook inert
until Phase 8 registration. +10 tests; regression tools-only 3397 passed / 2 skip.

Plan: docs/superpowers/plans/2026-06-08-router-mentor-machine-7-phase-5.md (Deferred Ф8).

B
2026-06-12 11:28:58 +03:00
Дмитрий 95bb6b17fd chore(mentor): роадмап эпика 2026-06-12 + env ROUTER_LLM_BASE_URL в observer-self-assessment-api (зеркало транспорт-фикса, TDD) + cspell словоформы. Регрессия tools 3754 GREEN 2026-06-12 08:14:35 +03:00
Дмитрий 328ac009d6 fix(mentor): smoke этап 4 пройден — деталь ошибки транспорта в catch вердикта + env ROUTER_LLM_BASE_URL в дефолте callAnthropicAPI (смена оператора на aitunnel) + контракт массива строк в промпте plan_points_addressed (F-C3); runbook этап 4 + env-таблица + блок смены оператора; smoke-план; cspell +aitunnel и словоформы. Регрессия tools 3753 GREEN 2026-06-12 07:55:31 +03:00
Дмитрий f677c6651f feat(strict-llm-keys): оба строго — судья только ROUTER_JUDGE_LLM_KEY, наставник только ROUTER_MENTOR_LLM_KEY, общий ROUTER_LLM_KEY не фолбэк (решение владельца 2026-06-12; resolveJudgeLlmKey/resolveMentorLlmKey + env-тесты строгости + runbook-таблица ключей) 2026-06-12 06:39:17 +03:00
Дмитрий 8293ca2ce6 feat(mentor-activation): активационная обёртка наставника — рубильник SEAM + journal/verdict store + export PLAN_PATH_RE + контекст-в-плане + producer-хук PostToolUse + freeze-gate зубы в печать судьи (план T1-T7 + sharp-edges W-1..W-4) 2026-06-12 05:51:41 +03:00
Дмитрий 57b811b3c0 fix(mentor-finreview): финревью Фазы B 5-скил — FR-1 freeze-gate VF-1/SE-A1 inline + FR-2 единый рендер районов/staleness (W1-канон) + FR-4 balanced-парс JSON + VA-1 единый рендер контекста/ДР-1 + VA-2 маркер КОНТЕКСТ ПУСТ + VA-3 валидация request_district + F-C2-6/W7 ноты 2026-06-11 20:10:42 +03:00
Дмитрий 437f4f8e4f feat(completeness-radars): радары полноты — graph-radar (соседи по links, слепота видна) + skeleton-radar (отчёт по каждому заголовку, молчание=not-reported) + freeze L2-пол (нах.F2, sub-plan F Tasks 1-3 + sharp-edges F-F1..F-F5) 2026-06-11 19:31:04 +03:00
Дмитрий 537154adf3 feat(mentor-integration): боевая проводка C2 — W1 catalog≠graph+районы (М3) + W2 гейт ДР-1 в стене (М2, аддитивно) + W3 onPlanWrite + W4 warn-прокидка O18 + W6 интеграционный тест + W7 контракты (sub-plan C2 + Д-С2-1..7 + sharp-edges F-C2-1..5) 2026-06-11 19:09:39 +03:00
Дмитрий 48b410f395 feat(mentor-live-seam): живой шов наставника — task-id O17 + tamper-evident журнал + вердикт-производитель C-1/F4 + runMentorRound/петля/F7 + freeze-gate VA-8/O2/VA-9 (sub-plan C Tasks 1-7 + A1-A8 + Д-1а/Д-2а/Д-3 + sharp-edges F-C1..F-C7) 2026-06-11 18:13:45 +03:00
Дмитрий 039743a71f feat(footgun-fixes): O13 skill-escape канон + O11 detectMoney сужен + O18 judge_mode warn + SE-R7-6 loop-termination (sub-plan E Tasks 1-6 + SE1/C-4) 2026-06-11 17:13:48 +03:00
Дмитрий adf8211b77 feat(reading-discipline): дисциплина чтения наставника — тип/вид/гейт ДР-1/read-LOG/probe-cap (sub-plan D Tasks 1-8 + SE4/SE5/SE12/V-3 + sharp-edges F-D1..F-D7) 2026-06-11 16:46:56 +03:00
Дмитрий 51f9f00274 feat(project-graph): слоистый граф районов + staleness O16 (sub-plan B Tasks 1-8 + SE7/SE8/SE11/V-3 + sharp-edges B1/B3) 2026-06-11 15:52:12 +03:00
Дмитрий e753fe42cc fix(context-verity): MIN_ANCHOR_LENGTH=4 порог anchor (SE-A2) + коллатераль тестов 2026-06-11 15:07:14 +03:00
Дмитрий 99d61d510c feat(context-verity): проверенный контекст — parseRef/resolveCitation/verifyArtifact/guard O2 (sub-plan A Tasks 1-6 + amendments SE6/VF-1/SE9 + ревью SE-A1/SE-A3) 2026-06-11 14:31:02 +03:00
Дмитрий ae3f841cee feat(escape-sign): reader key-gated verify floor_escape (M6 FIX-5 Task 3)
loadFloorEscapes (единственный ВЫДАЮЩИЙ читатель floor_escape) теперь key-gated
проверяет подпись: ключ есть → оставить только валидно-подписанные (форж/
неподписанный/битый отброшены); нет ключа (truthy) → принять все (как сегодня,
content-floor backstop).

- Рефактор: generic loadRecords → floor_escape-специфичный readFloorEscapeRecordsAt,
  возвращает ПОЛНЫЕ записи {type,action,ts,sig} (не stripped) для верификации.
  Единственный вызыватель — loadFloorEscapes (loadConsumed читает другой файл).
- loadFloorEscapes(sessionId, now, {keyImpl, fsImpl, runtimeDir}) — 3-й опц.
  аргумент, обратно-совместим (8 потребителей зовут loadFloorEscapes(sess)).
- ОТКЛОНЕНИЕ от дословного кода плана (одобрено владельцем): быстрый путь —
  пропусков нет → [] БЕЗ резолва ключа. Поведение §3/§6 идентично, но keychain-
  subprocess не дёргается на каждый tool-use в массовом пустом случае
  (loadFloorEscapes — gate hot-path; 5 из 8 потребителей keychain не читали).

TDD: 6 новых тестов — 4 key-gated (signed принят / forged+tampered отброшены /
ключ null → все / '' falsy → все / окно 5 мин), 2 на быстрый путь (нет записей /
нет файла → [] без вызова ключа). Регрессия существующего escape-grant GREEN
(26 тестов). Суммарно 32 GREEN по затронутым файлам.

План: docs/superpowers/plans/2026-06-10-floor-escape-signing.md (Task 3)
Прод-код инертен до провижининга ключа (Фаза 8). Гейт закрытия — следующим шагом.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 05:28:40 +03:00
Дмитрий f4ac596a11 feat(escape-sign): writer подписывает floor_escape при наличии ключа (M6 FIX-5 Task 2)
processEvent (PostToolUse AskUser) теперь подписывает floor_escape-пропуск
подписью FLOOR_ESCAPE, когда ключ доступен (resolveReceiptKey):

- +keyImpl=resolveReceiptKey, fsImpl={appendFileSync,mkdirSync} — инъекция для
  hermetic-тестов; резолв ключа один раз на событие (fail-safe: ошибка → key=null
  → floor_escape пишется неподписанным, PostToolUse-наблюдаемость не ломается).
- esc подписывается только при наличии ключа; approve_git_operation (rec) НЕ
  трогаем (§2.2). Нет ключа → esc без sig (как сегодня).
- Запись через fsImpl.* вместо прямых node:fs.

TDD: 2 новых теста (ключ → валидная подпись; ключ null → без sig). Регрессия
существующего enforce-askuser-answer-parser GREEN (approve_git_operation-путь цел).
Суммарно 10 GREEN по затронутым файлам.

План: docs/superpowers/plans/2026-06-10-floor-escape-signing.md (Task 2)
Прод-код инертен до провижининга ключа (Фаза 8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 05:16:15 +03:00
Дмитрий 7faef3c93f feat(escape-sign): домен FLOOR_ESCAPE + sign/verify helpers (M6 FIX-5 Task 1)
Defense-in-depth для escape-гранта: подпись пропуска floor_escape, чтобы форж
без секретного ключа отвергался (поверх content-floor). Task 1 — фундамент:

- receipt-sign.mjs: +домен RECEIPT_DOMAINS.FLOOR_ESCAPE='floor-escape' (R-31,
  изолирует подпись floor-escape от approval/frozen-plan).
- askuser-answer-parser.mjs: +signFloorEscapeRecord/verifyFloorEscapeRecord —
  зеркало signApprovalRecord/verifyApprovalRecord, домен FLOOR_ESCAPE. Чистые,
  без ключа → sig:null.

TDD: 5 новых тестов (доменная изоляция, подпись/верификация целой записи,
подделка/без sig/без ключа/чужой ключ/чужой домен → false). Регрессия по
затронутым файлам 82 GREEN, 0 регрессий.

Спека: docs/superpowers/specs/2026-06-10-floor-escape-signing-design.md
План:  docs/superpowers/plans/2026-06-10-floor-escape-signing.md (Task 1)
Прод-код инертен до провижининга ключа (Фаза 8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 05:13:20 +03:00
Дмитрий 84231a1470 feat(board): live source for guard board escapes/blocks (D-3)
Доска «кто на посту» (STATUS.md §7) теперь показывает реальные недавние
escape владельца и блоки машин М1–М6 вместо хардкода []/[].

- new tools/guard-block-log.mjs: logGuardBlock (best-effort, fail-quiet,
  Node fs append в guard-blocks-<sess>.jsonl) + loadRecentBlocks/
  loadRecentEscapes (скан session-файлов runtime, окно 24ч + cap 10, ts→ISO).
- проводка logGuardBlock в block-ветку main() 9 машинных хуков (floor /
  supreme-gate / judge-gate / snapshot / read-path-deny / mcp-classification /
  normative-content-rules / verify-gate / criterion-gate). Логгер вызывается
  ПОСЛЕ решения, не влияет на block; decide() pure не тронут.
- status-md-generator CLI: recentEscapes/recentBlocks из читателей вместо []/[].

До флипа Фазы 8 доска показывает 0/0 (хуки не зарегистрированы — данных нет);
реальная польза — пост-флип наблюдаемость.

TDD: guard-block-log.test (6) + 9 структурных wiring-тестов + 1 board-тест.
Гейт закрытия: sharp-edges (промежуточный по 9 хукам + читатели) +
variant-analysis (все block-ветки покрыты, иных источников нет). Регрессия
tools-only 3465 passed / 2 skipped / 0 failed (было 3449+2skip). 0 регрессий.

Plan: docs/superpowers/plans/2026-06-10-guard-board-live-source.md
2026-06-10 04:28:53 +03:00
Дмитрий 4dd2098e7b feat(seal): validate judge_mode at freeze time (defense-in-depth, SE-2 §4)
assertValidJudgeMode guard in freezePlan/freezeArtifact: fail-CLOSE on any
mode != {null|shadow|live-block}. Closes YAGNI-candidate from sealed-plan §11
/ gate1+se2 §4 (SE-a) — bogus mode can no longer enter a seal at the source
(complements the wall's fail-closed live-block whitelist).

- freezePlan validates the judgeMode param; freezeArtifact validates the
  embedded artifact.judge_mode (injected by seal-orchestration).
- guard sits before id/sig computation -> no partially-signed bogus-mode seal.
- throw is best-effort-swallowed at enforce-judge-gate.mjs onWiredSeal ->
  no seal produced (fail-CLOSE), hook never crashes.
- real flow never trips it (judgeGateMode yields only inert/shadow/live-block,
  inert never seals) — drift-only guard.

TDD: new tools/plan-lock-judge-mode.test.mjs (6 tests). Regression tools-only
3449 passed / 2 skipped / 0 failed (was 3443+2skip). 0 regressions.
sharp-edges + variant-analysis: clean (only two seal producers, both guarded;
wall comparison already fail-closed).

Plan: docs/superpowers/plans/2026-06-09-seal-time-judge-mode-validation.md
2026-06-10 03:48:07 +03:00
Дмитрий 0289e93c0e feat(gate1+se2): wire spec-judging (Гейт-1) + fail-closed wall whitelist (SE-2)
М7 Фаза 8 — последние 2 хвоста до флипа. Inline TDD; спека+план одобрены; 2 адверсариальных прохода.

Гейт-1 (печать артефакта в рантайме):
- extractGate1Product (enforce-judge-gate.mjs): детект записи specs/*.md (Write-only) → судить
  линзами gate1 (движок уже поддерживает). runJudgeGate: спека→gate1, иначе план→gate2.
- judged_hash от СЫРОГО content (SD-1, разбор #1 High): trimmed source_sha не сошёлся бы с
  печатью sealOnWiredGo → артефакт НИКОГДА не печатался бы. Один канон судья→печать.
- extractGate2Product не тронут (Гейт-2 = планы, регрессия зелёная).

SE-2 (стена не чтит shadow):
- decideMode (enforce-supreme-gate.mjs): fail-closed whitelist — энфорсмент ТОЛЬКО при
  judge_mode==='live-block' на ОБЕИХ печатях; shadow/null/опечатка → разговорный (мутаторы block).
  Разбор #1 (VA-a/SE-a): убрана единственная fail-OPEN сверка; опечатка режима безопасна.
- мигрированы 3 enforce-теста стены на judge_mode:'live-block'.

Тесты: gate1 10, SE-2 6; регрессия tools-only 3443 passed / 2 skip / 0 регрессий.
Гейт-1 тесты — отдельный файл enforce-judge-gate-gate1.test.mjs (real-test-verifier блокирует
import-only Edit существующего теста). Печать в рантайме до флипа НЕ производится.
2026-06-09 19:05:17 +03:00
Дмитрий 09598dd5bd feat(seal): sealed-plan production pipeline (M7 Фаза 8 code-precondition)
Производство двух печатей (артефакт-решение + план-шаги), чтобы стене М2 было
что матчить — код-предусловие флипа. Inline TDD, спека/план одобрены владельцем.

- C1 artifact-from-spec.mjs: спека markdown -> {sections, source_sha} по якорям {#id} (P2-2).
- C2 plan-steps-parse.mjs: план -> [{op,object,ref}], fail-CLOSE, reject op:Task (VA-4),
  канон object = repo-relative POSIX (SE-5; pathNormalize только на матче в стене, не на парсе).
- C3/C4 plan-lock.mjs: judge_mode в ПОДПИСАННОЙ базе freezePlan (VA-2) + атомарный persist
  temp->rename для обоих save (SE-4/VA-3, артефакт ДО плана).
- C6 seal-orchestration.mjs: sealableArtifact/sealablePlan + judgedHashOf (SD-1) +
  sealArtifact/sealPlan на РЕАЛЬНОМ GO (SE-3 wired===true), штамп artifact_id из текущего
  артефакта (SD-3), judge_mode впрыснут в печать ПОСЛЕ хеш-сверки sealOnApproval (фикс TOCTOU).
- C5 enforce-judge-gate.mjs: SPEC_PATH_RE + sealOnWiredGo (печать на wired GO, инъекция в main,
  юнит-тесты hermetic) + judged_hash в вердикте runJudgeGate. extractGate2Product не тронут
  (Гейт-2 = планы; Гейт-1 spec-judging — отдельный заход перед флипом).
- Интеграция seal-to-wall: печать -> decideMode стены М2 (allow / non-match block / closed-door).

Тесты: full tools-only регрессия 3427 passed | 2 skipped, 0 регрессий (+29 новых кейсов).
Печать в рантайме НЕ производится до флипа (стена/судья не зарегистрированы) — сборка
готовит код-предусловие. Спека docs/superpowers/specs/2026-06-09-sealed-plan-production-design.md.
2026-06-09 17:50:25 +03:00
Дмитрий 5fd4031b1e fix(tdd-verifier): escape dots in TEST_FILE_RE (stop misclassifying *spec.mjs prod files)
Unescaped dots in /.(?:test|spec).[a-z0-9]+$/i matched the bare substring "spec"
in prod filenames ending like artifact-from-spec.mjs, so the real-test verifier
treated a production module as a test file and blocked it for lacking expect().
Anchor the dots (\.) so only genuine .test.<ext> / .spec.<ext> files match.
Real test files are still fully checked (regression guard added).
2026-06-09 17:50:19 +03:00