From rune
Identifies architectural friction in codebases and proposes scored deepening refactors for shallow modules to improve testability and AI-navigability.
npx claudepluginhub rune-kit/rune --plugin @rune/analyticsThis skill uses the workspace's default tool permissions.
Surface architectural friction in a codebase and propose **deepening opportunities** — refactors that turn shallow modules into deep ones. Output is structured (numeric scores + JSON proposal payloads) so `surgeon`, `review`, and `audit` can consume it programmatically without re-reading the codebase.
Surfaces shallow modules, refactoring opportunities, seams, and tight coupling; proposes deepening refactors for testability and AI-navigability using precise vocabulary.
Explores codebases to identify architectural friction and opportunities to deepen shallow modules, improving testability, refactoring, and AI navigability.
Identifies deepening opportunities in codebases by spotting shallow modules and tight coupling, informed by domain glossary and ADRs. Proposes refactors for better architecture, testability, and AI-navigability.
Share bugs, ideas, or general feedback.
Surface architectural friction in a codebase and propose deepening opportunities — refactors that turn shallow modules into deep ones. Output is structured (numeric scores + JSON proposal payloads) so surgeon, review, and audit can consume it programmatically without re-reading the codebase.
The goal is testability and AI-navigability: a deep module presents a small interface that hides large machinery, so tests target one surface and future agents can reason about the system without traversing N small wrappers.
These eight terms have precise meanings. Banned aliases: "boundary" (overloaded with DDD), "component" (UI-specific), "service" (microservice-specific), "layer" (too generic). See references/language.md for full definitions.
cook Phase 5 (quality gate) when refactor signals appear in scout outputsurgeon before any deepening session — produces the proposal surgeon executesaudit to compute the architecture sub-scorereview when a reviewer flag mentions "shallow", "wrapper", "indirection"/rune improve-architecture <module-path>scout (L2): re-scan target module + callers when input context is stalebrainstorm (L2): when the deepened module needs a new interface, hand off in design-it-twice mode (see brainstorm v0.6+)journal (L3): record an ADR if the user rejects a candidate with a load-bearing reasoncook (L1): Phase 5 quality gatesurgeon (L2): pre-refactor input; consumes the proposal payloadaudit (L2): Phase 4 architecture sub-scorereview (L2): when shallow-module flag fires during reviewimprove-architecture → surgeon — proposal payload feeds surgeon's deepening sessionimprove-architecture ↔ brainstorm — when interface needs design-it-twice explorationimprove-architecture → audit — emits architecture sub-scoreimprove-architecture → journal — records ADRs for rejected candidates with load-bearing reasonssrc/auth/) OR signal codebase.scanned from a recent scout passCONTEXT.md (domain glossary, used to name modules in their domain language)docs/adr/ directory (existing ADRs that constrain proposals — do not re-litigate)Read in order, silently skipping any that don't exist:
CONTEXT.md (or CONTEXT-MAP.md + per-bounded-context CONTEXT.md)docs/adr/ filesGlob to enumerate, cap at 30 files)If CONTEXT.md is missing, do not flag it — treat as "no domain glossary yet". If an ADR contradicts a candidate you're forming, mark it and only surface the candidate if the friction is genuine enough to warrant ADR revision.
For each candidate module, compute three numeric scores (1–5) and one verdict (enum):
| Metric | Formula / Rubric |
|---|---|
| Depth | clamp_1_5(implementation_complexity / interface_complexity) — 1 = shallow wrapper, 5 = small interface hides large machine |
| Leverage | clamp_1_5(num_callers * unique_use_cases / interface_method_count) — 1 = thin caller benefit, 5 = many callers, fewer methods to learn |
| Locality | clamp_1_5(code_concentration_index) — 1 = logic spread across N callers, 5 = logic concentrated in one place |
| Deletion test | enum: vanish (was pass-through) | concentrate (was earning keep) | redistribute (mixed) |
Rubric details and edge cases: see references/scoring.md.
For each candidate's external dependencies, classify into one of four categories. The category determines test strategy:
| Category | Definition | Test Strategy |
|---|---|---|
in-process | Pure computation, in-memory state, no I/O | Test through deepened interface directly |
local-substitutable | Has local test stand-in (PGLite, in-memory FS) | Use stand-in in tests; no port at module seam |
remote-owned | Your own module deployed across a network seam | Define a port; in-memory adapter for tests, HTTP adapter for prod |
true-external | Third-party (Stripe, Twilio) | Inject as port; mock adapter in tests |
Full doctrine in references/deepening.md.
Before recommending a port:
For each surviving candidate, produce a structured proposal in YAML:
architecture.proposal:
module_path: src/auth/
current:
depth: 2
leverage: 3
locality: 2
deletion_test: redistribute
target:
depth: 4
leverage: 4
locality: 4
dependency_category: remote-owned
suggested_seam: AuthPort
adapters_planned: [HttpAuthAdapter, InMemoryAuthAdapter] # 2 = real seam ✅
tests_to_replace: [auth/login.test.ts, auth/session.test.ts]
tests_to_write_new: [auth/AuthPort.test.ts]
domain_terms_used: [Customer, Session] # from CONTEXT.md if present
adr_conflicts: []
Numbered list, each candidate showing:
CONTEXT.md provides oneDo NOT propose interfaces yet. Ask: "Which candidate to explore?"
When user picks a candidate, hand off:
brainstorm in design-it-twice mode if the new interface is non-obvious (multiple credible shapes)surgeon with the proposal payload otherwiseIf user rejects a candidate with a load-bearing reason ("we don't want to centralize auth because of compliance audit isolation"), offer to record an ADR via journal (only if score >= 11 per journal v0.4 criteria).
## Architecture Improvement Report
### Target
- **Path**: src/auth/
- **CONTEXT.md present**: yes / no
- **ADRs reviewed**: 3 (none conflicting)
### Candidates
#### 1. Auth port consolidation (depth 2 → 4)
- **Files**: src/auth/login.ts, src/auth/session.ts, src/auth/middleware.ts
- **Problem**: 3 shallow modules each handle one HTTP-flavored verb; logic about `Customer` identity is split across all three (locality = 2)
- **Solution**: collapse into AuthPort exposing `authenticate`, `revoke`, `verify` — 3 methods, deep impl
- **Benefits**: callers learn 3 methods instead of N free functions; auth logic concentrated; tests target the port
- **Score delta**: depth 2→4, leverage 3→4, locality 2→4
- **Deletion test**: redistribute (current modules ARE doing work, just spread)
#### 2. ...
### Recommendation
Candidate 1 — strongest leverage gain. Hand off to `brainstorm` design-it-twice for the AuthPort shape (3 credible alternatives), then `surgeon`.
### Architecture sub-score
- Current: 58/100
- Projected after candidate 1: 78/100
| Artifact | Format | Location |
|---|---|---|
| Architecture Improvement Report | Markdown | inline |
| Proposal payloads | YAML | inline (per candidate) |
| Architecture sub-score | integer 0-100 | inline + emitted to audit |
| ADR draft (if user rejects with load-bearing reason) | Markdown | .rune/adr/ADR-NNN-<slug>-s<score>.md via journal |
CONTEXT.md / ADR directory — do not flag as project gap| Failure Mode | Severity | Mitigation |
|---|---|---|
| Recommending a deepening that contradicts a documented ADR | HIGH | Step 1 reads ADRs; if conflict, surface only if friction is real enough to revise the ADR |
| Single-adapter seam slips into proposal | HIGH | Step 4 rule — drop or downgrade to "internal seam" |
| Vocabulary drift (using "boundary"/"component"/"service") | MEDIUM | Constraint 1 + linter pass in compiler/tests/vocabulary-discipline.test.js |
| Score inflation to make weak candidate look strong | HIGH | Each metric has rubric in scoring.md; judges show formula inputs |
| Missing CONTEXT.md domain terms — generic naming ("AuthService") | MEDIUM | If CONTEXT.md exists, names MUST come from it; otherwise OK |
| Proposing interface in same pass as candidates | MEDIUM | Step 6 hard-stops at candidate list; interface design = brainstorm Design-It-Twice |
| User rejects all candidates → no ADR recorded → next session re-litigates | MEDIUM | If reason is load-bearing AND score >= 11, offer journal ADR write |
SELF-VALIDATION (run before emitting Report):
- [ ] Every candidate has depth + leverage + locality scores (1-5 each)
- [ ] Every candidate has deletion-test verdict (vanish | concentrate | redistribute)
- [ ] Every candidate names a dependency category (in-process | local-substitutable | remote-owned | true-external)
- [ ] No banned vocabulary (grep candidate text for: boundary, component, service, layer in narrative)
- [ ] No interfaces drafted yet — that's brainstorm's job
- [ ] CONTEXT.md domain terms used if file present
- [ ] Each adapter list has >=2 entries OR seam is marked "internal-only"
IF ANY check fails → fix before reporting done.
~3000-7000 tokens input (codebase scan), ~2000-4000 tokens output (analysis + proposals). Opus model — architectural reasoning depth is the value. Called at most once per audit session, on-demand from cook / surgeon.
chain_metadata:
skill: "rune:improve-architecture"
version: "0.1.0"
status: "[DONE]"
domain: "[module path scored]"
exports:
architecture_subscore: 0-100
candidates: [{ module, depth, leverage, locality, verdict }]
proposal_payloads: [<yaml-per-candidate>]
suggested_next:
- skill: "rune:brainstorm"
mode: "design-it-twice"
reason: "Top candidate has multiple credible interface shapes — need diverse exploration before commit"
consumes: ["proposal_payloads"]
- skill: "rune:surgeon"
reason: "User picked candidate; interface shape is obvious; ready for deepening session"
consumes: ["proposal_payloads"]
- skill: "rune:journal"
reason: "User rejected candidate with load-bearing reason; record ADR (score >=11)"
consumes: ["candidates", "rejection_reason"]
Scope guardrail: improve-architecture proposes and scores. It NEVER edits code. Refactor execution belongs to surgeon. Interface exploration belongs to brainstorm Design-It-Twice mode.