Files
portal/docs/adr/ADR-011-brain-governance.md
T
Дмитрий bcdda41df4 docs(adr): ADR-011 amendment — conditional missed-activation rule
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:00:24 +03:00

10 KiB
Raw Blame History

id, title, status, date, related
id title status date related
ADR-011 Brain governance — router-only + observer + 4 mechanical controllers Accepted 2026-05-19
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 Rec1Rec5; 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 Прил. Н §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 L1L12 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.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 dashboarddocs/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 ~12s to pre-commit.
  • Observer JSONL grows ~50200KB/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.