Files
Mastermind/docs/adr/0005-strict-clean-capability-architecture.md
T

2.2 KiB

ADR 0005: Strict Clean Architecture and Capability Modules

Context

Mastermind is a complex macOS application with multiple responsibilities: continuous capture, knowledge extraction, local graph management, and AI assistance. To ensure maintainability, testability, and clear ownership of privacy boundaries, we need a robust architectural structure.

Decision

We adopt a Strict Clean Architecture organized around Capability Modules.

1. Capability Modules

The codebase is divided into stable capability boundaries:

  • AppShell: Orchestration, lifecycle, and composition root.
  • Observation: Collectors and raw evidence acquisition.
  • Knowledge: The Context Graph, projection, and retrieval logic.
  • Assistant: AI sessions, provider routing, and prompt management.
  • Trust: Activity logging, health monitoring, and privacy enforcement.
  • Infrastructure: Shared utilities, encryption, and low-level storage.

2. Strict Clean Architecture

Each module follows Clean Architecture principles:

  • Entities: Pure domain models and logic (inner-most).
  • Use Cases/Services: Application-specific business rules.
  • Interface Adapters: Controllers, presenters, and gatekeepers.
  • Frameworks & Drivers: External tools like ScreenCaptureKit, SQLite, and sidecar clients (outer-most).

3. Compile-Time Dependency Rule

  • Dependencies flow inwards: outer layers depend on inner layers.
  • Modules communicate through Application Ports (protocols).
  • Protocols are required at module boundaries and for all I/O (adapters).
  • Internal module logic does not require protocols for every internal function or value type, avoiding unnecessary boilerplate.

4. Enforcement

  • Boundaries are enforced by separate Swift targets/modules where possible.
  • The Composition Root (in AppShell) is the only place where concrete adapters are instantiated and injected.

Consequences

  • Pros: Clearer boundaries, easier to mock dependencies for testing, better isolation of sensitive data processing, and independent evolution of capabilities.
  • Cons: Higher initial setup cost for new modules and mandatory boilerplate for cross-module communication.