Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 KiB
id, title, status, date, related
| id | title | status | date | related | ||||
|---|---|---|---|---|---|---|---|---|
| ADR-011 | Brain governance — router-only + observer + 4 mechanical controllers | Accepted | 2026-05-19 |
|
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:
- L1-pattern: plugin enabled in
~/.claude/settings.jsonuser-level without formalization in Tooling Прил. Н. Occurred 3× in 8 days (UPM/21st 10.05; Sentry/Redis 13.05; Anthropic dev-tooling 18.05). - Version drift between 8 normative files. Tooling v2.11 collision 17.05.2026 — two parallel sessions consumed the same version number.
- 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 Прил. Н §4.X (extended with 9 obligatory attributes per spec §4.1) + the procedure in docs/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 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.jsonnot 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-commitnot 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.ymlrevert; removing observer = unregister Stop-hook + archivedocs/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: blockwhen 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 mappingclassification → recommended_node_ids[](single source of truth). 10 classification buckets, populated from the realtools/observer-transcript-parser.mjsclassifyTaskdictionary (bugfix / cleanup / feature / memory-sync / monitoring / other / planning / question / refactor / analysis).tools/.node-dormancy.json— generated from Прил.Н bytools/extract-node-dormancy.mjs(pre-commit jobextract-node-dormancyinlefthook.yml). Uses a two-signal availability check:dormant: truein the 9-attribute row OR keywordDEFERREDin 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. ExportsdetectMissedActivations(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-checkerincludesmissed.totalMissedin its return value; the CLI emitsWARN — missed activations: N (see /brain-retro)when N > 0. status-md-generatorrendersmissed_activations: Nin the metrics block; C5 row turns ⚠️ when N > 0./brain-retroanalyze(episodes, { classificationMap, dormancy })returnsmissedActivations: { 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.