enhance-arch-boundaries · git:20260818.6723100 · 2026-08-18 · sha256 703b9348b7d3b3ab

enhance-arch-boundaries git:20260818.6723100A

Immutable. This exact content never changes and is served at /api/v1/blob/703b9348b7d3b3ab.

---
name: enhance-arch-boundaries
description: >
  Install mechanically-enforced architecture boundaries (dependency-cruiser /
  eslint-boundaries) so layer direction, feature isolation, and forbidden
  imports fail CI. Use when "enforce module boundaries", "stop spaghetti
  imports", "add architecture rules". Advisory audit →
  audit-backend-architecture.
license: MIT
---

# enhance-arch-boundaries — Architecture as a fitness function

Codify the repo's intended structure as rules that block merge. **Import
spaghetti is how agents degrade architecture: each import looks locally
reasonable, no single diff is wrong, and after forty sessions the
layering is gone.** A rule in AGENTS.md is advisory. A dependency-cruiser
rule in the aggregator gate is physics.

## This skill vs neighbors

| Skill | Owns |
|---|---|
| **enhance-arch-boundaries** (this) | Mechanical boundary rules + shrink-only baseline |
| `audit-backend-architecture` | Advises which pattern to adopt — does not enforce |
| `housekeep-gates` | Wires this check into the aggregator |
| `docs-adr` | Records *why* the model was chosen |
| `enhance-agent-guardrails` | Broader guard install; this owns the import graph |

---

## Phase 0 — Recover the intended architecture (do not invent one)

The rules must encode the architecture the repo *means* to have.

- Read folder structure and existing conventions (`features/*`, `app/`,
  `lib/`, `server/`, `components/`, monorepo packages).
- Read `audit-backend-architecture` output if it exists — that is the
  drift to stop.
- Confirm with the user in one pass: layers and allowed direction (e.g.
  `ui → application → domain → infrastructure`, never reverse), feature
  units that must stay isolated, special zones (server-only, secrets,
  generated).

State the model in ten lines before writing any rule. If the repo
genuinely has no intended structure, **stop and say so** — enforcing a
structure nobody chose creates fights, not quality. Propose a minimal
layering first.

---

## Phase 1 — Install the rule set

Tool by stack: **dependency-cruiser** (framework-agnostic JS/TS),
**eslint-plugin-boundaries** (when living inside ESLint is preferable),
Nx module-boundary tags, import-linter (Python).

Core rules, each mapped to the confirmed model:

- **Layer direction** — lower layers cannot import upward; skipping
  layers flagged where the model says so.
- **Feature isolation** — features import each other only via a public
  surface (`features/x/index.ts`), never deep paths. Shared code goes
  through `shared/`, not sideways.
- **No circular dependencies** — anywhere. Cycles are where "change one
  thing" stops being possible.
- **Forbidden edges** — client importing server-only / service-role
  modules (cross-ref `plan-rls-audit` / `plan-secrets-audit`), UI
  importing the DB layer directly, production importing test utilities,
  anything importing generated internals.
- **No orphans** — modules nothing reaches (feeds `workflow-housekeep`).
- **Dependency hygiene** — no `devDependencies` from shipped code;
  deprecated internals marked un-importable so migration ratchets.

---

## Phase 2 — Grandfather, then ratchet

Do not weaken the rules to fit existing violations, and do not block the
repo on fixing them all.

- Capture existing violations into the tool's **known-violations
  baseline** so CI is green today.
- The baseline is a **shrink-only ratchet**: new violations fail;
  existing ones are tracked debt; the baseline file can only get smaller
  without review — same reset policy as `housekeep-gates`.
- File the grandfathered list as a burndown, worst edges first (cycles
  and client→server-secrets before cosmetic layer skips).

---

## Phase 3 — Wire and make agent-legible

- Add the check to CI wired into the aggregator gate (`housekeep-gates`)
  and mirror it in local hooks (same command, two callers).
- Generate the dependency **graph visualization** into docs; regenerate
  it on the scheduled run so it cannot go stale.
- Write the ten-line model + "how to fix a boundary violation" into
  agent rules *referencing the mechanical check* — the rule text
  explains, the gate enforces.
- Record the architecture decision as an ADR (`docs-adr`) so a future
  session knows the layering was chosen, by whom, and why the rejected
  alternative lost.

---

## Definition of Done

- [ ] Intended model recovered from the repo + confirmed with the user (or the no-structure finding raised)
- [ ] Rules installed: layer direction, feature isolation via public surfaces, no cycles, forbidden edges (incl. server-only → client), no orphans, dep hygiene
- [ ] Existing violations grandfathered into a shrink-only baseline; burndown filed worst-first
- [ ] Check in the aggregator gate + local hooks with one shared command
- [ ] Graph visualization generated into docs with a regeneration schedule
- [ ] Agent rules updated to state the model and point at the gate; decision recorded via `docs-adr`
- [ ] Deliberate-violation probe: a test import that breaks each rule class fails CI

## Output format

1. **Architecture model** — ten-line statement of layers, directions, features, special zones
2. **Rule set** — rule | what it forbids | why (mapped to the model)
3. **Grandfathered baseline** — count by rule | worst-first burndown
4. **Wiring** — gate job, hook parity, graph location, agent-rule text added
5. **Probe evidence** — violation per rule class | CI result

Applied directly (enhance-family). Pause for approval only on the model
confirmation and before committing the baseline.