/dr-verify
Трёхуровневая самоверификация: детерминированный floor + кросс-модельная peer-review (zero-flag UX, 6-step provider chain) + native runtime dispatch
Обзор
/dr-verify запускает трёхуровневый конвейер самоверификации, выявляющий пробелы на всё более глубоких уровнях по принципу cheapest-first. Уровень 1 — детерминированный shell-конвейер (нулевая стоимость LLM). Уровень 2 — кросс-модельная peer-review с чистым внешним контекстом — провайдер авто-резолвится через 6-шаговую цепочку (zero-flag UX). Уровень 3 — native runtime dispatch с multi-agent fan-out. Findings содержат явный тег source_layer плюс таксономию peer_review_mode (cross_vendor / cross_claude_family / same_model_isolated), поэтому audit log сохраняет provenance и dispatch class.
Использование
/dr-verify {TASK-ID} # zero-flag — провайдер авто-резолвится
/dr-verify {TASK-ID} --stage do
/dr-verify {TASK-ID} --floor-only # только Layer 1, быстрый pre-merge gating
/dr-verify {TASK-ID} --peer-provider deepseek # явный override (chain step #1)
Три уровня
- Уровень 1: Детерминированный floor — запускает
dev-tools/dr-verify-floor.sh, чистый shell-конвейер: AC coverage grep, file-touched audit, test-presence parse, shellcheck по dev-tools/scripts. Нулевая стоимость LLM, выполняется за секунды. Эмиттит JSONL findings сsource_layer: "floor"на stdout. - Уровень 2: Кросс-модельная peer-review — отправляет adversarial review в чистом внешнем контексте. Провайдер авто-резолвится через 6-шаговую цепочку (см. § Provider Resolution ниже); прежнее «default DeepSeek» поведение теперь chain step #4, а не hardcoded литерал. Передача
--task-idобязательна — без неё downstream token-cost tooling не сможет фильтровать логи по задаче. Findings помечаютсяsource_layer: "peer_review"+peer_review_provider: <name>+peer_review_mode: cross_vendor|cross_claude_family|same_model_isolated. - Уровень 3: Native runtime dispatch — verification-агенты на локальном runtime:
- Claude (канонический): 3 параллельных read-only субагента (reviewer + tester + security). Findings объединяются через union + dedupe по кортежу
(artifact_ref, ac_criteria, category); при коллизии побеждает higher severity. - Codex
[экспериментальный]fallback: single-prompt loop с canonical adversarial framing. Демотирован из канонического — на Codex предпочтительнее использовать Layer 2.
- Claude (канонический): 3 параллельных read-only субагента (reviewer + tester + security). Findings объединяются через union + dedupe по кортежу
Provider Resolution (Zero-Flag UX)
Когда флаг --peer-provider не задан, helper dev-tools/resolve-peer-provider.sh проходит 6-шаговую цепочку. Первый step, выдавший провайдера, побеждает.
- CLI флаг
--peer-provider <name>— явный override. ./datarim/config.yamlpeer_review.provider— per-project, team-shared (коммитится в repo).~/.config/datarim/config.yamlpeer_review.provider— per-user XDG, machine-local.~/.config/coworker/profiles.yamlпрофильcodeполеrecommended_provider— coworker default (обычноcross_vendorвроде DeepSeek).- Cross-Claude-family fallback — диспатчит agents/peer-reviewer.md на
model: sonnetв свежем subagent context. Только Claude Code runtime; покрывается Claude subscription, external API key не нужен. - Same-model isolated last resort — Opus ревьюит вывод Opus (Codex degraded path или final fallback). Наименее зрелый паттерн; эмиттит stderr WARN.
Provider whitelist: deepseek | moonshot | openrouter | sonnet | haiku | opus | none. Неизвестные значения отвергаются с exit 1 (supply-chain mitigation: malicious PR, инжектирующий provider: typosquat-host, блокируется на parse).
Таксономия peer_review_mode (3-tier)
cross_vendor— DeepSeek / Moonshot / OpenRouter черезcoworker ask. Другая компания, другой training run, другой RLHF — сильнейшая mitigation self-agreement bias.cross_claude_family— Sonnet 4.6 ревьюит вывод Opus 4.7 через Claude Code subagent dispatch. Разные model checkpoints с разными post-training runs, изолированный subagent context. Средний tier — покрывается Claude subscription. First measured tier: эмпирическая bias delta vs same-model self-critique находится под измерением в активном dogfood window.same_model_isolated— Opus ревьюит Opus или Codex single-prompt loop. Та же model family, то же training distribution. Last-resort fallback only; наименее зрелый паттерн.
Codex CLI degraded mode: когда CODEX_RUNTIME=1 установлен в env, chain step #5 пропускается и берётся step #6. Helper пишет WARN: Codex runtime detected, falling back to same_model_isolated mode в stderr; orchestrator пробрасывает этот warning в audit-log.
Схема Findings
Каждый finding соответствует канонической схеме (canonical в skills/self-verification.md § Findings Schema):
source_layer— enum:floor,peer_review,dispatchseverity— enum:high,medium,lowcategory— enum:correctness,completeness,consistency,safetyevidence—{type, source, excerpt}, гдеtype∈{file_quote, test_output, absent}(absentauto-discards)ac_criteria— массив AC labels, на которые маппится finding (может быть пустым)peer_review_provider— опционально, только Layer 2 (имя провайдера)peer_review_mode— опционально, только Layer 2 (3-tier taxonomy enum)peer_review_provider_source_layer— опционально, только Layer 2 (chain step, который зарезолвил:cli_flag,per_project_config,per_user_config,coworker_default,fallback_subagent,fallback_isolated)check_name— опционально, только Layer 1 (напримерac_coverage_grep,shellcheck)
JSONL Emission Discipline (Layer 2 prompts)
Findings эмитятся ТОЛЬКО когда check FAIL'ится или вскрывает NEW DRIFT. PASS-as-finding записи (например {"check_name":"F001 cleared, no finding"}) отвергаются — подтверждения принадлежат final-line summary {cleared_iter1: [...], total_new_findings: N}, не массиву. Сохраняет audit log signal-dense.
Вердикты
- PASS — только low-severity (или ноль) non-discarded findings
- CONDITIONAL — ≥1 medium и ноль high
- BLOCKED — ≥1 high (merge/archive блокируется до устранения)
Флаг --floor-only
Флаг --floor-only short-circuit на Layer 1 — идеален для быстрого pre-merge gating в CI. Завершается за секунды с нулевой стоимостью LLM, блокирует только на структурных / shellcheck-error проблемах. Уровни 2 и 3 пропускаются.
Тегирование результатов верификации
На этапе /dr-archive оператор заполняет блок verification_outcome во frontmatter архива (canonical схема в templates/archive-template.md): caught_by_verify, missed_by_verify, false_positive, n_a, dogfood_window (operator-supplied window-id, используется как grouping key, не как диапазон дат). Aggregator dev-tools/measure-prospective-rate.sh --since <YYYY-MM-DD> обходит все archive-*.md и вычисляет caught_per_5_tasks с decision_hint для следующего pipeline gate.
Пример сессии (zero-flag UX, без external API key)
> /dr-verify {TASK-ID} --stage all --max-iter 2
Layer 1 — floor: dr-verify-floor.sh --task {TASK-ID} --stage all
→ 2 findings (medium, safety, check_name=shellcheck)
→ exit 0 (нет high-severity, продолжаем)
Layer 2 — peer_review (provider auto-resolution chain)
Step #1 --peer-provider flag → не задан
Step #2 ./datarim/config.yaml → не задан
Step #3 ~/.config/datarim/... → не задан
Step #4 coworker --profile code → не задан
Step #5 cross-Claude-family → MATCH (subagent peer-reviewer @ sonnet)
Диспатчим agents/peer-reviewer.md, model=sonnet, isolated context
→ 1 finding (medium, correctness, peer_review_mode=cross_claude_family)
Layer 3 — dispatch runtime=claude
3 параллельных агента: reviewer / tester / security
→ reviewer: 1 finding (completeness)
→ tester: 0 findings
→ security: 0 findings
Aggregate: 4 unique findings после dedupe
Вердикт: CONDITIONAL (0 high, 4 medium)
source_layer_breakdown: {floor: 2, peer_review: 1, dispatch: 1}
peer_review_mode_breakdown: {cross_claude_family: 1}
Audit: datarim/qa/verify-{TASK-ID}-all-1.md (chmod a-w)
Связанные команды
- /dr-qa — multi-layer проверка качества (другая поверхность; комплементарна)
- /dr-archive — здесь оператор заполняет блок
verification_outcome