---
id: ADR-011
title: Brain governance — router-only + observer + 4 mechanical controllers
status: Accepted
date: 2026-05-19
related:
  - docs/superpowers/specs/2026-05-19-brain-governance-design.md
  - docs/superpowers/specs/2026-05-19-observer-factor-analysis-design.md
  - docs/discovery/2026-05-18-system-audit-brain.md
  - ADR-010 (HK1 hard-rule, hook collision pre-check)
---

# ADR-011: Brain governance — router-only + observer + 4 mechanical controllers

## Status

Accepted (2026-05-19). **Amended 2026-05-19** — observer factor-analysis extension: episode schema v2, two-sided enforcement (routing-gate + C5 controller). See Decision §5.

## Context

The Лидерра «brain» (60 formal positions + 20 ruflo plugins per Tooling Прил. Н §0) accreted faster than it was regulated. SYSTEM-аудит 18.05.2026 (`docs/discovery/2026-05-18-system-audit-brain.md`) closed Rec1–Rec5; intervention session 19.05.2026 went deeper to design ongoing governance.

Three recurring problems were identified:

1. **L1-pattern**: plugin enabled in `~/.claude/settings.json` user-level without formalization in Tooling Прил. Н. Occurred 3× in 8 days (UPM/21st 10.05; Sentry/Redis 13.05; Anthropic dev-tooling 18.05).
2. **Version drift** between 8 normative files. Tooling v2.11 collision 17.05.2026 — two parallel sessions consumed the same version number.
3. **Speculative regulation ahead of usage**. Initial recommendation «prune unused» rejected by owner — capability-readiness is an explicit strategy.

## Decision

### 1. Router-only

The brain has a single routing source of truth: the existing registry in [Tooling Прил. Н](../Tooling_v8_3.md) §4.X (extended with 9 obligatory attributes per spec §4.1) + the procedure in [`docs/router-procedure.md`](../router-procedure.md).

There is **no cache of «verified chains»**. There is **no 3-layer update mechanism**. There is **no forced-choice gate**. Every task is a fresh router-derived path.

Canonical chains L1–L12 in [`docs/routing-off-phase.md`](../routing-off-phase.md) remain as general-shape recommendations, not history-based records.

### 2. Observer (scope B, full package from day 1)

A passive Stop-event hook appends one JSONL line per session to `docs/observer/episodes-YYYY-MM.jsonl` and optionally a MD note in `docs/observer/notes/`. **Observer only writes; never intervenes.** PII-filter (gitleaks-like regex) is mandatory pre-write.

**Each episode has 5 mandatory fields** including a structured `primary_rationale` (7 sub-fields per spec §5.2.1: `step` / `node_chosen` / `triggers_matched` / `candidates_considered` / `boundaries_applied` / `hard_floor` / `task_classification`). Each individual router decision is also recorded as a `routing_decision` event in `events[]` (one per node-choice for chains). This enables **factor analysis** through `/brain-retro` — answers «which factors most often resolve conflicts between nodes X and Y» rather than just «node X used N times».

A `/brain-retro` skill aggregates evidence once per sprint and proposes regulatory candidates; the owner accepts or rejects manually.

### 3. 5 mechanical controllers

All 5 are mechanical (regex/diff/JSON math). 0 LLM calls in hot path.

- **C1 L1-watcher** — lefthook job + weekly cron. Detects plugins in `settings.json` not formalized in Tooling Прил. Н.
- **C2 Cross-ref consistency** — lefthook job, regex-style (adr-judge analog). Detects version drift between normative files.
- **C3 Observer-of-observer** — counter + lefthook warn. Self-prune through **54 weeks** without reads.
- **C4 STATUS dashboard** — `docs/observer/STATUS.md`, regenerated per-commit.
- **C5 Observer-coverage-checker** — lefthook warn-only job. Flags observer coverage gaps (git activity but 0 episodes) and registration-integrity breaks (Stop-hook missing from `settings.json`, `post-commit` not installed). Surfaced in STATUS.md.

### 4. Behavioral rule «unused ≠ problem»

The capability-readiness strategy is explicit. A node never used on a real task is **not** a problem and **not** an auto-removal candidate. Used-count is informational, never an alert. This rule overrides the analytical instinct to «prune unused».

Exception: deprecated upstream packages or physically broken tools (separate category — `npm audit` / `composer outdated`).

### 5. Observer factor-analysis extension (v2)

The observer episode is extended to `schema_version: 2` so a real factor analysis becomes possible: `decision_provenance` (autonomous vs user-dictated method, with a counterfactual), `environment` factors, `task_size`, `prompt_signal`, and an honest `outcome` of `unknown` at write time. Four layers — schema v2, deterministic capture + a routing-tag, two-sided enforcement (Stop-hook routing-gate + C5 self-discipline controller), `/brain-retro` analysis. The routing-gate makes provenance reliable: when the user dictates a method and the routing-tag is missing, the Stop-hook returns `decision: block`. Spec: `docs/superpowers/specs/2026-05-19-observer-factor-analysis-design.md`.

## Consequences

### Positive

