Three more static code analysis sensors
Birgitta BΓΆckeler (published on martinfowler.com) Β· rss Β· 2026-05-20 source β Reader π₯οΈ
Agent SkillsCode QualityEvolutionary Architecture & Fitness FunctionsFeedback LoopsModularity & Coupling
For maintainability concerns that cross file and module boundaries, computational static-analysis sensors (dependency rules, coupling metrics) can usefully enforce a few structural invariants but cannot judge what coupling is appropriate; the most productive sensor is an inferential, prompt-driven AI modularity review that reads the code itself, with the deterministic tools relegated to enforcement of known rules and to triage of review attention.
practical Β· mixed β An experience report that argues for a practical position: how to combine computational and inferential sensors for cross-module maintainability when AI is doing the coding. Mostly expository/narrative ('here is what I tried') but with clear normative takeaways.
Structure
| Part | Role |
|---|---|
| Framing: from in-file linting to cross-module sensors | context |
| Sensor 1 β Dependency rules via dependency-cruiser (layered module structure, custom error messages that double as self-correction guidance for the agent) | evidence (case 1) |
| Sensor 2 β Custom coupling-data CLI (vibe-coded with a TypeScript-compiler-based analyser; two interfaces: web visualisations for humans, CLI output for agents) | evidence (case 2, mostly negative) |
| Sensor 3 β Inferential 'AI modularity review' using Vlad Khononov's Modularity Skills, run against the codebase itself (not just metrics) | evidence (case 3, positive) |
| Cross-cutting observations: repeat the analysis to surface more, grounding inferential review in deterministic data added little, computational sensors alone are insufficient | synthesis |
| Forward pointer to next installment on regression testing, coverage, and mutation testing as sensors | context |
Key terms
- sensor Feedback Loops
Any tool β deterministic or AI-driven β that feeds back signals about a code change to the agent (or human) so that self-correction is possible before issues reach human review. Sensors run at different cadences: in-session, in CI, on a slow schedule, or in production. - computational sensor Feedback Loops
A deterministic, rule-based tool whose output is reproducible given the same inputs (linter, type-checker, dependency-cruiser, coupling-analyser, SAST). - inferential sensor Feedback Loops
An LLM-driven review (prompt + model + sometimes auxiliary CLI tools) whose output is interpretive and not bit-reproducible. Useful when 'what counts as bad' depends on context. - self-correction guidance Feedback Loops
Extra prose embedded in a sensor's error/warning messages, written specifically so that an AI agent reading the output understands what to do β effectively a controlled prompt injection at the point of failure. - dependency rules Modularity & Coupling
Declarative constraints (in this case dependency-cruiser config) that forbid imports across designated layer boundaries β e.g. clients must not import from services. - coupling data Modularity & Coupling
Per-file metrics about incoming and outgoing imports/calls, produced by her custom 'coupling-analyser' CLI, optionally visualised as e.g. a DSM. - AI modularity review Modularity & Coupling
A scheduled, prompt-driven LLM analysis that reads the actual code (not just metrics) using a curated 'skills' pack (Vlad Khononov's Modularity Skills) and emits concrete refactoring recommendations. - Modularity Skills (Khononov) Agent Skills
An external, reusable prompt/skill bundle by Vlad Khononov that operationalises modularity heuristics for LLM-based codebase review. - garbage collection (metaphor)
Used by analogy: the AI modularity review acts like a periodic sweep that finds accumulated waste (duplicate routes, scattered parameters, misplaced responsibilities) that the agent would not refactor on its own initiative. - impact radius Modularity & Coupling
The set of callers/dependents potentially affected by a change to a given file β proposed as a future use for coupling data during human code review triage.
Propositions
- explicitAnalysis of cross-file/cross-module concerns is historically even more under-used than basic linting.conf: high
- explicitdevelopedCustom error messages that explain the underlying concept (layering, etc.) work as self-correction guidance for AI agents and meaningfully change agent behaviour.conf: highextends βExperiences with local models for coding Β· p19 β Thematic extension of BΓΆckeler's own sensor / self-correction program (that extract is about *static* code-analysis sensors whose custom error messages steer agents; here she invokes a *runtime* browser sensor the agent never called). Same underlying idea β self-correction feedback changes agent behaviour β extended to small local models as a lever for viability.
- explicitAI made it economically viable to author dependency-cruiser rules whose configuration syntax would otherwise be too costly to learn.conf: high
- explicitcontestedDependency-cruiser-style rules can substitute for a markdown 'how this codebase is structured' guide because they actively enforce the structure rather than describing it.conf: highcontradictsAlex Wang's Post Β· p1 β Bockeler claims enforceable dependency rules can replace the prose architecture guide, while Wang says stable architecture context belongs in CLAUDE.md markdown.
- explicitFolder-based dependency rules need a meta-rule that any new file must be located inside the predefined folder structure; otherwise the agent escapes the system by inventing new folders.conf: high
- explicitWhat dependency-cruiser-style tools can encode is bounded by what is expressible via imports, file names, and folder structure.conf: highrefinesArchitecture as Code to Teach Humans and Agents About Architecture Β· p7 β Bounds the claim that architecture is objectively definable everywhere: structural tools only encode what imports, file names, and folder structure can express.
- explicitDependency-structure visualisations (DSMs etc.) are too low-level to meaningfully reduce reviewer cognitive load on AI-changed codebases.conf: medium
- explicitEven a strong model (Claude Opus 4.7) interpreting raw coupling metrics produces lackluster, often wrong, findings because it cannot tell intentional patterns (DI factories, shared frontend/backend schemas) from coupling smells.conf: high
- explicitIf raw coupling metrics are used as input to an LLM, legitimate high-coupling hubs must be suppressible, or the noise compounds.conf: high
- explicitCoupling metrics' best use is triage of human (or agent) attention during code review β surfacing changes whose blast radius is large β not autonomous quality judgement.conf: high
- explicitA prompt-driven LLM review that reads the actual code outperforms an LLM constrained to metric output.conf: high
- explicitAI agents will, by default, copy-paste rather than refactor toward shared abstractions even after several repetitions; the modularity review fills that gap.conf: high
- explicitRunning the same LLM analysis multiple times surfaces additional issues that any single run misses.conf: high
- explicitWithout periodic AI modularity review (and without expert human review), an agent reliably compounds inadvertent technical debt at the modularity level.conf: high
- explicitcorroboratedFor modularity, computational sensors alone are insufficient; semantic interpretation by an LLM is required.conf: highrefinesHarness engineering for coding agent users Β· p5 β Identifies modularity as a domain where the cheap deterministic computational tier cannot carry the load and inferential LLM judgment is required.supports βArticle: Agentic Fitness Functions: Extending Evolutionary Architecture Beyond Deterministic Rules Β· p9 β Both conclude that computational/structural sensors alone are insufficient and that semantic interpretation by an LLM is required for architecture-level judgment β reached independently in different domains (cross-file modularity vs. boundary fidelity).
- implicitDesign intent can be encoded as enforceable invariants in a tool config (e.g. layer rules) instead of being kept only in human heads or prose docs.conf: highsupportsAlex Wang's Post Β· p6 β Encoding design intent as enforceable tool-config invariants is a concrete case of moving structure from the prompt into the environment to gain reliability.
- implicitLayered architecture (routes β services β clients + domain, no I/O in services, etc.) is the right modularity target for this kind of TypeScript web app.conf: high
- implicitMaintaining the rule-set and the custom coupling-analyser is itself a cheap, sustainable activity once AI helps author them.conf: medium
- implicitOff-the-shelf 'skills' from named experts (Khononov's Modularity Skills) raise the floor of LLM code review enough that organisations need not author their own modularity prompts.conf: medium
- implicitThe agent should be treated as a reader of error messages, so error messages should be designed for an LLM audience as well as a human one.conf: high
- implicitModularity problems are detectable but not autonomously fixable by the same agent that introduced them; a separate review run is needed.conf: medium
Arguments
Computational dependency rules are worth adopting in an AI-coding harness despite their narrow expressive range. strength: high
Explicit premises:
- Once authored, they actively enforce structure rather than describe it.
- AI eliminates the configuration-syntax cost that previously made them unattractive.
- Agents observably self-correct from dependency-cruiser feedback.
- Custom error messages can be used as self-correction guidance.
Implicit premises:
- Layered structure expressed via folders/imports is a good-enough proxy for the architectural intent the team actually cares about.
- The maintenance cost of the rule-set is lower than the maintenance cost of an equivalent markdown guide plus human enforcement.
Inferences:
- Teams who skip writing such rules are silently accepting that the agent will mis-place files within a few iterations.
- If the rules ARE the architecture documentation, then dependency-cruiser config becomes load-bearing for onboarding, and losing the maintainer of that config becomes a knowledge-loss event.
Raw coupling metrics are not, on their own, a useful sensor for an AI agent. strength: high
Explicit premises:
- Strong models reading the metric output misclassify intentional DI factories and shared schemas as smells.
- What counts as appropriate coupling is context-dependent.
- Without a suppression mechanism, false positives accumulate as noise.
Implicit premises:
- The model's misclassifications are not addressable purely by better prompting β the problem is information-theoretic (metrics omit intent).
Inferences:
- The right place for coupling metrics is upstream of human/agent attention allocation (impact-radius triage), not downstream as a quality verdict.
- Anyone selling a 'coupling dashboard for AI codebases' is selling a sensor that fires noise without architectural context.
An LLM modularity review that reads the actual code, driven by a curated skill pack, is the best available sensor for cross-module maintainability under AI-assisted development. strength: high
Explicit premises:
- It produced concrete, valid refactoring findings (duplicate routes, scattered parameters, misplaced auth code).
- It correctly contextualised the 'god module' false positives that the metric-only run produced.
- Repeated runs add coverage; single runs miss issues.
- Without it (and without expert human review), the agent compounded inadvertent debt.
Implicit premises:
- The skill pack (Khononov's) encodes enough good architectural taste to be trusted as a sensor; its quality is largely outside the team's control.
- An LLM reading the full codebase periodically is affordable in tokens and wall-clock β i.e. inference cost continues to fall or the codebase stays small enough.
Inferences:
- Modularity quality in AI-built systems becomes a function of the modularity skills you import, not of the implementing model.
- Organisations now depend on third-party skill maintainers in a way structurally analogous to dependency on linter rule-set maintainers β but with much less mature ecosystem hygiene.
Computational and inferential sensors are not substitutes; they belong in different parts of the harness.
Explicit premises:
- Deterministic rules excel at enforcement of known invariants.
- Inferential reviews excel at judgement calls about what is appropriate in context.
- Grounding the inferential review in the deterministic data made little difference in this case.
Implicit premises:
- The two sensor classes fail in non-overlapping ways, so coverage is additive.
- The cost of running both is justified relative to letting the agent compound debt.
Inferences:
- Harness design becomes a portfolio problem: which deterministic rules to enforce, which inferential skills to run, and at which cadence.
Narratives
- The `clients-no-services` rule: she shows the dependency-cruiser JSON for forbidding API clients from importing from the services orchestration layer, plus the expanded error message that recaps the entire layering convention as self-correction guidance for the agent.
β Concretely demonstrates the 'custom error messages as agent guidance' pattern; supports the proposition that deterministic rules can substitute for a markdown guide. - The agent declared her dependency-injection factory a 'god module' and her shared frontend/backend zod schema a 'god module', based purely on coupling metrics β both being deliberate, well-known patterns.
β Carries the argument that raw coupling metrics strip away intent and therefore mislead even a strong LLM; without telling the abstract claim, the anecdote makes it. - Changing the way a user specifies a date range forced edits in 40+ files; the modularity review then surfaced 'Request parameters repeated at every level' as a finding, confirming her intuition that the design was leaking.
β Validates Sensor 3 by closing the loop between a felt pain (40-file change) and a structural finding (no parameter object). - Three nearly-identical route files, each reimplemented when a new backend endpoint was added, because the agent will copy-paste rather than refactor on the third or fourth repetition.
β Supports the proposition that AI agents do not autonomously generalise across repetitions and that a separate sweep is needed. - Auth logic accidentally lurking inside the wiring/DI factory.
β Illustrates the broader claim that responsibilities drift to whatever module the agent happened to be editing, and that only a semantic reviewer notices. - Running the modularity review a second time, with no memory of the first, surfaced a new issue.
β Supports the proposition that LLM reviews are usefully stochastic and should be run multiply.
Questions addressed
- β
Can deterministic static analysis enforce architectural boundaries in an AI-coded codebase?
Yes, but only for what imports / file paths can express; pairs well with custom error messages that double as agent guidance. - β
Are raw coupling metrics, fed to an LLM, a useful modularity sensor?
No β even Claude Opus 4.7 misclassifies intentional patterns; the data lacks the context the LLM needs. - β
Is a prompt-driven LLM modularity review (that reads the code) a useful sensor?
Yes β it found valid, concrete refactorings; run it more than once. - β Where in the change lifecycle should the AI modularity review live?
She wants it nearer the commit, scoped to changed files, but hasn't built that yet. - β Who maintains the dependency rules and the custom coupling-analyser once the original author moves on?
Not addressed. - β What happens to a team's design intent if it lives only in dependency-cruiser config and an imported Modularity Skill pack?
Not addressed. - β How does the architecture get debated and evolved when it's expressed as enforcement rules rather than as prose?
Not addressed. - β Does this approach generalise beyond a single TypeScript/Next.js app rebuilt by one expert?
She notes risk profiles vary by software type but doesn't test generalisation.
Gaps
- incompleteNo treatment of the social-and-organisational fate of the artefacts themselves. Dependency-cruiser configs, custom coupling-analyser CLIs, and imported Modularity Skill packs are all new load-bearing artefacts. Who owns them? Who updates them when the architecture should change? In the absence of an owner, the rules outlive the intent behind them and become either silently violated or silently obsolete β the classic linter-suppression-debt pathology, scaled to architecture.
Read next: Cutler on institutionalised overload and waste; Fearless Change (Manns & Rising) on what it takes for organisational invariants to survive; Tornhill's Software Design X-Rays on attaching social/ownership data to code-quality signals; Vlad Khononov's modularity work directly (since his Skills are now part of the harness). - incompleteThe article treats the dependency-cruiser rule set as a substitute for a markdown structure guide, but it skips the question of whether enforcement and explanation are interchangeable. A rule that says 'clients cannot import services' enforces a constraint but does not teach why the layering exists β and the moment the constraint is wrong, the team has no shared prose to reason with. This silently relocates design intent into tooling that few people maintain, and few people can read.
Read next: Ousterhout 'A Philosophy of Software Design' on the role of design documents; Parnas on module specifications; Hickey 'Simple Made Easy' for the distinction between rules-as-policy and rules-as-understanding. - incompleteHeavy reliance on Khononov's externally maintained Modularity Skills pack as the thing that makes Sensor 3 work. The article does not examine: skill-pack versioning, drift, security/supply-chain assumptions, or what happens when the skill author changes their mind. The harness now has a third-party dependency at the level of taste, not just at the level of code.
Read next: Khononov's Learning Domain-Driven Design and his coupling talks; literature on prompt drift; the emerging 'skills-as-dependency' discussion (Osmani's agent-skills writing). - incompleteThe coupling-analyser is described as a vibe-coded custom CLI. The article acknowledges it would benefit from suppression of legitimate high-coupling hubs but does not engage with the more interesting question: if your coupling tool requires hand-curated exceptions for every architectural pattern, you are effectively encoding architectural intent in two places (the rules AND the exception list). At that point, why not skip the metric layer and go directly to the inferential review?
Read next: Tornhill, Software Design X-Rays; the dependency-cruiser community's own discussion of when DSM-style tools earn their keep. - incompleteThe article observes that the AI modularity review found duplicate routes, scattered parameters, and misplaced auth β i.e. exactly the things a senior reviewer would find in a half-hour read of the code. There is no contrastive baseline against human-only review, against pair-review with the original implementing agent, or against a much cheaper rubric like 'review every file changed >X times in the last 30 days'. Without such a baseline, the proposition 'the review is the best available sensor' is unfalsifiable on the evidence given.
Read next: DORA reports' methodology on baselines; Beck on test-commit-revert and 'starving genies' as alternative scaffolds for keeping AI-edited code honest. - incompleteNo engagement with the relationship between this approach and existing fitness-function / architecture-as-code tooling (ArchUnit, NetArchTest, ts-arch, Modulith, even Structure101). dependency-cruiser is one point in a much larger design space; treating it as 'the' dependency-rules sensor leaves the reader without a sense of where the boundary lies between custom configuration and adopting an established framework.
Read next: Ford/Parsons/Kua 'Building Evolutionary Architectures' on fitness functions (which she links to in the framing); ArchUnit; ts-arch. - incompleteThe framing assumes the agent is always the implementing actor and the human (plus other agents) are the reviewers. It does not consider the inverse case β where humans implement and the AI modularity review is the rubric against which their code is judged β even though the same tooling would work. This matters because it shapes whether the harness is 'AI guardrails' or 'organisational architecture discipline that happens to use AI'.
Read next: Cutler on operating-system design; Beck on team practices. - illogicalShe claims dependency-cruiser rules are 'a useful replacement for describing code structure in a markdown guide', but a markdown guide and an enforcement rule do different epistemic work: one teaches, one constrains. Treating them as substitutes is the same move that has historically led teams to delete their architecture docs in favour of 'the tests are the spec', then discover that nobody can reason about the system any more.
Read next: Ousterhout on documentation; the long literature on tacit-vs-explicit knowledge in software teams.closed byTony Seale's Post β That gap warns that migrating meaning into machine-only enforcement tooling (dependency-cruiser rules replacing a markdown structure guide) destroys the human-readable prose that teaches β the 'tests are the spec' failure. Vault-LD's core move directly answers it: keep prose AND typed structure/semantics in one file so the two epistemic jobs β teaching (markdown) and constraining/validating (YAML-LD) β coexist per-file rather than one substituting for the other.
Closes gaps elsewhere
- Architecture as Code to Teach Humans and Agents About Architecture Β· g2 β Supplies the missing concrete tooling: dependency-cruiser rule sets with LLM-facing error messages, a custom coupling-analysis CLI, and LLM modularity-review skills as working architecture-as-code implementations.
- Architecture as Code to Teach Humans and Agents About Architecture Β· g3 β Examines which constraint types actually guide agents: import/folder rules work (with a meta-rule preventing folder escape), while modularity constraints defeat deterministic sensors and require semantic LLM review.
- Fragments: May 5 Β· g3 β A subsequent martinfowler.com piece takes the position the Fragments left open: internal quality still matters because agents reliably compound modularity debt without enforced rules and periodic AI review.
Related documents
- Harness engineering for coding agent users
- Alex Wang's Post
- Addy Osmani's Post
- Have your agent record video demos of its work with shot-scraper video
- Agents don't know what good looks like. And that's exactly the problem.
- Architecture as Code to Teach Humans and Agents About Architecture
- Maintainability sensors for coding agents
- Presentation: Clean Architecture for Serverless: Business Logic You Can Take Anywhere
- Fragments: May 5
- The Hard-Stop Rule: From 3 HCM Monoliths to 120 Domain Microservices