Strata’s defaults describe a coherent target architecture. How you turn them on
depends on where you are starting.
New repos
The defaults are calibrated for a fresh repo. Turn everything on from the first
commit and the structure carries you: there is very little to fix, because there is
little code yet, and the rules keep it on the rails as it grows.
roots = ["src/my_package"]
tests = ["tests"]
That is the recommended starting point. This is where Strata is easiest to live
with, because you never accumulate drift in the first place.
Existing repos
Pointing the full default set at a large existing repo will surface a lot at once.
That is not the tool overreacting; it is measuring real drift against the target
architecture. But a big-bang refactor to reach zero faults is usually the wrong
response, and it is rarely safe.
The goal is to adopt gradually: enforce what is cheap and valuable now, and defer
the rules that would force structural moves until you actually want to make them.
Enforce as aggressively as you can refactor safely, and no more. If your test
suite would not catch a bad structural move, do not let the linter pressure you
into one. Turn those rules off for now and come back to them when you have the
coverage or the appetite.
A gradual rollout
-
Run once to see the shape of the drift.
-
Start from a small, high-value set rather than everything. The import and
hygiene families tend to be cheap wins:
select = ["SFL", "SFX", "SFA", "SFN"]
-
Turn off the rules that imply refactors you are not ready for, and keep
moving:
select = ["SF"]
ignore = ["SFR302", "SFS001", "SFS002", "SFS003"]
-
Scope enforcement to the code you trust. If one package is well tested and
another is legacy, point
roots at the part you want held to the standard and
leave the rest out for now.
-
Tighten over time. Re-enable families or drop entries from
ignore as you
refactor, so the enforced standard ratchets up with your confidence.
See choosing rules for the full mechanics.
Which rules cost what
Friction depends on your code, but as a rough guide when deciding what to enable
first:
| Usually cheap to satisfy | Often implies a refactor |
|---|
SFL001, SFL002 (imports) | SFR layout and placement (moving files between packages) |
SFX hygiene | SFS001/SFS002/SFS003 orchestrator caps (splitting functions) |
SFA annotations | SFL101/SFL102 boundary rules (untangling cross-package imports) |
SFN001 naming | SFR401 entry-module shape (reshaping public surfaces) |
The left column is mostly local, mechanical edits. The right column can move code
across module boundaries, so it benefits most from good tests and a deliberate pace.
Prefer custom rules over contortions
If a default rule does not fit how a part of your repo is legitimately built, do
not twist the code to pass it. Turn that rule off and, where it matters, write a
custom rule that encodes the invariant you actually care
about.
This is often the better move for an existing codebase: instead of a disruptive
refactor to satisfy a generic rule, you capture your real architectural intent as an
executable check. You reduce the immediate refactor pressure while still gaining
enforcement, and the custom rule flows into your generated
agent guidance like any core rule.
The through-line
Strata is opinionated by default, but adoption is meant to be deliberate. On a new
repo that means all-on from the start; on an existing one it means a rollout you
control, matched to how safely you can change the code. Either way, deviations live
in configuration where they are visible, not scattered
through the source. See Philosophy for why that matters.