- Speculative regulation eliminated structurally — no chain catalog can drift.
- Evidence-loop active from day 1 — owner has data for monthly/quarterly review.
- 3 recurring problem classes (L1-pattern, version drift, evidence consumption) closed mechanically with 0 LLM cost.
- Capability-readiness preserved — installed-but-unused tools are not flagged.

### Negative / risks

- 4 new lefthook jobs add ~1–2s to pre-commit.
- Observer JSONL grows ~50–200KB/month; archival after 12 months is a manual task.
- C3 54-week threshold is long — if observer infra is broken silently, detection waits up to a year. Mitigator: C4 STATUS.md shows weekly read-counter.

### Neutral

- The decision is reversible at low cost: removing controllers = `lefthook.yml` revert; removing observer = unregister Stop-hook + archive `docs/observer/`.

## Enforcement

- C1 / C2 / C3 lefthook jobs fail-fast on commit when invariants break.
- C4 STATUS.md regeneration on post-commit (informational; not a gate).
- Observer routing-gate runs inside `observer-stop-hook.mjs` (`decision: block` when a method is dictated without a routing-tag); C5 observer-coverage-checker is a warn-only lefthook job.
- ADR-011 itself is enforced by **adr-judge** (lefthook job 9) — this section's existence is verified per-commit (regex `^## Enforcement$`).

## References

- spec: `docs/superpowers/specs/2026-05-19-brain-governance-design.md`
- spec (extension): `docs/superpowers/specs/2026-05-19-observer-factor-analysis-design.md`
- plan: `docs/superpowers/plans/2026-05-19-brain-governance.md`
- plan (extension): `docs/superpowers/plans/2026-05-19-observer-factor-analysis.md`
- ADR-010 (HK1 pre-check hard-rule)
- Pravila §12 / §14 / §15 (hard-floor for router procedure step 1)
- PSR_v1 R15 (off-phase routing extends to brain governance)
- memory: `feedback_brain_unused_tools_not_problem.md`, `project_brain_governance_design.md`

## Amendment 2026-05-21: Conditional missed-activation rule (§16.4 v1.36)

The original §16.4 stated unconditionally that an unused node is not a problem. Real-world episodes show this is too permissive: when a profile-classified task (e.g. `refactor`) runs with `node_chosen === 'direct'` and a relevant non-dormant node exists in Tooling Прил.Н, the absence of activation IS a signal (router miss, not a problem in the node itself).

The rule now reads:

- **Unused + no profile task** → still not an alert (capability-readiness).
- **Unused + profile task present** → "missed activation", surfaced in STATUS.md C5 and `/brain-retro`. Not a commit block.

**Mapping artefacts:**

- `tools/observer-classification-map.json` — manual mapping `classification → recommended_node_ids[]` (single source of truth). 10 classification buckets, populated from the real `tools/observer-transcript-parser.mjs` `classifyTask` dictionary (bugfix / cleanup / feature / memory-sync / monitoring / other / planning / question / refactor / analysis).
- `tools/.node-dormancy.json` — generated from Прил.Н by `tools/extract-node-dormancy.mjs` (pre-commit job `extract-node-dormancy` in `lefthook.yml`). Uses a **two-signal** availability check: `dormant: true` in the 9-attribute row OR keyword `DEFERRED` in the boundaries column. Both signals normalize to the same JSON value, so consumers don't distinguish "permanent dormant" (#17) from "deferred-pending" (#44 / #50 / #54 / #67) — they're all "cannot activate right now".
- `tools/missed-activations.mjs` — pure deterministic matcher. Exports `detectMissedActivations(episodes, classificationMap, dormancy)`. No fs, no exec.

**Detection threshold:** single episode (per user decision 2026-05-21). No smoothing; every qualifying episode counts.

**DEFERRED exclusion:** nodes flagged as unavailable in `.node-dormancy.json` are filtered before counting. Current dormant set: #1 (replaced), #17 (pg_partman, native-Windows), #44 (Figma MCP, no Figma account), #50 (Jupyter MCP, no Python ML env), #54 (n8n-mcp, n8n not in stack), #67 (NightOwl, pending Б-1 / Linux).

**Surfacing:**

- C5 `observer-coverage-checker` includes `missed.totalMissed` in its return value; the CLI emits `WARN — missed activations: N (see /brain-retro)` when N > 0.
- `status-md-generator` renders `missed_activations: N` in the metrics block; C5 row turns ⚠️ when N > 0.
- `/brain-retro` `analyze(episodes, { classificationMap, dormancy })` returns `missedActivations: { totalMissed, byNode, byClassification }` — the retro skill renders a per-node + per-classification breakdown.

**Initial measurement on May 2026 episodes:** 16 missed activations, dominated by memory-sync × 7 (CLAUDE.md edits without `#33 claude-md-management` chosen) and feature × 4 (no Superpowers brainstorming invocation). This is the kind of "router miss" signal the rule is designed to surface, not a problem in the unactivated nodes themselves.

**Linkage:**

- Pravila §16.4 v1.36 (2026-05-21).
- Plan: `docs/superpowers/plans/2026-05-21-observer-missed-activations.md`.
- Spec / decision rationale: this amendment.
