Skip to main content
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

  1. Run once to see the shape of the drift.
    strata check
    
  2. 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"]
    
  3. Turn off the rules that imply refactors you are not ready for, and keep moving:
    select = ["SF"]
    ignore = ["SFR302", "SFS001", "SFS002", "SFS003"]
    
  4. 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.
  5. 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 satisfyOften implies a refactor
SFL001, SFL002 (imports)SFR layout and placement (moving files between packages)
SFX hygieneSFS001/SFS002/SFS003 orchestrator caps (splitting functions)
SFA annotationsSFL101/SFL102 boundary rules (untangling cross-package imports)
SFN001 namingSFR401 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.