Context

Because wiring is plain ES imports (ADR-002), an inter-module cycle compiles silently. Bun surfaces circular dependencies at runtime as undefined module members — a confusing error with no indication of the cycle path. More importantly, a cyclic module graph means every module in the cycle is load-bearing for all the others: you cannot extract, test, or understand any one of them in isolation.

Decision

The module dependency graph must be a directed acyclic graph (DAG). A topological sort must exist. Inter-module cycles are detected by patties graph using a DFS with colour marking and are always a hard failure (CI exit 1). Intra-module file cycles are a warning by default. The --strict flag promotes them to failures.

Consequences

Cyclic dependencies are caught on every push rather than surfacing at runtime. The fix pattern is explicit: extract shared concepts into a third module, or replace a direct import with a callback/event interface to flip the dependency direction. Cost: some initially convenient bidirectional designs must be refactored. This is the point — convenience is not a justification for spaghetti.

Patties design specifications · a design exploration · All decisions