2 pointsby kvlonge5 hours ago1 comment
  • kvlonge5 hours ago
    I built Fensu, an architecture linter for Python and TypeScript/SvelteKit. Unlike normal linters that mostly enforce rules inside individual files, Fensu tries to preserve the shape of a growing repository: which layers may import which, what belongs in each module, how large orchestrators can become, where public surfaces live, etc.

    It ships with an opinionated default architecture rather than just a blank rule framework, but the rules can be disabled, extended, or replaced with your own. For example, the Python default organizes code into domains with defined roles for things like models, types, classes, helpers, and public entry points. Domains can contain those roles directly or split into named subdomains that follow the same structure.

    When that structure drifts, fensu check produces deterministic faults explaining both what was violated and how to fix it. So rather than a reviewer repeatedly saying "this shouldn't import that" or "this logic belongs in a helper", those decisions can become executable rules that fail locally and in CI.

    It also has fensu map, which statically renders downstream call trees with source locations.

    Tests preserve behavior and types preserve interfaces, but most architectural knowledge still lives in READMEs and code review. I've found executable architecture constraints especially useful with coding agents (or team members using them), where very large refactors are now practical but architectural drift can happen at the same scale. I've used Fensu while doing refactors touching 1,000+ files and across 10+ repos at work. Not saying you need to be that extreme, but it did work.

    Regardless of what you think of the library, I'd encourage people to try writing deterministic rule checkers for their own repos. Once they're in place, they save an unbelievable amount of time and stop a lot of the same arguments from happening repeatedly in code review (or cursing at an agent).

    The built-in Python and TypeScript analyzers and rules are implemented natively in Rust, so checking TypeScript/SvelteKit doesn't require starting Node. Python repos can also define custom rules when the built-ins don't match their architecture. Custom rules can call into parts of the Rust-backed analysis API too, so you don't necessarily have to give up the performance of the native analyzer when writing your own checks.

    Install with: pip install fensu

    Then run: fensu

    https://github.com/chio-labs/fensu