The Other Intent
updated
“There should be one — and preferably only one — obvious way to do it.” — Tim Peters, The Zen of Python (PEP 20)
Every change I ship carries two intents. One of them has a home.
The business intent, what we’re accomplishing, goes in the PR description. Solved problem; we’ve had a text box for it since forever. The engineering intent — how it’s built — I said out loud to an agent at eleven at night. It was load-bearing, and it now exists in exactly one place: the shape of the code that came out. Nowhere in the repo is there a sentence a future diff could be checked against.
The obvious fix is to write it down, and I’ve watched that fail in my own codebase. A comment that said presets must be resolved before checking permissions survived a refactor that reversed the order. It didn’t complain. It sat there describing the old world in the present tense, and it looked like a live constraint. That’s the whole problem with recording engineering intent as prose. Prose doesn’t fire.
The fashionable fix is to move review left: front-load the argument before the code exists. That’s right. It’s aimed at the wrong intent.
BLUF: Bottom line up front
- There are two intents in a change, and only one has an artifact. Business intent goes in the PR description. Engineering intent gets stated in a conversation and left in the code.
- You can’t split them by role. Engineers straddle the line constantly — I make business calls from what a decision costs technically in a year, or from just imagining being the user. Any process that assigns “the what” to one person and “the how” to another is describing a team that doesn’t exist.
- Taste comes out of review entirely. A nit means no standard existed. Leaving it as a comment is legislating in a venue with one participant and no mechanism for precedent. If there’s more than one way to do a thing, there are too many ways.
- Encoding engineering intent as a rule is the mechanism — a record isn’t. The best version of move review left stops at preserving the decisions from the agent session. A preserved session log is prose nobody reads next quarter. A rule fires on the next diff. That’s the whole post.
- The part that resists the rule form is the architecture part, and the asymmetry is measured. In twenty agent-built projects, code volume tracked architectural decay at ρ = 0.94 against 0.53 for code-level decay — same detector, same projects — and four escalating levels of prompt detail moved neither (no significant effect, p > 0.8).
- Review keeps exactly one job: does the structure that got built match the intent that was stated. That’s a comparison, not a read. Fluency makes it fast, and it’s the one thing you can’t route anywhere else.
- Rules rot, and that’s the design. A rule is dated and disposable; the judgment behind it isn’t. Rules are a function of your intent and this year’s stack, so they have to expire. And you can’t fully generate them from encoded judgment either — the derivation is lossy exactly where the hard cases live, which is why you still work the rules by hand.
Two intents, one artifact
Business intent is the feature. Engineering intent is how it’s built — this goes behind the existing boundary rather than beside it, this stays a lookup because the switch will grow a fourth case next quarter, this doesn’t get its own abstraction until there’s a second caller.
Different claims, different lifetimes. The business intent is spent when the feature ships; you can read it once, at review, and never again. The engineering intent is a standing constraint. It applies to the diff in front of you and to every diff after it that touches the same seam. It’s the one that needed writing down. It’s the one that didn’t.
And you cannot fix this by dividing labour. Engineers straddle the line all day. I make business calls out of technical experience — this feature as specified will need a migration in six months, so let’s cut it differently. I make them by imagining myself as the user and noticing what I’d need. Product people make engineering calls when they insist on a deadline that picks the architecture. There is no clean seam, so a process that routes “what” to product and “how” to engineering routes both to nobody.
None of that split is new, and I’d rather stand on the prior art than claim it. Requirements engineering already has a name for the durable half: architecturally significant requirements, characterised by Chen, Babar and Nuseibeh out of a grounded-theory study of practitioners — the requirements that bind how a thing gets built rather than describe what it does. Same line, drawn from the requirements side instead of the review side. The decay has a name too. Perry and Wolf separated architectural erosion, which comes from violating the stated principles, from drift, which comes from insensitivity to them — nobody breaks the rule, people just stop being able to see it. Drift is what engineering intent does when nothing keeps it firing. And Lehman’s Continuing Change is why it never gets to stop: a system in real use has to be adapted continually or it becomes progressively less satisfactory, so the constraint has to outlive every diff that already satisfied it.
What the field built for this is a record. Architecture decision records — Nygard, 2011 — put the decision, its context and its consequences in a file next to the code. Right instinct, wrong end of the pipe: an ADR is read by whoever thinks to look, and the diff that violates it eighteen months from now is written by someone who doesn’t know the file exists. The literature names the durable half and writes it down. Attaching it to the seam so it fires on the next diff is the part still missing.
Taste is an input, not an output
Here’s where I part company with the sharpest statement of the other side. Ankit Jain and David Poll’s Code review is a taste problem — a sponsored, contributed piece, so weigh its numbers accordingly — argues that review is a taste problem at bottom: the judgment is the irreducible part, so review’s job is to be the place where taste gets exercised.
I want taste out of review completely.
Not because taste doesn’t matter — because a nit is evidence of an earlier failure. When someone leaves I’d have done this differently on a diff, that’s not judgment being exercised. It’s a standard that didn’t exist getting invented on the spot by one person, in a thread. The reviewer is legislating in a venue with one participant and no mechanism for precedent. The author complies or argues, and either way nothing about the next diff changed. Do that a hundred times and you have a hundred private standards and one codebase that reads like a hundred people wrote it.
The whole codebase should look like it was written by one person. For an AI writing most of it, there should be no such thing as subjective — because the moment you tell it “either is fine,” you’ve told it to pick, and it will pick differently from diff to diff. If there’s more than one way to do a thing, there are too many ways to do a thing.
This isn’t a new idea, it’s just usually applied one level down. Go shipped gofmt and ended every brace argument in the language by deleting the degrees of freedom. The move is the same at the level of structure: don’t adjudicate the disagreement per-diff, delete it.
And notice the trap in their remedy. The argument goes: mine your last thousand review comments, sort them into deterministic / execution-testable / genuine judgment, and codify the first two buckets. That’s right, and it’s a refutation of the taste framing, not a version of it. Their split lands “around 45/30/25” — hedged in the original, and carrying no corpus, method or n, so take it directionally. If most of what your reviewers say is codifiable, then most of it was never taste. It was an unwritten standard, doing damage by staying unwritten.
Two problems with the number, though. Mined comments sample what one rushed person happened to notice, not what review could have caught. And the leftover bucket isn’t a backlog you burn down. A rule generalises across diffs; an architecture objection is indexed to the system’s current shape. Change the shape and the objections regenerate. The judgment share is a rate, not a remainder.
Where each thing belongs
| What | Venue | Who | When |
|---|---|---|---|
| business intent — what we’re accomplishing | PR description | author | with the work |
| engineering intent — how it’s built | stated by the engineer, encoded as a rule | author + agent | before the work, kept current |
| rule-shaped correctness | the rules pass | agent | on the diff |
| questions, second opinions | standup, Slack | anyone | before the code exists |
| does the built structure match the stated intent | the glance | senior | at review |
Row four is the one people put in the review tool and shouldn’t. Review is where teams argue, the story goes — a shared space to decide what belongs in the product. But look at review’s actual quorum: one approver, usually someone who wasn’t in the design conversation, reading the outcome after the work is finished. That’s not a forum, it’s a gate with a comment box bolted on. Merge a forum into a gate and the gate’s properties win — asynchronous, one-vote, terminal, and biased toward whatever’s already built. Conversation belongs in standup or Slack, before the code exists, where a junior can ask a senior and a senior can get a second opinion without anyone’s work being on the line.
Row two is where I disagree with the people I mostly agree with. The strongest version of move review left says: capture the intent and the decision-making from the agent session where it happened, and preserve it before you submit. Same diagnosis I have. The delta is one word — mechanism, not record. A preserved session log has the same fate as my presets comment: decoupled from the code, unread, eventually wrong, still looking authoritative. Encode the same decision as a rule and it fires on the next diff, including the one written six months later by someone who never saw the conversation. That’s what the ladder from name to shape to type to test is really ranking: how hard it is for the code to drift away from the thing you wrote. A rule belongs on that ladder, next to the test.
Concretely. The sentence I said out loud was this stays a lookup, because the switch will grow a fourth case next quarter. As a comment, that describes a table which may already be a switch again. As a rule it’s a condition with a carve-out:
when: a dispatch over a closed set of string cases is added or edited
confirm: the dispatch is a lookup table, not a switch
refute: the branch bodies differ in control flow — an early return,
a throw, an await — which a table can't hold
else: flag it, and cite the added case
Four lines, and the third one is the part I never said. I said “keep it a lookup.” I didn’t say what to do when one branch has to throw, and I only found that out when I tried to write the condition down. That’s the difference between recording a decision and encoding it: the encoding interrogates you.
What actually resists the rule form
“Encode your intent as a rule” is doing a lot of work in that table, so here is the part of it I can’t cash.
Agents are getting better at code much faster than they’re getting better at architecture. The mechanism matters more than the fact. An agent works the way a junior works: it reaches for what’s visible and mashes it toward the target. Architecture is writing for what comes next, and what comes next is mostly not visible — it lives in institutional knowledge, in the change nobody has proposed yet, in the reason this module doesn’t import that one.
The junior-developer framing isn’t mine. It’s the stated conclusion of a study that measured smells in agent-built systems:
current agents operate as proficient “junior developers”: they follow instructions with syntactic precision but lack the “senior architect” foresight needed to manage system-wide dependencies and maintain a coherent architectural vision.
— Zhu, Tsantalis and Rigby, AI-Generated Smells (2026)
Their numbers are the sharpest version of the asymmetry I’ve found, because both halves come out of one pipeline. Across twenty agent-generated projects, code volume correlated with architectural smells at ρ = 0.94 — near-perfect — against 0.53 for code-level smells. File count predicted architectural decay at 0.72 and predicted code-level smells not at all (0.33, not significant). Same detector, same projects, both numbers: the higher up the structure you look, the faster quality falls away as the system grows. They call it a Volume-Quality Inverse Law, and they name what it produces a modular mirage — the agent splits the files and never achieves the cohesion, so related behaviour ends up scattered behind a tidy directory tree.
Then the finding that should bother anyone selling a better spec: prompt specificity had no statistically significant effect on any smell category (p > 0.8). Four escalating levels of requirement detail, no measurable architectural improvement. Read that as the ceiling on what a frontloaded document buys you — my reading of their experiment, not their claim — and it’s why the answer isn’t a longer plan up front.
The repair side agrees, and it indicts the instruments too. SmellBench ran eleven agent configurations from four model families at hard-severity architectural smells in a real Python project: the best agent resolved 47.7%, and the most aggressive one introduced 140 new smells while repairing. Its detector was wrong 63.1% of the time on expert review, and the agents matched the experts on which flags were wrong at κ = 0.94. Spotting a misfired architecture rule is not the same measurement as satisfying one — but an agent that reads the instrument better than it obeys it is telling you something about the instrument.
And the asymmetry isn’t an agent artifact. Long before an LLM wrote anything, Arcelli Fontana and colleagues correlated nineteen code smells against four architectural smells across 111 Java projects and came up empty: fourteen of fifty-four combinations cleared a 0.5 rank correlation, in nine projects, and never the same combination more than twice. Their conclusion is that architectural smells cannot be derived from code smells at all — on a corpus of monolithic Java from 2013, which is the standing caveat on this whole literature. Code-level signal is a hint about architecture. It is never a check.
Which puts a hard edge on my own proposal, and you can see it in the tools that already do this well. ArchUnit, dependency-cruiser and the rest do genuinely mechanize architecture rules — but only the structural subset: dependency direction, cycles, layering, naming. The architectural review skills I’ve looked at do the same thing: they check the dependencies and whether they flow the right way.
That’s a real check, and it isn’t the same as the architecture being right. The modular mirage is what it misses. The files are split, the arrows all point downhill, the check passes, and the behaviour that belongs together is smeared across four modules. The part of engineering intent you can encode is the part shaped like a dependency graph, and cohesion doesn’t reduce to one — the metric families that try, LCOM and co-change coupling, are proxies for it, not it. The industry’s answer for everything else was to invent a different instrument and call it a fitness function, which is a concession dressed as a technique.
Even inside the part that does encode, determinism doesn’t come free. My own rules pass was unstable on a real diff: two runs over the same change shared three findings out of ten. The fix wasn’t better prose. It was making every rule carry a closed decision procedure with a pre-committed default when the evidence is missing — policy over instances. That’s shipped, and I haven’t re-run the same two-run comparison since, so treat it as designed-for rather than re-measured.
The residue is unwritten, not unjudgeable
There’s a leftover. It’s the architecture-shaped part, and no rule reaches all of it. That’s not an argument for putting taste back in the review thread.
The job is: does the structure that got built match the intent that was stated. Not do I like this code — that question has no answer and no venue. That’s the line I’m drawing. Judgment against a stated claim is a comparison, and a comparison has a referent; taste without one is a preference with a CI hook. The remaining job still takes an architect. It just isn’t taste, because there’s something to be wrong about. The senior isn’t re-deriving the design from the diff; they’re comparing a claim to an artifact, which is why fluency makes it a glance rather than a read.
That comparison is also older and more tractable than it looks. In 1995, Murphy, Notkin and Sullivan published software reflexion models: the engineer states a high-level model and how it maps to the source, and a tool computes where the source agrees with the stated model and where it differs. They ran it on design conformance against a million-line system. Thirty-one years ago, someone built the comparison I want. The agent-emitted version is the new part — intent as stated versus structure as built, so the senior reviews a claim instead of reconstructing one.
The glance stays human for now. But it’s a comparison, and comparisons get mechanized.
Where this breaks
Encoding is a design step. The carve-out in that lookup rule is the pattern, not the exception — most of what I ended up writing had no counterpart in the sentence I started from. Budget for that. “The agent writes it to the rules” is a gauntlet, not a transcription.
Stated intent will be wrong, and you want it to change. The intent you write before the work is a hypothesis. The fix isn’t to get it right up front, it’s to keep the RFC current and record what you took, what you left, and why — so the next person can pick it up and so a cross-model check has something to disagree with. That isn’t a retreat from mechanism, not record: the record holds the judgment, which is the durable half, and the rule enforces the rule-shaped subset of it.
The glance is only as good as the statement. No stated intent, no comparison, and the senior is back to reconstructing a design from a diff.
Rule-authoring is a venue with one participant too. I convicted the nit for exactly that, and it applies here with more force: one author, no diff in front of them, binding on every future change, enforced automatically, and unlike a nit there’s nobody on the other side to say not here, and here’s why. Two things keep it honest and neither is optional. The rule ships with its exception path, written at the same time as the condition — that’s what the refute line is for. And the discovery channel has to move rather than close: the thing you used to type as I’d have done this differently still gets noticed, it just gets written as the standard instead of left in the thread. If nobody is writing the standard, you haven’t removed the nit. You’ve suppressed it, and you’ve lost the only sampling mechanism that told you which standard was missing.
Rules rot. That’s the design, not the bug. A rule indexed to the current shape of the system keeps firing confidently about a world that moved — so rules have to be dated, and they have to expire. That’s a mechanism worth its own post, so I’ll leave it there. What matters here is why it doesn’t sink the model: the rule isn’t the durable thing. Intent is. The rules are a function of intent and whatever your stack is this year, and the stack moves much faster than the judgment does. You’re supposed to throw rules away.
Which raises the obvious move: encode the judgment, declare the stack, generate the rule set. It would be great if that worked, and I’d use it tomorrow. It won’t work all the way, because the derivation is lossy — and the gaps are exactly the shape-indexed, exception-riddled cases that made you want a rule in the first place. That’s not a reason to skip the encoding. It’s the reason you still work directly on the rules, by hand: the judgment is what you preserve, the rule is what you bin.
How sure I am
- My framing of a split the literature already draws: the two intents are not my discovery. Architecturally significant requirements name the durable half from the requirements side; Perry and Wolf’s erosion-versus-drift names what happens to it when nothing enforces it; Lehman’s Continuing Change says why it never expires. What’s mine is the mechanism claim — that the durable half has to be attached to the seam and fire on later diffs, and that the ADR, which is the field’s answer, is the record form of the same instinct and loses for exactly that reason. Also mine: the venue routing and taste-out-of-review-entirely. One bound on the prior art: I could not read Perry and Wolf’s 1992 paper directly — the available PDF is a scan with no text layer — so I’m taking the erosion/drift distinction from the survey that reports it rather than quoting the original.
- My model, argued from practice: the PR-description gap and the straddling are my own working experience, not a measured claim about how teams review in general. PEP 20 and gofmt are prior art for deleting degrees of freedom rather than adjudicating them — they’re precedent for the move, not evidence for my version of it.
- Lived and real: the decoupled comment that survived a reversing refactor (my own codebase, recounted in my own book). The rules-pass instability — two runs over one real diff sharing three findings of ten — is a real measurement, and the fix, a closed decision procedure with a pre-committed default under missing evidence, is shipped. I have not re-run that comparison since, so the fix is designed-for and not yet re-measured. The lookup rule above is written in the real form but is an illustration, not a rule out of my catalog.
- Backed, with bounds stated: the architecture asymmetry is measured, not just premised. Zhu, Tsantalis and Rigby report the gradient inside a single pipeline — code volume correlates with architectural smells at ρ = 0.94 against 0.53 for code-level ones, file count at 0.72 against 0.33 (not significant) — and prompt specificity showed no significant effect on any smell category (all p > 0.8). Bounds: twenty projects generated by one multi-agent framework, one detector, and generated code rather than a maintained codebase, so it measures what agents build from scratch and not what they do to your repo. SmellBench covers the repair side on a real project and its numbers are verified: 47.7% best resolution, 63.1% detector false-positive rate, 140 new smells from the most aggressive agent, κ = 0.94 agreement with experts on which flags were wrong. I don’t repeat its framing that architectural repair “remains unexplored,” because it isn’t — LLM refactoring of architectural smells was already being studied at an ICSA 2025 workshop, and SmellBench itself drops cyclic and hub-like dependencies for want of instances. Arcelli Fontana and colleagues found no derivable relationship between code smells and architectural smells across 111 Java projects, which is the sharpest number for harder to test for and the reason I can say the asymmetry predates agents. One real caveat, and it applies to that whole literature: the Qualitas Corpus dates to 2013 and is monolithic Java, which the authors say doesn’t reflect microservice or cloud-native architecture. What survives all of it is the modest version of the claim — the code-level part is improving faster than the architecture part.
- My inference, not the papers’: that an agent which reads the instrument better than it obeys it is telling you something about the instrument (κ and a resolution rate are different measurements and I’m not ranking them). That the null result on prompt specificity is a ceiling on frontloaded documents. That the modular mirage is what a dependency check misses — nobody ran ArchUnit on those twenty projects, so that weld is mine.
- Argued, not measured: that the judgment share is a rate rather than a finite backlog — it follows from the rule form, and I have no measurement of the regeneration rate. That architecture is writing for what isn’t visible yet: the junior-developer framing is Zhu et al.'s, the mashing-toward-the-target mechanism is mine. That cohesion doesn’t reduce to a dependency graph — I’m claiming LCOM and co-change coupling are proxies, not proving it. That rules rot and have to expire, and that generating them from encoded judgment is lossy where the hard cases live: both from shipped rule practice, neither measured.
- Unsystematic: “the architectural review skills I’ve looked at” is a handful I read, not a survey.
- Not mine and not claimed: I haven’t built the reflexion-model-style intent-versus-structure diff; I’m pointing at 1995 prior art for a thing I want. And the critique of the 45/30/25 split is a critique of its sampling, not a counter-measurement — I don’t have a better number, only a reason to distrust that one.
Sources
- Tim Peters, The Zen of Python (PEP 20, 2004) — “one — and preferably only one — obvious way.” The canonical statement of deleting degrees of freedom rather than adjudicating them.
gofmtand the Go project’s formatting decision — prior art for ending a taste argument by removing the choice. Cited as a well-known engineering precedent, not audited.- Ankit Jain and David Poll, Code review is a taste problem (The New Stack, August 13 2026) — a sponsored, contributed piece (the site’s own taxonomy tags it
sponsor-aviator, sponsored-post-contributed). The position this post argues with, and the best version of “move review left.” Its “AI slop register” — mine the last thousand review comments, split them deterministic / execution-testable / genuine judgment, codify the first two — is the mechanism I agree with; its split (“around 45/30/25”) is hedged in the original (“you might end with,” “may be codifiable”) and carries no corpus, method, or n. - Ion George Dinu, Marian Cristian Mihăescu, Traian Rebedea, SmellBench: Evaluating LLM Agents on Architectural Code Smell Repair (arXiv:2605.07001, May 2026) — 11 agent configurations, four model families, 65 hard-severity architectural smells in a real Python project. 47.7% best resolution; 63.1% of detected smells false-positive on expert review; the most aggressive agent introduced 140 new smells; agents agreed with experts on which flags were wrong at κ = 0.94. The paper’s own framing of the gap: localized code transformation versus the architectural understanding needed for cross-module refactoring.
- Yue Cai Zhu, Nikolaos Tsantalis, Peter C. Rigby, AI-Generated Smells: An Analysis of Code and Architecture in LLM- and Agent-Driven Development (arXiv:2605.02741, May 2026) — the quote used here, and the measured gradient behind it: across twenty agent-generated projects, code volume → architectural smells ρ = 0.94 (p < 0.001) against 0.53 for code-level smells; file count → 0.72 (p < 0.001) against 0.33 (not significant); prompt specificity no significant effect on any smell category (all p > 0.8). Their names for the failure modes are theirs: a Volume-Quality Inverse Law, and the modular mirage — files split, semantic cohesion absent. Bounds: one multi-agent framework, one detector, generated rather than maintained code, which the authors state as a threat to validity.
- Francesca Arcelli Fontana, Valentina Lenarduzzi, Riccardo Roveda, Davide Taibi, Are architectural smells independent from code smells? An empirical study (arXiv:1904.11755; Journal of Systems and Software 2019, doi:10.1016/j.jss.2019.04.066) — 19 code smells against four architectural smells (unstable dependency, hub-like dependency, cyclic dependency, and components carrying more than one) across 111 Java projects from the Qualitas Corpus, code smells detected in 103 of them, Kendall rank correlation. 14 of 54 combinations cleared tau 0.5, in nine projects, and never the same combination in more than two; the other 40 came in under 0.5 in at least 32 projects each. All 23 projects above the threshold were inspected by hand and “did not yield any useful feedback.” Their conclusion: architectural smells cannot be derived from code smells and “deserve special attention.” Cited because it is pre-LLM and human-written, which makes the asymmetry a property of the two levels rather than of agents. Same 2013 monolithic-Java corpus caveat, carried in text.
- Pandini and Martini, An exploratory study on architectural smell refactoring using Large Languages Models (ICSA 2025 workshop; Zenodo 14745953) — LLMs suggesting refactorings for cyclic-dependency smells. Cited only to establish that prior work exists, which is why this post doesn’t repeat SmellBench’s “remains unexplored.”
- An Empirical Study on the Code Refactoring Capability of Large Language Models (ACM TOSEM, doi:10.1145/3801158, March 2026) — unit-test pass@5 above 90% on multi-file refactorings, best median smell reduction 15.1%, developers outperforming LLMs on context-sensitive refactorings, and the conclusion that LLMs “benefit from integration with human expertise for architectural or semantically complex changes.” One tension I’m not reconciling: this study finds tailored prompts help on repair, where Zhu et al. found prompt detail didn’t help on generation. Different tasks, different measurements.
- ArchUnit, ArchUnitTS, dependency-cruiser — architecture rules that genuinely mechanize, over the structural subset (dependency direction, cycles, layering, naming), and run as a CI test rather than at write time. Cited as the honest bound on this post’s own mechanism.
- Neal Ford, Rebecca Parsons, Patrick Kua, Building Evolutionary Architectures (O’Reilly, 2017) — architectural fitness functions: “fitness functions check that developers preserve important architectural characteristics.” Cited as the industry conceding that ordinary assertions don’t reach architecture.
- Gail C. Murphy, David Notkin, Kevin Sullivan, Software Reflexion Models: Bridging the Gap between Source and High-Level Models (FSE 1995) — the engineer states a high-level model and its mapping to source; a tool computes where source and model agree and differ. Applied to design conformance on a million-line system. Prior art for mechanizing the glance; the tool was theirs, the agent-emitted version is the part that doesn’t exist yet.
- Lianping Chen, Muhammad Ali Babar, Bashar Nuseibeh, Characterizing Architecturally Significant Requirements (IEEE Software, 2012; ieeexplore.ieee.org/document/6365165) — “a framework for characterizing architecturally significant requirements (ASRs) on the basis of an empirical study using grounded theory.” The existing name for the half of intent that keeps constraining after the feature ships. Cited as the prior art the two-intents split rests on; the paper characterizes those requirements, it doesn’t propose firing them at the diffs that come later.
- Michael Nygard, Documenting Architecture Decisions (2011) — the origin of the architecture decision record: decision, context, consequences, in a file beside the code. The record-shaped answer this post argues is the right instinct at the wrong end of the pipe. Cited for the form, which is now standard practice, not for a claim about how well it works in any particular team.
- Dewayne E. Perry and Alexander L. Wolf, Foundations for the Study of Software Architecture (ACM SIGSOFT Software Engineering Notes 17(4), October 1992, p. 40; doi:10.1145/141874.141884) — the erosion-versus-drift distinction. Read second-hand and deliberately not quoted: the available PDF is a scan with no text layer, so the definitions used here come from de Silva and Balasubramaniam, Controlling software architecture erosion: A survey (Journal of Systems and Software, 2012, doi:10.1016/j.jss.2011.07.036), which reports erosion as resulting from violating architectural principles and drift from insensitivity to them.
- Meir M. Lehman, Programs, Life Cycles, and Laws of Software Evolution (1980) — the laws of software evolution, including Continuing Change (1974): a system in real use must be continually adapted or it becomes progressively less satisfactory. Cited for why a construction constraint has no expiry date, not for the rest of the laws.
- How to Think About Code, “Say What You Mean” and “Tests as Promises” — the name → shape → type → test ladder read as a ranking by checkability, and the decoupled-comment failure recounted here (the author’s own book).
- A Description Can’t Replace the Code — why a recorded intent artifact is itself a description and inherits the compression trap. This post takes that as settled rather than re-arguing it.
- Rules Are the Alpha — where the rules come from, and why an encoded opinion is the defensible part.
Related: A Description Can’t Replace the Code (a recorded intent is itself a description, and inherits the compression trap); Teaching the Reviewer (explaining a rule is how you extract the part you can freeze); Rules Are the Alpha (where the rules come from, and why the encoded opinion is the defensible part); Nobody Broke It (what a rule that outlived its reason does when it keeps firing anyway).