Adversarial audit rounds 5+6 на v3.5 spec выявили 45 attack-векторов: - Round 5 (v3.5→v3.6 + v3.6→v3.7 maximum-closure): 15 + 7 acceptable residual closed - Round 6 (v3.7→v3.8): 30 attack-векторов в 18 классах вкл. 4 FATAL v3.6 — Round 5 closure (15 holes, +9 protected paths, Smoke 4-7, §5.1↔§4.5 sync, recovery-pattern hard-block в §4.7). v3.7 — Maximum closure pass (7 v3.6 residual + edge): LLM-judge на каждую AskUser-опцию (R-NEW-1), parent_random_id 256-bit sentinel (R-NEW-4), restricted/ subdir + journal-reader CLI (R-NEW-2), shell-quote tokenizer (R-NEW-3), TF-IDF + LLM-judge для off-topic (R12), smart batching multi-question AskUser (S6), git stash variants в conditional class (Edge). v3.8 — Round 6 closure (30 holes в 18 classes): - F1 PowerShell tool gate (был полностью вне scope §5.1 — обнуляло архитектуру на Windows) - F2 Workflow internal agent() enumeration (nested агенты вне gate-visibility — unlimited bypass) - F3 node_modules whole-dir hard-deny + dep-checksums verification через SHA-256 ключевых deps - F4 LLM-judge anti-injection (delimiter tokens + pre-filter + multi-judge consensus Sonnet+Haiku) §3.1 protected paths расширен +30 entries (memory/CLAUDE.md/Pravila/ PSR/Tooling с Skill exemption для claude-md-management, CI/CD configs, lint/build configs, plugin cache, shell init, npm configs, node_modules, parent-sentinel, dep-checksums, expected-path). §3.0.1 OS-keychain для LLM key (Windows Credential Manager / Keychain / libsecret через keytar); key не в process.env → не утечёт через npm test stdout. §3.2.1 automated bootstrap smoke (1/5/6/7 на каждый session start, cached 7 days); user-run остаётся для 3/4/8. §6.1 docs/recovery-procedures.md новый файл — пошаговая шпаргалка PowerShell-команд для 3 уровней recovery. Budget: 13.5-20h (v3.5) → 22.5-32h (v3.6) → 33-44h (v3.7) → 45-60h (v3.8). Закрыто 105 holes total через 9 раундов adversarial audit. Generalisable lesson v3.8: каждый раунд аудита должен начинать с abstract classification классов атак до enumeration конкретных дыр. v3.7 «maximum closure» был maximum внутри границ воображения v3.6 R5-audit; Round 6 показал что сами границы имели дыры. Spec: 1980 → 2554 строк (+1110 inserts / -44 deletes за v3.6-3.8 sweep). +13 терминов в cspell-words.txt (PowerShell aliases, npm deps). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Observer infrastructure
Passive evidence-loop for the Лидерра «brain» per ADR-011.
Files
episodes-YYYY-MM.jsonl— append-only JSONL, one line per Stop-event. Schema v2 (schema_version: 2): the 5 mandatory fields +decision_provenance(who chose the node),environment(economy_level / model / post_compaction / session_turn / parallel_session),task_size,task_ref,prompt_signal, and anoutcomethat isunknownat write time (refined by/brain-retro). On an internal hook failure a minimalobserver_errormarker line is written instead of a silent skip. Written bytools/observer-stop-hook.mjsviatools/observer-transcript-parser.mjs.notes/YYYY-MM-DD-<slug>.md— optional MD notes for sessions with qualitative history.STATUS.md— auto-generated dashboard. Regenerated per-commit bytools/status-md-generator.mjs..read-counter.json— C3 observer-of-observer counter. Updated on Read of observer files.dashboard.html+dashboard.js+dashboard-core.js— Brain Dashboard: visualises the episode log over the automation-graph topology (4 views — Карта / Разбор / Лента / Агрегат). Runnpm run brain:dashboard, open the printed localhost URL.dashboard-core.jsis pure logic, unit-tested intools/brain-dashboard-core.test.mjs.
Lifecycle
- Write: every Stop-event appends one JSONL line, parsed from the session transcript (Stop-hook).
- Aggregate:
/brain-retroskill reads JSONL each sprint, proposes regulatory candidates. - Surface:
STATUS.mdshows controllers + monthly stats. - Self-prune: C3 warns if 54 weeks pass without any read of observer files.
Routing-tag discipline
When the user dictates a specific method/node (e.g. «запусти discovery-interview»), Claude must emit one line in its response:
<!-- routing: provenance=user_directed_method node=<chosen> counterfactual=<node Claude would have chosen autonomously> -->
The Stop-hook routing-gate (tools/observer-routing-detector.mjs + routingGateDecision) detects a dictated method; if the tag is missing it returns decision: block, so the turn cannot end without the tag. The gate fires at most once per turn (stop_hook_active guard). This makes decision_provenance reliable — factor analysis can separate a router error from a user-dictated one.
Privacy
PII filter (phone numbers, emails, tokens) is applied before every write — see tools/observer-pii-filter.mjs. gitleaks pre-push also scans observer files as part of full-history sweep.
Don't
- Don't edit
episodes-*.jsonlmanually — it's append-only. - Don't write outside
docs/observer/notes/for hand-curated notes. - Don't change
.read-counter.jsonmanually — it's maintained by hooks.
HK1 pre-check (Pravila ADR-010) — verified 2026-05-19
Before registering tools/observer-stop-hook.mjs on Stop event (Task B5), verified collision against 6-component economy/skill-discipline architecture:
- User-level
~/.claude/settings.jsonalready has Stop hook: agent-type Sonnet-4.6 economy compliance verifier (analyzes transcript for claim-without-evidence violations). - Project-level
.claude/settings.json— Stop slot empty.
Result: no overwrite. observer-stop-hook will be added as command-type entry in project-level Stop array. Project + user scopes are independent slots in Claude Code 2.x — both run on the same Stop event without conflict. The agent verifier (user scope) and the JSONL appender (project scope) have non-overlapping responsibilities.