$npx -y skills add softspark/ai-toolkit --skill architecture-auditAudits codebase for architectural friction, shallow modules; proposes RFCs. Triggers: improve architecture, shallow modules, deepen modules, reduce coupling.
| 1 | # Architecture Audit |
| 2 | |
| 3 | $ARGUMENTS |
| 4 | |
| 5 | Explore a codebase organically, surface architectural friction, and propose module-deepening refactors as GitHub issue RFCs. |
| 6 | |
| 7 | ## Usage |
| 8 | |
| 9 | ``` |
| 10 | /architecture-audit [area to audit or 'full codebase'] |
| 11 | ``` |
| 12 | |
| 13 | ## What This Command Does |
| 14 | |
| 15 | 1. **Explores** codebase organically — friction IS the signal |
| 16 | 2. **Presents** deepening candidates to user |
| 17 | 3. **Frames** problem space for chosen candidate |
| 18 | 4. **Spawns** 3+ parallel sub-agents for radically different interface designs |
| 19 | 5. **Compares** and recommends |
| 20 | 6. **Files** RFC as GitHub issue |
| 21 | |
| 22 | ## Key Concept |
| 23 | |
| 24 | A **deep module** (Ousterhout) has a small interface hiding a large implementation. Deep modules enhance testability, AI navigation, and enable boundary testing. |
| 25 | |
| 26 | A **shallow module** has a large interface with thin implementation — avoid. |
| 27 | |
| 28 | ## Process |
| 29 | |
| 30 | ### 1. Organic Exploration |
| 31 | |
| 32 | Use Agent (subagent_type=Explore) to navigate the codebase naturally. Note friction: |
| 33 | |
| 34 | - Where does understanding one concept require bouncing between many small files? |
| 35 | - Where are modules so shallow the interface is nearly as complex as the implementation? |
| 36 | - Where have pure functions been extracted just for testability but real bugs hide in how they're called? |
| 37 | - Where do tightly-coupled modules create integration risk in the seams? |
| 38 | - What is untested or hard to test? |
| 39 | |
| 40 | ### 2. Present Candidates |
| 41 | |
| 42 | Numbered list. For each candidate show: |
| 43 | |
| 44 | | Field | Content | |
| 45 | |-------|---------| |
| 46 | | Cluster | Which modules/concepts are involved | |
| 47 | | Why coupled | Shared types, call patterns, co-ownership | |
| 48 | | Dependency category | In-process, Local-substitutable, Ports & Adapters, or True external (see reference/) | |
| 49 | | Test impact | What existing tests would be replaced by boundary tests | |
| 50 | |
| 51 | Do NOT propose interfaces yet. Ask: "Which would you like to explore?" |
| 52 | |
| 53 | ### 3. Frame the Problem Space |
| 54 | |
| 55 | For the chosen candidate, write a user-facing explanation: |
| 56 | - Constraints any new interface would satisfy |
| 57 | - Dependencies it would rely on |
| 58 | - Rough illustrative code sketch (not a proposal — just grounding) |
| 59 | |
| 60 | Show to user, then immediately proceed to step 4. |
| 61 | |
| 62 | ### 4. Design Multiple Interfaces |
| 63 | |
| 64 | Spawn 3+ sub-agents in parallel via Agent tool. Each gets a different constraint: |
| 65 | |
| 66 | | Agent | Constraint | |
| 67 | |-------|-----------| |
| 68 | | Agent 1 | Minimize interface — 1-3 entry points max | |
| 69 | | Agent 2 | Maximize flexibility — many use cases and extension | |
| 70 | | Agent 3 | Optimize for most common caller — default case trivial | |
| 71 | | Agent 4 | Ports & adapters pattern (if cross-boundary) | |
| 72 | |
| 73 | Each outputs: interface signature, usage example, what it hides, dependency strategy, trade-offs. |
| 74 | |
| 75 | Present sequentially, compare in prose, give opinionated recommendation. |
| 76 | |
| 77 | ### 5. Create GitHub Issue RFC |
| 78 | |
| 79 | Use `gh issue create` with template below. Don't ask for review. |
| 80 | |
| 81 | ## Issue Template |
| 82 | |
| 83 | <issue-template> |
| 84 | |
| 85 | ## Problem |
| 86 | |
| 87 | Architectural friction: |
| 88 | - Which modules are shallow and tightly coupled |
| 89 | - Integration risk in the seams |
| 90 | - Why this makes the codebase harder to navigate/maintain |
| 91 | |
| 92 | ## Proposed Interface |
| 93 | |
| 94 | - Interface signature (types, methods, params) |
| 95 | - Usage example |
| 96 | - What complexity it hides |
| 97 | |
| 98 | ## Dependency Strategy |
| 99 | |
| 100 | - **In-process**: merged directly |
| 101 | - **Local-substitutable**: tested with [specific stand-in] |
| 102 | - **Ports & adapters**: port definition, production adapter, test adapter |
| 103 | - **Mock**: mock boundary for external services |
| 104 | |
| 105 | ## Testing Strategy |
| 106 | |
| 107 | - New boundary tests to write |
| 108 | - Old shallow tests to delete |
| 109 | - Test environment needs |
| 110 | |
| 111 | ## Implementation Recommendations |
| 112 | |
| 113 | Durable guidance NOT coupled to file paths: |
| 114 | - What the module should own |
| 115 | - What it should hide |
| 116 | - What it should expose |
| 117 | - How callers migrate |
| 118 | |
| 119 | </issue-template> |
| 120 | |
| 121 | ## Dependency Categories |
| 122 | |
| 123 | | Category | Description | Deepenable? | |
| 124 | |----------|-------------|-------------| |
| 125 | | In-process | Pure computation, no I/O | Always | |
| 126 | | Local-substitutable | Has local test stand-ins (PGLite, in-memory FS) | If stand-in exists | |
| 127 | | Remote but owned | Your services across network (Ports & Adapters) | Via port injection | |
| 128 | | True external | Third-party (Stripe, Twilio) — mock at boundary | Via mock injection | |
| 129 | |
| 130 | ## Testing Principle |
| 131 | |
| 132 | **Replace, don't layer.** Old unit tests on shallow modules are waste once boundary tests exist — delete them. Tests assert on observable outcomes through public interface, not internal state. |
| 133 | |
| 134 | ## Rules |
| 135 | |
| 136 | - **MUST** explore the codebase organically (Explore sub-agent) before proposing deepening targets — do not anchor on what you already know |
| 137 | - **MUST** present numbered candidates to the user and wait for selection before step 3 — auto-picking skips the product decision |
| 138 | - **NEVER** design interfaces in step 2; interface work only happens in step 4 af |