6 ms·
Technical, cognitive, and intent debt
- kvisner 6mo agoI see what Martin is saying here, but you could make that argument for moving up the abstraction layers at any point. Assembly to Python creates a lot of Intent & Cognitive debt by his definition, because you didn't think through how to manipulate the bits on the hardware, you just allowed the interpereter to do it. My counter is that technical intent, in the way he is describing it, only exists because we needed to translate human intent into machine language. You can still think deeply about problems without needed to formulate them as domain driven abstractions in code. You could mind map it, or journal about it, or put post-it notes all over the wall. Creating object oriented abstractions isn't magic.
- didericis 6mo ago> you didn't think through how to manipulate the bits on the hardware, you just allowed the interpreter to do it If you are thinking through deterministic code, you are thinking through the manipulation of bits in hardware. You are just doing it in a language which is easier for humans to understand. There is a direct mapping of intent.
- raincole 6mo agoMost programmers who write reasonably deterministic code don't even know how many bits it allocates.
- lmm 6mo ago> If you are thinking through deterministic code, you are thinking through the manipulation of bits in hardware. No I'm not. If I want the machine to evaluate 2+2, I don't know or care what bits in hardware it uses to do that (as long as it doesn't run out of memory), I just want the result to come back as 4.
- didericis 6mo agoWhen you press the 2 button, the plus button, the 2 button and the equals button, you are translating your question into bits and operations which are logically guaranteed to yield bits that represent your answer. When you think through what will happen as a result of deterministic code, you are also thinking through what the bits will do, albeit at a higher level of abstraction. When you ask an LLM to do something, you have no guarantee that the intent you provide is accurately translated, and you have no guarantee you’ll get the result you want. If you want your answer to 2+2 to always be 4, you shouldn’t use a non deterministic LLM. To get that guarantee, the bit manipulation a machine does needs to be logically equivalent to the way you evaluate the question. That doesn’t mean you can’t minimize intent distortion or cognitive debt while using LLMs, or that you can’t think through the logic of whatever problem you’re dealing with in the same structured way a formal language forces you to while using them. But one of my pet peeves is comparing LLMs to compilers. The nondeterminism of LLMs and lack of logical rigidity makes them fundamentally different.
- lmm 6mo ago> When you press the 2 button, the plus button, the 2 button and the equals button, you are translating your question into bits I am not. 2 is 2, + is +, I don't care whether the machine chooses to represent them as ASCII or EBCDIC or semaphore flags. > If you want your answer to 2+2 to always be 4, you shouldn’t use a non deterministic LLM. Right. Determinism and locality are important. But bit-banging isn't (as long as the higher level abstractions are good).
- layer8 6mo agoTranslating your intent into a formal language is a tool of thought in itself. It’s by that process that you uncover the ambiguities, the aspects and details you didn’t consider, maybe even that the approach as a whole has to be reconsidered. While writing in natural language can also be a tool of thought, there is an essential element in aligning one’s thought process with a formal language that doesn’t allow for any vagueness or ambiguity. It’s similar to how doing math in natural language without math notation is cumbersome and error-prone.
- ah1508 6mo agoAgree: house architects have their language (architectural plans) to translate people needs in non ambiguous informations that will be useful for those who build the house. Musician uses musical notes, physician uses schemas to represent molecules, etc... And programmers use programming languages, when we write a line of code we don't hope that the compiler will understand what we write. Musical notes are a kind of abstraction: higher level than audio frequency but lower level than natural language. Same for programming language. Getting rid of all the formal languages take us back 2000 years ago. Using a formal language also help to enter in a kind of flow. And then details you did not think about before using the formal language may appear. Everything cannot be prompted, just like Alex Honnold prepared his climbing of El Capitan very carefully but it's only when he was on the rock that he took the real decisions. Same for Lindbergh when he crossed the Atlantic. The map is not the territory.
- kvisner 6mo agoI agree, but that formal language doesn't need to be executable code.
- ah1508 6mo agoSo you need to find something better. In an article "How NASA writes 'perfect' software (1996) (fastcompany.com)" (comments on HN), the author explains that adding GPS support required 1500 pages of spec, and to avoid ambiguity the spec used pseudo code to describe expected features and behaviors. If you invent a formal language that is easy to read and easy to write, it may look like Python... Then someone will probably write an interpreter. We have many languages, senior people who know how to use them, who enjoy coding and who don't have a "lack of productivity" problem. I don't feel the need to throw away everything we have to embrace what is supposed to be "the future". And since we need good devs to read and LLM generated code how to remain a good dev if we don't write code anymore ? What's the point of being up to date in language x if we don't write code ? Remaining good at something without doing it is a mystery to me.
- achierius 6mo ago> Assembly to Python creates a lot of Intent & Cognitive debt by his definition, because you didn't think through how to manipulate the bits on the hardware, you just allowed the interpereter to do it I agree! You often see this realized when projects slowly migrate to using more and more ctypes code to try and back out of that pit. In a previous job, a project was spun up using Python because it was easier and the performance requirements weren't understood at that time. A year or two later it had become a bottleneck for tapeout, and when it was rewritten most of the abstract architecture was thrown out with it, since it was all Pythonic in a way that required a different approach in C++
- jdw64 6mo agoI like the word intent, but Martin Fowler’s essay made me think more carefully about it. When Thomas Kuhn talked about paradigm shifts, “paradigm” ended up carrying more than twenty different meanings. In the same way, I think intent has recently become one of the most polluted and overused words in programming. My own toy language project uses the word intent, so I am not really in a position to criticize others too harshly. Reading the Hacker News comments, I kept thinking that programming is fundamentally about building mental models, and that the market, in the end, buys my mental model. If we start from human intent, the chain might look something like this: human intent -> problem model -> abstraction -> language expression -> compilation -> change in hadrware But abstraction and language expression are themselves subdivided into many layers. How much of those layers a programmer can afford not to know has a direct effect on that programmer’s position in the market. People often think of abstraction as something clean, but in reality it is incomplete and contextual. In theory it is always clean; in practice it is always breaking down. Depending on which layer you live in, even when using the same programming language, the form of expression can become radically different. From that point of view, people casually bundle everything together and call it “abstraction” or “intent,” but in reality there is a gap between intent and abstraction, and another gap between abstraction and language expression. Those subtle friction points are not fully reducible. Seen from that perspective, even if you write a very clear specification, there will always be something that does not reduce neatly. And perhaps the real difference between LLMs and humans lies in how they deal with that residue. Martin frames the issue in a way that suggests LLM abstractions are bad, but I do not fully agree. As someone from a third-world country in Asia, I have seen a great deal of bad abstraction written in my own language and environment. In that sense, I often feel that LLM-generated code is actually much better than the average abstractions produced by my Asian peers. At the same time, when I look at really good programming from strong Western engineers, I find myself asking again what a good abstraction actually is. The essay talks about TDD and other methodologies, but personally I think TDD can become one of the worst methodologies when the abstraction itself is broken. If the abstraction is wrong, do the tests really mean anything? I have seen plenty of cases where people kept chasing green tests while gradually destroying the architecture. I have seen this especially in systems involving databases. The biggest problem with methodology is that it always tends to become dogma, as if it were something that must be obeyed. SOLID principles, for example, do not always need to be followed, but in some organizations they become almost religious doctrine. In UI component design, enforcing LSP too rigidly can actually damage the diversity and flexibility of the UI. In the end, perhaps what we call intent is really the ability to remain flexible in context and search for the best possible solution within that context. From that angle, intent begins to look a lot like the reward-function-based learning of LLMs.
- archagon 6mo agoAI is not an abstraction layer.
- xantronix 6mo agoIt is if you never cared about technical correctness nor owning consequences.
- ricardo_lien 6mo ago> you didn't think through how to manipulate the bits on the hardware, you just allowed the interpreter to do it The interpreter is deterministic but LLMs aren't.
- destring 6mo agoThe thing is that you paid that debt once. The mappings are well defined and deterministic. The whole purpose of an abstractions is to not have to look underneath it to make sure what you did with the abstraction is still correct. You can make sure because you, or someone you trust, did the work of paying that debt once. With LLMs you always need to verify the output, for every generation you need to pay that debt. So it is not an abstraction.
- patrickmay 6mo agoExactly, well said. "The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise." -- Edsger Dijkstra
- PaulHoule 6mo agoHits the spot for me. I am always pushing back on AI to simplify and improve concision.
- cindyllm 6mo ago[dead]
- curio_Pol_curio 6mo agoHow does it --if it does-- relate to your idea of "affordability porn" :) That line (between your other values?) was uproarious; I apologise for not u*voting it, partially because I couldn't vocalise my peculiar fetish att (+ "gnarliness-pornstar" doesn't sound nearly as enticing as "AI-affordability-pornstar" X)
- hibikir 6mo agoLLMs don't lack the virtue of laziness: it has it if you want it to, by just having a base prompt that matches intent. I've had good success convincing claude backed agents to aim for minimal code changes, make deduplication passes, and basically every other reasonable "instinct" of a very senior dev. It's not knowledge that the models haven't integrated, but one that many don't have on their forefront with default settings. I bet we've all seen the models that over-edit everything, and act like the crazy mid-level dev that fiddles with the entire codebase without caring one bit about anyone else's changes, or any risk of knowledge loss due to overfiddling. And on Jess' comments on validating docs vs generating them... It's a traditional locking problem, with traditional solutions. And it's not as if the agent cannot read git, and realize when one thing is done first, in anticipation of the other by convention. I'm quite senior: In fact, I have been a teammate of a couple of people mention in this article. I suspect that they'd not question my engineering standards. And yet I've no seen any of that kind of debt in my LLM workflows: if anything, by most traditional forms of evaluating software quality, the projects I work on are better than what they were 5, 10 years ago, using the same metrics as back then. And it's not magic or anything, but making sure there are agents running sharing those quality priorities. But I am getting work done, instead of spending time looking for attention in conferences.
- dc_giant 6mo agoMind sharing the instructions you give Claude to go for minimal code changes etc?
- awesome_dude 6mo agoI often say to Claude "you're doing X when I want Y, how can I get you to follow the Y path without fail" and Claude will respond with "Edit my claude.md to include the following" which I then ask Claude to do.
- mettamage 6mo agoAh yea I do that too. I often have reflection sessions with Claude where I ask it "how can I make sure you do behavior X so we get outcome Y?" It works relatively well but not always.
- brodouevencode 6mo ago> ...to develop the powerful abstractions that then allow us to do much more, much more easily. Of course, the implicit wink here is that it takes a lot of work to be lazy This lines up with YAGNI, but most people believe the opposite, often using YAGNI to justify NOT building the necessary abstractions.
- coldtea 6mo agoThe counter-argument is that people build abstractions they deem necessary but aren't, and then they're married to that premature architecture quite often. That's what YAGNI is there to advise against. I don't think what Fowler says here is in favor of saddling the early versions of your system with abstractions before you actually seen its use in practice, and its needs over time as requirements and conditions change. From this "Laziness drives us to make the system as simple as possible (but no simpler!) — to develop the powerful abstractions that then allow us to do much more, much more easily." it's clear that when he talks of abstractions he means of very basic, and as simple as possible, building blocks. Like having core, orthogonal, principles in the system. Not the kind of piling of software and pattern design abstractions e.g. the Java land in the past used to build.
- ryanisnan 6mo agoI think Martin isn't wrong here, but I've first hand seen AI produce "lazy" code, where the answer was actually more code. A concrete example, I had a set of python models that defined a database schema for a given set of logical concepts. I added a new logical concept to the system, very analogous to the existing logical set. Claude decided that it should just re-use the existing model set, which worked in theory, but caused the consumers to have to do all sorts of gymnastics to do type inference at runtime. It "worked", but it was definitely the wrong layer of abstraction.
- michaelrpeskin 6mo agoIs more code really bad? For humans, yes we want thing abstracted, but sometimes it may make more sense to actually repeat yourself. If a machine is writing and maintaining the code, do we need that extra layer now? In the olden days we used Duff's devices and manually unrolled loops with duplicated code that we wrote ourselves. Now, the compiler is "smart" enough to understand your intent and actually generates repeated assembly code that is duplicated. You don't care that it's duplicated because the compiler is doing it for you. I've had some projects recently where I was using an LLM where I needed a few snippets of non-trivial computational geometry. In the old days, I'd have to go search for a library and get permission from compliance to import the library and then I'd have to convert my domain representations of stuff into the formats that library needed. All of that would have been cheaper than me writing the code myself, but it was non-trivial. Now the LLM can write for me only the stuff I need (no extra big library to import) and it will use the data in the format I stored it in (no needing to translate data structures). The canon says the "right" way to do it would be to have a geometry library to prevent repeated code, but here I have a self contained function that "just works".
- zingar 6mo agoWe have confidence in the extra code a compiler generates because it’s deterministic. We don’t have that in LLMs, neither those that wrote nor read the code.
- jazzypants 6mo ago
- mfiguiere 6mo agoWrong link. Technical, Cognitive and Intent Debt was discussed here: https://martinfowler.com/fragments/2026-04-02.html https://martinfowler.com/fragments/2026-04-02.html
- tomhow 6mo agoThanks! we updated the link.
- backprop1989 6mo ago> The problem is that LLMs inherently lack the virtue of laziness. I assure you, they do not.
- xdennis 6mo agoI completely agree. This is one of the most annoying things about LLMs. I always see them fixing linter errors by adding ignore comments, typing many things as "Any", duplicating test fixtures instead of extracting them, sometimes deleting tests they don't like, etc. My most recent Claude Code fix consisted of one line: calling `third_party_lib._connect()`. It reaches into the internals of an external library. The fix worked, but it is improper to depend on the specific implementation. The correct fix was about 20 lines. (Tangentially, this is why I think LLMs are more useful for senior developers because junior developers tend to not have a sense for what's good quality and accept whatever works.)
- globular-toast 6mo agoI've seen them adding "ignore" for linter errors I don't even catch in my CI. For example, adding Pylint stuff when I don't even use Pylint. This isn't laziness. It's just parrot-fashion regurgitation of code, which is by design for LLMs.
- JulienMer 6mo ago[dead]
- kippinsula 6mo agothe framing as "debt" is fair but in our case the bigger pain isn't lazy code, it's overzealous code. claude will happily refactor three unrelated files because it spotted a "pattern". we've ended up with a CLAUDE.md that's basically a list of "do not touch unless asked". probably says more about us than the model but yeah.
- konovalov-nk 6mo agoThis is my current visualization of the problem: https://excalidraw.com/#json=y1fSSx2z8-0nFs7CDnqhp,d9Di8JdGUCDE4S3OkEFaDQ https://excalidraw.com/#json=y1fSSx2z8-0nFs7CDnqhp,d9Di8JdGU... I think the "cognitive bottlenecks" in software engineering live between artifacts, where code is simply one of them. outcome → requirements → spec → acceptance criteria → executable proof → review I'm making experimental tooling that automates the boring parts around those transitions, while keeping humans focused on validating that intent survived each step.
- chrisweekly 6mo agocool dataviz but it's editable! trying to pan and zoom and scoll on my phone led to moving elements around on the canvas
- konovalov-nk 6mo agoMy bad. Well, it's Excalidraw, and you can download png / svg from it. Here's image you can open on the phone https://pbs.twimg.com/media/HGjHvSsWIAAkhHL?format=jpg&name=4096x4096 https://pbs.twimg.com/media/HGjHvSsWIAAkhHL?format=jpg&name=... I also did a post explaining reasoning behind this diagram: https://x.com/br11k_dev/status/2047105958451507268 https://x.com/br11k_dev/status/2047105958451507268 But I'll make a proper post on HN once I have all ingredients ready! - Minimal CLI tooling - Jupyter Lab you can go through step by step, on example greenfield project (URL shortener app) - Blog post on what I've been doing for last 2 months
- therealdrag0 6mo agoActivate the “Hand” tool to avoid that.
- Grp1 6mo agoI like the "between artifacts" framing. One layer I'd add is proxies/metrics. In a lot of analytics-heavy systems, the real loss isn't spec -> code, it's question -> proxy. Once the proxy gets baked into acceptance criteria, dashboards, or evals, people optimize that and gradually forget it was only a proxy.
- aroido-bigcat 6mo ago[dead]
- takihito 6mo agoI heard that LLMs imitate humans. Let's add laziness, impatience, and arrogance—the virtues of programmers—to AGENTS.md and improve it.
- meander_water 6mo agoUnfortunately large parts of the paper that he linked to from the Wharton school is entirely AI generated, and yet to be peer reviewed. I realize that most researchers use AI to assist with writing, but when the topic of your paper is "cognitive surrender", I struggle to take any content in there seriously.
- ai_slop_hater 6mo ago> I realize that most researchers use AI to assist with writing This is disgusting
- stingraycharles 6mo agoUnfortunately this is the new reality, it’s everywhere.
- zeafoamrun 6mo agoGood thing I didn't read it but used an LLM to summarize it for me!
- jeremyjh 6mo agoI didn't even read a summary, I just used an LLM to write inane comments on hacker news for me.
- croemer 6mo agoIt uses "not merely" 7 times! I wonder if an LLM would repeat a phrase that often. It could be the author starting to write like LLMs, instead.
- __mharrison__ 6mo agoWhere's the other half of the article? What an abrupt ending...
- crabmusket 6mo agoThis isn't one article, it's a "fragments" post with five separate small thoughts. They happen to all be about LLMs so I can see why it would read as a single article, but it's not.
- oaiey 6mo agoThere is a paper linked which is describing the whole thing!
- unit149 6mo ago[dead]
- EverMemory 6mo ago[dead]
- aldielshala 6mo agoIntent debt is a useful framing. A few comments explaining "why" instead of "what" would have saved hours of guessing.
- russellthehippo 6mo agoBest thing I've read on hacker news in so long. I relate so hard. Simon Willison's stuff on cognitive debt and "your job is to ship code you have proven to work" have led me to work on a project about Intent-Driven Development, because prior intent always seemed to dim with each set of changes. Might put it together into a real protocol and post here on hacker news sometime.
- konovalov-nk 6mo agoI'm wondering if we're working on the same thing. If you haven't seen my posts I suggest to look through them. In short: 1. stacked-commits automation (cannot skip writing context/why/verify sections) 2. product specs (full ERD: https://excalidraw.com/#json=WT-oRUdyKBhAsDZJ3NwAR,WAbVgfO39XJ9zMkBxsM6ng https://excalidraw.com/#json=WT-oRUdyKBhAsDZJ3NwAR,WAbVgfO39...) 3. linking specs to code via SCIP indexes, and commits to ACs, later you can attach anything you want
- russellthehippo 6mo agoWow, yeah. You call it “optimizing for understanding.” I’ve been thinking about a very similar problem as “optimizing for execution of intent.” My version is roughly: if execution and verification are getting cheap, but taste, design, intent, and planning are still expensive, then the workflow should focus on how intent gets executed in each change and how it stays intact over time instead of slowly drifting. I’m more hesitant to formalize all of that into heavy tooling, but there are clear parallels here. I wrote up more of what I mean here: https://russellromney.com/blog/intent-driven-development https://russellromney.com/blog/intent-driven-development
- konovalov-nk 6mo agoYeah the single file SYSTEM.md would not scale. When you are working on something, you don't load entire context of entire app in your head, only "minimal viable context" (MVC). In my ERD this is a record in the Spec table. And sure, some specs might reference other specs. Some can depend implicitly or explicitly. But this is a clear anchor point you can approach two ways: either from searching from a list of specs, or by going to file you know needs editing, and calling `blast-radius` script to fetch which specs link to it. Intent can be represented as granular artifacts. The tiniest granularity in my schema is Acceptance Criterion, where it is represented in code as a test. It can be e2e, unit, integration — depends on the context and what is "acceptable" way to prove AC works on system level. For example, AC for product-level spec that says "Invalid input is rejected with clear feedback" (Submitting invalid input shows validation error and does not create a short URL record) means that we have e2e test in playwright that starts from the URL creation page and follows user across steps to receive the error. And the engineers who are working on this AC see it with their own eyes. But this might not be enough. Why? Because you can still show an error on screen, but the record in the DB would be created. So I decided there should be one more window that shows state of the objects (their properties) in real time. This could be simple TUI that just visualizes "evidence artifacts". Think of how a debugger works: you can step forward and you have local variables you can track. So the idea is simple: "Watch how playwright script executes steps for AC one by one, while you look at the DB table. After every step you see updated object state. If multiple state changes happened after a single step, ideally we want to display history of updates. At the end of run we compare evidence before/after state for every tracked object." I call this "runtime engine". This is approximately how engineers simulate it in their head when reading code. But why even bother simulating it, when we can simply run and observe what happens?
- diehunde 6mo agoIt's very nerve-racking for people who like to have a deep understanding of everything they ship. A modernization project that would take you 2 months now can be done in a week or less because you don't need to go deep into the business logic to replicate it and instead you can just focus on designing the boundaries and interfaces properly. Then like the article mentions, just create a good test harness to test parity as much as you can. I was feeling very conflicted about this myself, but then I thought: I have these other systems I have to maintain on a daily basis and I also don't understand the internals and business logic that well because I wrote them years ago and haven't changed much. I just rely on the test suite if something needs to be changed or the code structure if I need to see how something in particular works.
- lucketone 6mo agoTo have good test harness you need to get deep into business logic. Am I missing something?
- mandeepj 6mo ago> It's very nerve-racking for people who like to have a deep understanding of everything they ship. A deep domain knowledge of your industry and your business (company/org) makes you very valuable in your team and your company. I've seen people survive layoffs and other cost-cutting cycles just because they possessed immense knowledge compared to those who did not.
- triage8004 6mo agoYou clearly know what you are talking about but I didn't understand about your testing methods explanation at all.
- CharlieDigital 6mo ago> The most creative act is this continual weaving of names that reveal the structure of the solution that maps clearly to the problem we are trying to solve. From Confucius, The Analects, 13.3: If names are not rectified, then language will not be in accord with truth. If language is not in accord with truth, then things cannot be accomplished. If things cannot be accomplished, then ceremonies and music will not flourish.
- chaosprint 6mo agoWell written. I also wrote in my personal notes yesterday that if you don't organically and continuously develop code, it's hard to say you truly "own" it. Like self-driving cars, at least you remember the scenery along the way, but now it just teleports you to another place and then shows you the recording. This kind of review is ineffective. Such ghosted code might be acceptable for small tools, but for databases or similar systems, it's really worrying. I've now basically stopped granting the agent any write permissions and returned to how I wrote codes 2 years ago with manual QA. The thing is, it's actually more efficient in turns of tokens and the results. That's just my personal experience.
- yasirlatif 6mo agoThe "intent debt" framing is the most underappreciated category here. Cognitive and technical debt are at least visible in the code. Intent debt is invisible — it only surfaces when someone makes a change that's locally reasonable but globally wrong because the original constraint no longer exists in any artifact. The hardest version of this is in enterprise systems where the constraint was a regulatory requirement that quietly changed three years ago, but nobody updated the code because the tests still passed. You can't recover intent from a test suite.