{"componentChunkName":"component---src-templates-blogpost-js","path":"/post/less-context-more-constraint/","result":{"data":{"contentfulBlogPost":{"title":"Less context, more constraint","slug":"less-context-more-constraint","createdAt":"2026-05-22T02:05:47.195Z","body":{"childMarkdownRemark":{"html":"<p>Most of what gets written about AI pair-programming is either \"this is going to replace all of us\" or \"this is just autocomplete on steroids.\" I've just spent four months building a piece of moderately complex embedded firmware in pair with Claude Code, and neither of those framings matches what I actually saw. The patterns that worked for me were quieter, narrower, and in some cases the opposite of the popular advice.</p>\n<p>This article is the set of those patterns. It's one engineer's four-month experiment, so take it as a single case study rather than a survey. But the project was complex enough - hardware, network protocols, real-time constraints, independent measurement - that I think the lessons transfer to other domains. Any domain, really, where the AI's enthusiasm needs to be checked against a working system that doesn't lie.</p>\n<p>The companion to this is <a href=\"https://rjk.codes/post/23-microseconds-building-ieee-1588-ptp-on-a-4-microcontroller/\">the timing engineering article</a>, which describes what was actually built. This one is about how I built it and what that experience suggests about getting more out of an AI pair programmer on a hard problem.</p>\n<p>A note on the genre: most of what follows is not \"use this prompt template\" advice. It's about how the workflow changes, where the AI's judgment is useful and where it isn't, and a couple of habits I think most teams should pick up. I've tried to avoid restating things that are already discussed well elsewhere - if a section feels obvious to you, skip it.</p>\n<h2 id=\"the-popular-advice-on-context-is-wrong-for-interactive-workflows\" style=\"position:relative;\"><a href=\"#the-popular-advice-on-context-is-wrong-for-interactive-workflows\" aria-label=\"the popular advice on context is wrong for interactive workflows permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The popular advice on context is wrong for interactive workflows</h2>\n<p>The common framing on prompting is <em>\"give the model as much context as possible.\"</em> It's the framing behind RAG, behind giant system prompts, behind the dump-the-whole-codebase trend. My four months of data look nothing like that.</p>\n<table>\n<thead>\n<tr>\n<th></th>\n<th>Nov 2025</th>\n<th>Dec 2025</th>\n<th>Feb 2026</th>\n<th>Mar 2026</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Median prompt length</td>\n<td>86 chars</td>\n<td>83</td>\n<td>65</td>\n<td><strong>61</strong></td>\n</tr>\n<tr>\n<td>Prompts containing pasted text</td>\n<td><strong>29%</strong></td>\n<td>14%</td>\n<td>9%</td>\n<td><strong>0%</strong></td>\n</tr>\n<tr>\n<td>Prompts with file paths, URLs, commit hashes or line refs</td>\n<td>6%</td>\n<td>6%</td>\n<td>0%</td>\n<td><strong>0%</strong></td>\n</tr>\n</tbody>\n</table>\n<p>(1,275 prompts across the project, this project only, pulled from <code class=\"language-text\">~/.claude/history.jsonl</code>.)</p>\n<p>Pastes went from nearly a third of my prompts to zero. Explicit pointers went to zero. Median prompt length dropped 30%. Whatever I was doing, \"stuff more context into each prompt\" was the opposite of it.</p>\n<p>A comparison from the prompt data makes the pattern clearer:</p>\n<ul>\n<li><strong>2025-12-19</strong>: <code class=\"language-text\">csv is in tests/baseline.csv</code></li>\n<li><strong>2026-03-04</strong>: <code class=\"language-text\">lets try 0.15</code></li>\n</ul>\n<p>Both are short. The December one carries a pointer: here's the file, here's where to find it. The March one carries nothing - just an instruction. By March the model already knew that <code class=\"language-text\">lets try 0.15</code> meant: edit a particular <code class=\"language-text\">#define</code>, rebuild the firmware, flash it to a specific device, settle for thirty minutes, run a one-hour integration test, write the results to a timestamped directory. None of that was in the prompt because none of it needed to be. The context was in the conversation.</p>\n<p>This contradicts a lot of the prompting literature, but the contradiction is about <em>mode</em>. Most advice on prompting assumes a one-shot interaction: a single prompt against a fresh model with no shared history. For that case, more context probably does help. Interactive pair-programming is a different mode. The conversation accumulates context over time, and once it's loaded, restating it has two costs: it's wasted tokens, and it gives the model a chance to weight the restated version more heavily than the original or to get confused about which version is current.</p>\n<p>The pattern that emerged was simple: build up shared context early, then keep your prompts tight. Pay the cost of restating context only when something new turns up; otherwise let the conversation do the carrying.</p>\n<p><strong>For your project:</strong> audit a long session's prompts. How many of them are restating something the model has already been told? Each one is friction you've stopped noticing. The shortest prompt that conveys your intent is usually the one that produces the cleanest output, because it's the one that leaves the model the least to misuse.</p>\n<h2 id=\"constraints-belong-in-your-tooling-not-your-prompts\" style=\"position:relative;\"><a href=\"#constraints-belong-in-your-tooling-not-your-prompts\" aria-label=\"constraints belong in your tooling not your prompts permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Constraints belong in your tooling, not your prompts</h2>\n<p>There is a category of thing you do want to state - operational constraints, things the model must not do, scopes it must not exceed. These look like context but aren't. They're rules.</p>\n<p>A representative example from my own history:</p>\n<blockquote>\n<p><strong>2025-12-06</strong>: <code class=\"language-text\">lets go step by step, but remember do not break the ethernet grandmaster or slave, wifi code should be specific to the measurement device, show me each step before we implement it</code></p>\n</blockquote>\n<p>That's not adding context, it's ring-fencing. I'm telling Claude what <em>not</em> to touch, what the unit of work is, and what verification I expect along the way.</p>\n<p>The trap with constraints is that they're easy to forget. The model is helpful, the conversation moves on, and three turns later the helpful new code happens to touch the thing you said not to touch. Reminding the model in prose, prompt by prompt, is unreliable.</p>\n<p>The pattern I converged on: any constraint I'd stated twice belonged in my tooling, not in my prompts. Flash the slave only, never the grandmaster? Encode it as <code class=\"language-text\">picotool load --ser &lt;slave-serial&gt;</code>, used consistently. The constraint is enforced by the tool rather than remembered by the model. Save every test artefact to a timestamped directory? Build it into the integration harness so it can't be forgotten. Use the project's virtual environment, never global packages? Make the venv-activation step part of every run command.</p>\n<p>This sounds like normal engineering discipline because it is. What's different with AI is that the cost of <em>not</em> doing it is higher. A human engineer reminded once will usually internalise the constraint. An AI in a long session will probabilistically drift, especially as the conversation gets dense and the early instructions slip out of attention. The defence is to make the constraint impossible to violate without conscious effort, rather than easy to violate by accident.</p>\n<p><strong>For your project:</strong> make a list of the operational rules you've stated to the AI more than twice. Each one is a candidate for codification. A wrapper script, a config check, a pre-commit hook, a test that fails when the constraint is violated. Anything that moves the rule out of your prompts and into your workflow. \"If you've reminded the model twice, you've found tooling work\" is a useful instinct.</p>\n<h2 id=\"the-ai-optimises-for-the-easy-path-not-the-right-one\" style=\"position:relative;\"><a href=\"#the-ai-optimises-for-the-easy-path-not-the-right-one\" aria-label=\"the ai optimises for the easy path not the right one permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The AI optimises for the easy path, not the right one</h2>\n<p>This was the slowest of the patterns to recognise, and probably the most useful one once I did.</p>\n<p>Three examples will land it.</p>\n<p><strong>The data-source bias.</strong> I wanted automated phase measurement off my oscilloscope. Claude proposed image capture: take a screenshot, parse it with computer vision, extract the offset. We built it. It worked at coarse phase, quantised badly at fine phase, and aliased silently because the scope's display bandwidth was lower than its sample rate. The redirect was a single prompt:</p>\n<blockquote>\n<p><strong>2026-02-19</strong>: <code class=\"language-text\">I think we can pull waveform data off the scope and calculate this ourselves? per this example?</code></p>\n</blockquote>\n<p>We switched to VXI-11, pulled the actual waveform samples, computed the phase from those. Much cleaner. The image approach worked, technically, but it was the easiest data source the model could see, not the most accurate.</p>\n<p><strong>The completeness bias.</strong> When I first asked Claude to build the WiFi PTP stack, the response was the whole stack: network, GPS parsing, PTP message handling, the lot. We flashed it. There was no serial output, no network connectivity, no way to tell what was failing. The AI's instinct is to give you the complete thing in one go. Mine, learned painfully, is to insist on vertical slices: get USB serial output working first, then WiFi association alone, then GPS NMEA parsing alone, then integration. Each step needs a visible checkpoint. The model is happy to build the whole stack; you have to be the one asking for the parts.</p>\n<p><strong>The plausible-options bias.</strong> When something unexpected breaks in the system, the AI's first response is usually \"here are three plausible fixes.\" All of the fixes might work, in the narrow sense. But \"here are three fixes\" is not always the right first move - sometimes \"let's understand what changed\" is. The AI defaults to moving forward. You have to be the one asking for diagnosis before treatment.</p>\n<p>The common thread across all three: the AI is reaching for whatever's easy to do right now. It's not unwilling to consider better paths - but it won't propose them spontaneously. You have to be the one asking \"is there a cleaner upstream source?\" or \"what's the simplest possible thing that would prove this works?\" or \"what changed before this broke?\"</p>\n<p><strong>For your project:</strong> build a habit of three questions to ask before accepting any AI-proposed solution. <em>Is there a cleaner input upstream? Is this the simplest thing that would prove the point? What changed before the symptom appeared?</em> They're the questions an experienced engineer asks out of habit. The AI doesn't ask them spontaneously, but it engages well with them once you do.</p>\n<h2 id=\"the-ai-cant-see-the-costs-you-can\" style=\"position:relative;\"><a href=\"#the-ai-cant-see-the-costs-you-can\" aria-label=\"the ai cant see the costs you can permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The AI can't see the costs you can</h2>\n<p>Continuing the plausible-options theme from the previous section: at one point in the project I changed the PTP sync rate from 1 Hz to 4 Hz, on the theory that more frequent corrections would tighten the servo. The result was a +300 µs shift in the slave's reported phase offset, and the sigma didn't improve. Claude proposed three fixes: recalibrate an asymmetry constant for the new rate, add a rate-dependent term to the calibration model, build an auto-calibration step that adjusted at runtime.</p>\n<p>All three would have technically worked. The right answer was none of them. The right answer was to revert to 1 Hz and treat the failure as evidence that the change had broken an assumption I'd locked in earlier (a hand-calibrated constant that was valid only at 1 Hz). What I actually sent was this:</p>\n<blockquote>\n<p><strong>2026-03-07 15:31</strong>: <code class=\"language-text\">can we revert to 1hz and make sure we have the same performance and we have locked that in, lets go back to 1hz, flash both, settle for 30min and then test for 1hr, post that we save results, and make sure we commit code and then we can try again with the 4hz version along with the other term update</code></p>\n</blockquote>\n<p>That's not the AI's instinct. The AI's instinct, given a problem and three plausible fixes, is to offer the fixes. What it doesn't see is the <em>maintenance cost</em> of those fixes. Each one would have added a new parameter or behaviour to the system - something I'd own forever, that I'd have to recalibrate whenever I changed anything else, that future-me would have to remember when debugging an unrelated regression. That cost is invisible from inside the chat. From the AI's perspective, \"add a rate-dependent term\" is just a code change. From mine, it's a parameter I'd be looking after for the rest of the project.</p>\n<p>This is the place where the AI did not move my workload. If anything it moved it <em>forwards</em> - I had to actively resist the natural pull of having three plausible solutions in front of me. The decision to back out a change is harder when you have to argue against three options that are sitting there ready to implement.</p>\n<p>The general form: the AI proposes solutions in the local frame. You hold the global frame. Maintenance cost, parameter proliferation, the question \"is this change consistent with assumptions made elsewhere,\" the question \"is solving this symptom worth the architectural complexity it introduces\" - those don't appear in the AI's reasoning unless you put them there.</p>\n<p><strong>For your project:</strong> when the AI hands you N reasonable options, add one more question to your standard set: <em>which of these introduces a parameter or interaction I'll have to maintain forever?</em> The honest answer is usually \"all of them, to varying degrees,\" and that question alone often surfaces a better option (back out, redesign, find a different angle) that wasn't in the original list.</p>\n<h2 id=\"independent-validation-matters-more-with-ai-not-less\" style=\"position:relative;\"><a href=\"#independent-validation-matters-more-with-ai-not-less\" aria-label=\"independent validation matters more with ai not less permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Independent validation matters more with AI, not less</h2>\n<p>This is the most obvious of the patterns to anyone who has done engineering for a while, but it's worth stating in the context of AI pair-programming, because the stakes are higher now.</p>\n<p>On this project, what kept me honest was an independent measurement device: a separate microcontroller, with its own GPS reference, observing the actual outputs of the system and reporting them to a host computer. The companion timing article explains the why and the how. What's relevant here is what would have happened without it.</p>\n<p>Without the measurement device, every claim about how well the system was working would have come from the system's own self-report. And the system computes its self-report from the same data it uses to drive itself, so any error in that data produces an error in the self-report that the control loop will then drive to zero. The system can lock into a beautiful, tight loop while being systematically wrong by a margin that would never show up internally.</p>\n<p>With an AI in the loop, the risk is worse, because the AI is fluent. It will explain why the metrics are good. It will propose improvements that look reasonable. It will write summary statistics and mark the runs as passing. If you don't have an independent way to check, you'll ship something that looks right and isn't.</p>\n<p>A concrete instance: during a routine test late in the project, the slave's self-report briefly claimed a 23 <em>millisecond</em> phase excursion. The cumulative sigma for the test was wrecked and the run failed its threshold. But the measurement device, watching the physical output, recorded a clean 23-microsecond sigma across the same window - the 23 ms spike existed only in the calculation, not in the physical world. Most likely one bad data point that the control loop correctly ignored. Without the measurement device I'd have spent days chasing a regression that didn't exist.</p>\n<p>The general claim: with an AI in the loop, the cost of <em>not</em> having an independent ground truth is higher, because the AI's fluency moves faster than your ability to check by reading. The discipline of \"build the verification before you build the thing\" is older than AI, but AI raises the stakes.</p>\n<p><strong>For your project:</strong> before you put the AI on anything important, ask: <em>how would I know if this was wrong?</em> If the answer is \"I'd notice in production\" or \"I'd see it in the logs,\" that's not enough. You need a check that runs against ground truth - a test against a known-good output, a measurement from outside the system, a property that holds independently of the code being tested. The AI will execute on whatever you specify; if your verification is weak, you'll get fluent code that passes weak verification.</p>\n<h2 id=\"a-note-on-the-cost-of-trying-shift\" style=\"position:relative;\"><a href=\"#a-note-on-the-cost-of-trying-shift\" aria-label=\"a note on the cost of trying shift permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A note on the cost-of-trying shift</h2>\n<p>This is the AI-pair-programming claim that's discussed most often, and I won't dwell on it. But it deserves an honest mention because it did shape the project.</p>\n<p>Two specific moments. The first was a two-week detour where I designed and implemented a one-way time-sync protocol from scratch as a comparison to PTP. I would not have attempted that detour without AI. The cost in calendar weeks would have made it look like a poor use of evenings and weekends. With AI, the cost was manageable, and the detour produced one of the project's most useful insights - a smoother frequency-domain servo design that fed back into the main PTP code.</p>\n<p>The second was a six-point parameter sweep across the servo's gain, each value requiring a ninety-minute test run. Six attended hours of test execution at the bench would have been a multi-week project across spare evenings. With Claude executing the sweep, it ran across two evenings. And the sweep changed the answer - I had previously concluded the optimum was at one value by sweeping downward from there. The cheap sweep upward (which I wouldn't have run otherwise) revealed a different optimum.</p>\n<p>The way I'd put it: the right measure of AI productivity isn't \"lines of code per hour.\" It's the <em>minimum experiment size you'll consider attempting</em>. That number drops by maybe an order of magnitude, and it changes the set of projects worth attempting. Detours become recoverable. Sweeps become manageable. Speculative comparisons become worth doing.</p>\n<p>This is the only well-discussed claim in the article. Everything above it, I think, is less commented on.</p>\n<h2 id=\"what-didnt-change\" style=\"position:relative;\"><a href=\"#what-didnt-change\" aria-label=\"what didnt change permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What didn't change</h2>\n<p>The work the AI doesn't touch is the work that decides which experiments are worth running, what counts as a good enough result, when to back out a change, and how to know if the result is real. None of that moved on this project. If anything it became more visible, because it is now the part that is mine alone.</p>\n<p>Specifically:</p>\n<ul>\n<li><strong>Architecture decisions</strong> stayed mine. The major structural choices, the build-versus-buy calls, the \"let's try this entirely different approach\" moments - Claude proposed options and trade-offs when I asked; the calls were mine.</li>\n<li><strong>Hardware reality</strong> stayed mine. Physical-world problems cannot be reasoned about through a chat interface.</li>\n<li><strong>The smell test</strong> stayed mine. When Claude has three plausible fixes in front of you and the right answer is \"back out the change,\" you have to want that answer.</li>\n<li><strong>Independent validation</strong> stayed mine. The measurement device existed because I built it, not because the AI suggested it.</li>\n<li><strong>Knowing the domain well enough to validate</strong> stayed mine. The project worked because I understood the underlying engineering well enough to recognise when something was wrong. I'm sceptical of any \"AI replaced an engineer\" story where the human didn't already understand the problem well enough to validate the output.</li>\n</ul>\n<p>The honest claim is that this is not AGI doing engineering. It's a way of getting more done, if you already know what you want to build. The \"know what you want to build\" part still costs what it always costs - and arguably more, not less, because the AI will execute on whatever you specify. If you don't know what to specify, you'll get something that looks right and isn't.</p>\n<p>The patterns in this article are about getting more out of an AI pair programmer while keeping the knowing-what-you-want part intact. Less context, more constraint. Ask which path is right, not which is easiest. See the things the AI can't see. Validate independently or don't ship. None of it is revolutionary. None of it is well-discussed either, and four months in I think most of it is genuinely useful.</p>"}},"synopsis":{"synopsis":"Lessons on AI pair programming from a medium-duration, high-complexity project."},"image":{"fluid":{"base64":"data:image/png;base64,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F3CculE8AAAC9FBMVEUOIToAJDllT3KSaZpaUnAwQ1gZKUITHDoPFzkLFjodJj83Q0lMWlNZalpKWFMnMEcqNEgpNkciL0EbKTwRIzsAIDdQRmN/YomHaY9pVXUQIT4ZKkMpPlJASVFZZmBRXl1CTlc7RFg2PlUzPFIwO04pNUgbKT4RITcOIDkJITotNk1rWHlGQFonSFkvWGY4YW4+Wmo6QVU6QVc+RV89RF9CSGM1PVUpM0obJkAUID0PHDsMGzkIGTMQJD4pLUdDQVgvRFMxWGc6T2M5Qlo7QFo8QVs8QFtGS2dFS2czOlYWIj8XJEEZJkMgKkUvQ0MvRT4FFi8RIz0nLklAQ1wzPlYxNlE4PVc8P1pARF85SWVCXHdESWElLUsoMk8oM1A/R2BUWG5CS1xDX0czSUAFFi4LGzQVJ0IYKEExPlY0QFk4RmMvUW8pYIEiX4IzWno9QmI8Q2NPU25ra4JtbIJWV20qMEkQGTUCBCUFFy4RITsRIzxAOVxYQW4yUXUcWHgkQF8sM1Q5QVZLXl1XbWJgYnhNTWciKEEAAB4AARYEChoPDx8FFS0IGjISIjxENFo/NFkhK0gnLUhISmNUV3BUbmBge2dRaVYnMzwAABUAARIMDx0YFyMbGicZHCkIFzAIGDIHFzAMHTcAGTIeK0NGS2RYWnVgYH1KWGA/WUYeLy0AABcVEyMfGyggHioZHCoUHSwQGyoEFCwIGDEMHTkwNlBPUm9FSGMvMUcAARgAABIMCiAeHCklISwoKDEhJzEWIC8OGSkQGSgRGScPGzEGFi4GFi8JGDEOFy0UGywAABEAAxYWFygiIS0mJC4kJS4gJzEjLjYaJDAXHywXHSkWHCkeKD8EEysEEScDDiEBDBsBChkIDyEZGi0kIzMjIjAgIy8hKTIZJDAcJjElLDImLDIfJiwZHykVGicVGyYOGCwCDB0CDBkEDRwMEiIUFykcHCwgIzEtNTUkLDMmLzUrNDMnLTInLTEcIiodISoSFyUTGSYdIikwZenAAAAAOUlEQVQY02NkYMQCRLCIsdBEEIv1LMI3NbAIWiM474VggrcY1GGCQjCVQgyW6LrfMV4l5KR/zBAaALgACDhnODXCAAAAOHRFWHRpY2M6Y29weXJpZ2h0AENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBhY2thcmQgQ29tcGFueflXeTcAAAAhdEVYdGljYzpkZXNjcmlwdGlvbgBzUkdCIElFQzYxOTY2LTIuMVet2kcAAAAmdEVYdGljYzptYW51ZmFjdHVyZXIASUVDIGh0dHA6Ly93d3cuaWVjLmNoHH8ATAAAADd0RVh0aWNjOm1vZGVsAElFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQkRTSKkAAAAASUVORK5CYII=","aspectRatio":1.5393386545039909,"src":"//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=1000&q=50","srcSet":"//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=250&h=162&q=50 250w,\n//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=500&h=325&q=50 500w,\n//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=1000&h=650&q=50 1000w,\n//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=1350&h=877&q=50 1350w","srcWebp":"//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=1000&q=50&fm=webp","srcSetWebp":"//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=250&h=162&q=50&fm=webp 250w,\n//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=500&h=325&q=50&fm=webp 500w,\n//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=1000&h=650&q=50&fm=webp 1000w,\n//images.ctfassets.net/gwhekaixyfn6/3SQzGsxIpZsoPQXg21h2nB/2506e7429adb4b9487518711a1bdf43e/code.png?w=1350&h=877&q=50&fm=webp 1350w","sizes":"(max-width: 1000px) 100vw, 1000px"}},"tags":["ai","coding"]}},"pageContext":{"slug":"less-context-more-constraint","id":"546639f9-9426-508f-b3ee-dff55896a7ac"}}}