.agents/skills/improve-codebase-architecture/REFERENCE.md
When assessing a candidate for deepening, classify its dependencies:
Pure computation, in-memory state, no I/O. Always deepenable — just merge the modules and test directly.
Dependencies that have local test stand-ins (e.g., PGLite for Postgres, in-memory filesystem). Deepenable if the test substitute exists. The deepened module is tested with the local stand-in running in the test suite.
Your own services across a network boundary (microservices, internal APIs). Define a port (interface) at the module boundary. The deep module owns the logic; the transport is injected. Tests use an in-memory adapter. Production uses the real HTTP/gRPC/queue adapter.
Recommendation shape: "Define a shared interface (port), implement an HTTP adapter for production and an in-memory adapter for testing, so the logic can be tested as one deep module even though it's deployed across a network boundary."
Third-party services (Stripe, Twilio, etc.) you don't control. Mock at the boundary. The deepened module takes the external dependency as an injected port, and tests provide a mock implementation.
The core principle: replace, don't layer.
Describe the architectural friction:
The chosen interface design:
Which category applies and how dependencies are handled:
Durable architectural guidance that is NOT coupled to current file paths: