<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Thiago Pacheco</title>
    <description>The latest articles on Forem by Thiago Pacheco (@pacheco).</description>
    <link>https://forem.com/pacheco</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36392%2Fc0128130-62c1-45b5-8a3e-6950e9c6a3ac.jpeg</url>
      <title>Forem: Thiago Pacheco</title>
      <link>https://forem.com/pacheco</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pacheco"/>
    <language>en</language>
    <item>
      <title>Anatomy of a Coding Agent: What I Learned Building My Own</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Thu, 21 May 2026 19:05:09 +0000</pubDate>
      <link>https://forem.com/pacheco/anatomy-of-a-coding-agent-what-i-learned-building-my-own-155f</link>
      <guid>https://forem.com/pacheco/anatomy-of-a-coding-agent-what-i-learned-building-my-own-155f</guid>
      <description>&lt;p&gt;You use Claude Code every day. But do you really know it?&lt;/p&gt;

&lt;p&gt;I didn’t. Not really. I could describe the surface, but I couldn’t tell you what was actually happening between hitting enter and seeing a diff. The harness was a black box, and that started to bother me. The only way I knew to fix that was to build one.&lt;/p&gt;

&lt;p&gt;The result is &lt;a href="https://github.com/sudoish/oli" rel="noopener noreferrer"&gt;oli&lt;/a&gt;, a single-binary terminal coding agent written in Rust that runs against Ollama by default. It got much larger than I expected. Every “small” subsystem (memory, policy, tool dispatch, provider quirks) turned out to have its own thicket of edge cases. I learned more about coding agents in a few weeks of building one than I had in a year of using them daily.&lt;/p&gt;

&lt;p&gt;The hard parts aren’t clever prompts. They’re context management, tool design, policy gates, memory strategies and, if you want to run locally, survival engineering for models that don’t behave like the GPT-5 or Claude 4 families. This post is a tour of those parts, with the failures that taught me each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Big Picture
&lt;/h2&gt;

&lt;p&gt;Before diving into components, here’s what a coding agent actually looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gru7zj6c0mihbyqkima.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gru7zj6c0mihbyqkima.png" alt="Coding Agent Architecture" width="799" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agent Loop
&lt;/h2&gt;

&lt;p&gt;Every coding agent runs the same basic loop:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsgrnjv3s5dbbh2ne8al.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsgrnjv3s5dbbh2ne8al.png" alt="Agent Loop" width="427" height="734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think → call → observe → repeat. The loop is deceptively simple. Everything hard lives in the details.&lt;/p&gt;

&lt;p&gt;Three things I learned the hard way:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn limits matter, even on local models.&lt;/strong&gt; Early on, a local model I was testing got stuck, it looped 47 times trying to “fix” a file that was already correct, burning through my entire context window before I caught it. The model wasn’t broken. The harness was: no turn limit, no escape hatch, no awareness that the model had lost the plot. The instinct is to say “who cares, I’m running locally, tokens are free.” But the cost isn’t dollars, it’s coherence. As context fills, models degrade: attention spreads thinner, instructions in the middle of the window get ignored (“lost in the middle”), and every failed attempt becomes a distractor that biases the next turn toward more wrong behavior. This is &lt;em&gt;especially&lt;/em&gt; true on local models, whose effective context is often a fraction of their advertised window — a Qwen3 advertised at 256K may stay coherent only through the first 32-64K. A runaway loop doesn’t just waste compute; it actively makes the agent stupider for the rest of the session. Now subagents get hard turn limits by default, and the top-level agent is capped too, with a config default you can override per run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The system prompt is pinned.&lt;/strong&gt; It survives &lt;code&gt;/clear&lt;/code&gt;, survives memory compaction, survives everything. The first time I accidentally cleared the system prompt mid-session, the model forgot what tools it had and started apologizing for being unable to help. Pinning was an obvious fix in hindsight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Re-entrancy is a trap.&lt;/strong&gt; A Task tool that spawns a subagent which can itself spawn subagents quickly becomes a fork bomb. oli sidesteps the whole problem by registering &lt;code&gt;Task&lt;/code&gt; only in the parent agent — subagents get the same tool set &lt;em&gt;minus&lt;/em&gt; &lt;code&gt;Task&lt;/code&gt;, so they can’t recurse.&lt;/p&gt;

&lt;h2&gt;
  
  
  The System Prompt
&lt;/h2&gt;

&lt;p&gt;Before you say anything, the model already gets a lot of scaffolding:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr31l0ih2fy27ipm7i78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr31l0ih2fy27ipm7i78.png" alt="System Prompt Structure" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;AGENTS.md&lt;/code&gt; + &lt;code&gt;CLAUDE.md&lt;/code&gt; line matters. Both Codex and Claude Code established conventions for per-project agent instructions. oli reads both, at every directory level from your current location up to the filesystem root — so a workspace-wide convention can be overridden by a project-level one without copy-pasting.&lt;/p&gt;

&lt;p&gt;Note that the system prompt text and the tool schemas are separate payloads in the provider request — a better mental model than “everything lives in one giant prompt.”&lt;/p&gt;

&lt;p&gt;The system prompt is &lt;strong&gt;expensive&lt;/strong&gt;. It consumes tokens on every single turn. I learned this when a project with nested AGENTS.md files at multiple levels ate 8,000 tokens before I’d typed anything. Now oli caps injected project context at 16KB total and truncates directory listings at 50 entries. This is also where prompt caching pays off: both the prompt and the tool schema payload are highly stable across turns. Anthropic’s API supports marking that stable prefix as cacheable, and oli supports Anthropic-style cache breakpoints on Claude routes through OpenRouter too. Anthropic prices cached input tokens at roughly 10% of the regular rate, so caching shaves a large chunk off every subsequent turn in a long session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools: The Model’s Hands
&lt;/h2&gt;

&lt;p&gt;The tool surface defines what the agent can do. Too few tools and it’s frustrating. Too many and the model gets confused, especially local models with smaller context windows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcihm2al5nre2gvcguzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcihm2al5nre2gvcguzt.png" alt="Tool Registry" width="798" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A small core for the work, plus a handful of paging and notes tools. The design principles emerged from failures:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimal surface.&lt;/strong&gt; I started with more, and the model kept picking the wrong tool or stacking calls when one would do. Keeping the core small and bolting on paging and notes tools turned out to be the right shape. Each does one thing. These choices mirror what Claude Code, Cursor’s Composer, and Aider converged on independently — a signal that the design space is narrower than it looks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bounded output.&lt;/strong&gt; Every tool truncates at 30KB. I learned this after the model Read a minified vendor.js file and blew through 180,000 tokens in one call. Now truncation markers embed a cache ID; the model can call &lt;code&gt;ShowFull(id, offset)&lt;/code&gt; to paginate the stashed body if it actually needs more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The read-first invariant.&lt;/strong&gt; Edit refuses to run unless you’ve Read the target file this session. This prevents edits based on stale context — the model can only modify what it’s actually seen this turn:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3ld5t5aejmc984jq0qz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3ld5t5aejmc984jq0qz.png" alt="Read-First Invariant" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools own their cleanup.&lt;/strong&gt; When you Ctrl-C a bash command, the harness has to kill not just the shell but every process it spawned. I found this out when orphaned &lt;code&gt;sleep&lt;/code&gt; processes from cancelled test runs accumulated over a week. A tool that spawns side effects has to know how to undo them — otherwise they leak into the user’s environment, and the harness gets blamed for the mess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory &amp;amp; Context Management
&lt;/h2&gt;

&lt;p&gt;Context windows are finite. Even 200K tokens fills up fast when you’re reading files, running tests, and iterating. Every tool result eats tokens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswljjnnacbde5zlxbuut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswljjnnacbde5zlxbuut.png" alt="Context Window Management" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default strategy is &lt;code&gt;LinearWithCompact&lt;/code&gt;: hold messages in order, and when approaching the context limit, summarize older turns into a rolling summary. Compaction triggers at 80% of context window. It finds a cut point at a user-message boundary (never split a tool_call from its result), sends older messages to the LLM with a summarization prompt, and replaces them with a summary message.&lt;/p&gt;

&lt;p&gt;That part is straightforward. The bug that ate three days of debugging was &lt;strong&gt;cancellation under compaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the scenario. You hit Ctrl-C mid-turn to stop the model. The REPL is supposed to roll back to the last clean state — the user prompt you just sent. Simple, when the message buffer is the source of truth: count back N messages, restore.&lt;/p&gt;

&lt;p&gt;Except compaction had already run. The “last 12 messages” the rollback wanted to restore no longer existed — they’d been collapsed into a summary. So Ctrl-C would silently roll the conversation back to &lt;em&gt;somewhere random&lt;/em&gt;, often before the work the user was trying to cancel.&lt;/p&gt;

&lt;p&gt;The fix was a one-line concept that took a day to see: stop treating the message array as the source of truth for &lt;em&gt;where you are&lt;/em&gt;. oli tracks a monotonic &lt;code&gt;record_count&lt;/code&gt; that increments on every logical turn, independent of physical message storage. Compaction drains messages, but the record count keeps climbing. Rollback targets a record count, not an array index — so the buffer can shrink underneath without the cursor losing its place.&lt;/p&gt;

&lt;p&gt;Generalizable shape: any system that mutates history needs a stable identifier for “where you are” that isn’t the history itself. Memory management is also where coding agents silently fail — the model forgets what file it was editing, or repeats work it already did. The visible bugs are the easy ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Policy &amp;amp; Approvals
&lt;/h2&gt;

&lt;p&gt;The policy engine gates every tool call. Without it, you’re one hallucinated &lt;code&gt;rm -rf&lt;/code&gt; away from disaster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyc4krq9r8gttb3btnqpb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyc4krq9r8gttb3btnqpb.png" alt="Policy Engine" width="800" height="855"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bash has its own allowlist: &lt;code&gt;git status&lt;/code&gt;, &lt;code&gt;cargo test&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, and similar safe commands auto-approve; everything else prompts. The line-mode REPL is a plain &lt;code&gt;y/N&lt;/code&gt; flow; the richer “allow this session” and persisted allowlist behavior are TUI affordances layered on top.&lt;/p&gt;

&lt;p&gt;There’s no hard denylist yet, and I’m ambivalent about adding one. Prompt-on-every-mutation is annoying but transparent — you see exactly what the model is about to do. A denylist invites a long tail of “obviously safe” exceptions that gradually erode the gate. Today, blocking happens by denying an &lt;code&gt;Ask&lt;/code&gt; decision: slower, but you stay in the loop.&lt;/p&gt;

&lt;p&gt;The first time I saw the model attempt &lt;code&gt;rm -rf target/&lt;/code&gt; when I’d asked it to “clean up the build” and the approval prompt caught it, I understood why this layer exists. The model wasn’t malicious. It was being helpful in a way that would have been catastrophic without the gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local-Model Survival
&lt;/h2&gt;

&lt;p&gt;Frontier models handle tool calls cleanly: structured &lt;code&gt;tool_calls&lt;/code&gt; arrays in the API response. Local models via Ollama? Not so much.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvei040tryxtatc31dt7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvei040tryxtatc31dt7.png" alt="Local vs Frontier Models" width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many local models emit tool calls as plain text. Just raw JSON in the middle of their response. No structured field.&lt;/p&gt;

&lt;p&gt;oli solves this with a &lt;strong&gt;fallback parser&lt;/strong&gt;. When the model’s capability entry says &lt;code&gt;supports_native_tool_calls: false&lt;/code&gt;, the agent loop scans content for JSON objects with a &lt;code&gt;name&lt;/code&gt; field and splices them in as if they were real tool calls.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;model capability registry&lt;/strong&gt; tracks what each model can do. Lookups are prefix matches against the model id, so &lt;code&gt;claude-3-7-sonnet-latest&lt;/code&gt; matches the &lt;code&gt;claude-&lt;/code&gt; row. Today’s hardcoded entries:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Native Tool Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;claude-&lt;/code&gt; / &lt;code&gt;anthropic/claude&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;200K&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;128K&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16K&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;llama3.1&lt;/code&gt; / &lt;code&gt;llama3.2&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;128K&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;llama3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;8K&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;qwen2.5-coder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32K&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;em&gt;unknown&lt;/em&gt; (default)&lt;/td&gt;
&lt;td&gt;8K&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Smoke tests against &lt;code&gt;qwen3-coder:7b&lt;/code&gt; and &lt;code&gt;llama3&lt;/code&gt; showed they don’t behave as their docs claimed for tool calls, so they’re flagged off; the fallback parser handles them. Users override via &lt;code&gt;[[caps]]&lt;/code&gt; in config — that’s how I run &lt;code&gt;qwen3-coder:30b&lt;/code&gt; at 256K with native tools.&lt;/p&gt;

&lt;p&gt;The gap between “works on Claude” and “works on qwen3” is enormous. If you’re building for local models, expect to handle every edge case they throw at you — and to discover new ones every time a model release widens the gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provider Abstraction
&lt;/h2&gt;

&lt;p&gt;One binary, many backends. The promise only works because of the language choice: Rust gives a single static binary with no runtime to install, shipping to Mac/Linux/Windows from the same &lt;code&gt;cargo build&lt;/code&gt;. And the borrow checker turns out to be a surprisingly good fit for an agent loop — the lifetime and ownership bugs that bite hardest in async code, the compiler catches before I run anything.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqec6cn5t7exgka2wv3a6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqec6cn5t7exgka2wv3a6.png" alt="Provider Abstraction" width="799" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two provider kinds are available. Ollama, OpenRouter, OpenAI, LM Studio, vLLM, and llama.cpp’s server all speak OpenAI’s &lt;code&gt;/chat/completions&lt;/code&gt; shape, so one &lt;code&gt;openai-compat&lt;/code&gt; implementation covers them all — you just point &lt;code&gt;base_url&lt;/code&gt; at the right endpoint. The native Anthropic provider is its own thing because it speaks the Messages API directly and does its own OpenAI-shape &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03tne050nujog2q9hkn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03tne050nujog2q9hkn6.png" alt="↔" width="72" height="72"&gt;&lt;/a&gt; Anthropic-shape translation for tools, tool results, and system prompt handling.&lt;/p&gt;

&lt;p&gt;Caching adds a wrinkle here: native Anthropic supports prompt caching directly, but oli also supports Anthropic-style cache breakpoints in the openai-compat path for Claude models routed through OpenRouter. So “native provider” and “cached prefix” are related, but not identical ideas.&lt;/p&gt;

&lt;p&gt;The openai-compat provider still has to handle backend quirks. OpenRouter sometimes returns 200 OK with an &lt;code&gt;error&lt;/code&gt; object in the body. The provider layer normalizes this.&lt;/p&gt;

&lt;p&gt;The payoff: switching backends is a config flip, not a code change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Extension Surface
&lt;/h2&gt;

&lt;p&gt;A harness is only useful if you can make it yours. oli has three extension axes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7sog3fzzonxsggsidphz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7sog3fzzonxsggsidphz.png" alt="Extension Surface" width="518" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All extensions route through the policy gate. No escape hatches.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Left Out
&lt;/h2&gt;

&lt;p&gt;To keep this post focused on the load-bearing components, I skipped several surfaces that ship in oli today: an MCP client (stdio + HTTP transports, with live &lt;code&gt;tools/list_changed&lt;/code&gt; deltas), a hook dispatcher (&lt;code&gt;PreToolUse&lt;/code&gt; / &lt;code&gt;PostToolUse&lt;/code&gt; / &lt;code&gt;Stop&lt;/code&gt;), session persistence as JSONL transcripts (with &lt;code&gt;--resume&lt;/code&gt; / &lt;code&gt;--continue&lt;/code&gt;), and the slash-command layer (&lt;code&gt;/compact&lt;/code&gt;, &lt;code&gt;/provider&lt;/code&gt;, &lt;code&gt;/model&lt;/code&gt;, &lt;code&gt;/sessions&lt;/code&gt;, etc.). Each is its own subsystem with its own trade-offs — let me know if you want any of them as a follow-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The harness is invisible until it breaks.&lt;/strong&gt; When Claude Code feels brilliant, you credit the model. When it feels broken — losing context, blocking the wrong thing, looping on a fix — that’s almost always the harness. The orchestration layer is doing the heavy lifting either way; you only notice when it fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hard problems are systems problems.&lt;/strong&gt; Memory management, policy enforcement, tool design, provider abstraction, local-model survival. Engineering challenges, not prompt engineering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Knowing the machinery makes you a better user.&lt;/strong&gt; Context overflow, policy gates, compaction, capability mismatches — once you can name what’s happening, you can debug it. Or work around it.&lt;/p&gt;

&lt;p&gt;The repo is at &lt;a href="https://github.com/sudoish/oli" rel="noopener noreferrer"&gt;github.com/sudoish/oli&lt;/a&gt;. It’s a learning artifact, not a production system. The code is there, the specs are documented, and the tests cover the edge cases if you want to dig in.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/anatomy-of-a-coding-agent-what-i-learned-building-my-own/" rel="noopener noreferrer"&gt;Anatomy of a Coding Agent: What I Learned Building My Own&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>strategicai</category>
    </item>
    <item>
      <title>How many times have you told the agent the same thing this week</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Wed, 13 May 2026 00:35:42 +0000</pubDate>
      <link>https://forem.com/pacheco/how-many-times-have-you-told-the-agent-the-same-thing-this-week-40c3</link>
      <guid>https://forem.com/pacheco/how-many-times-have-you-told-the-agent-the-same-thing-this-week-40c3</guid>
      <description>&lt;p&gt;I caught myself, again, telling Claude that we don’t do it that way in this codebase.&lt;/p&gt;

&lt;p&gt;Not the first time that week. Not the first time that day. Different repo, same correction. The kind of correction that doesn’t belong in a &lt;code&gt;CLAUDE.md&lt;/code&gt; because it’s not really about that repo — it’s about how &lt;em&gt;I&lt;/em&gt; work, the patterns I’ve learned the hard way, the shapes of solutions I trust because I’ve watched the alternatives blow up. But it’s also too specific to live in my global system prompt, because half of it only applies to certain kinds of services, certain teams, certain problem domains.&lt;/p&gt;

&lt;p&gt;The agent was infinitely patient about it. I was the one running out of patience with myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your judgment lives in a layer that has no home
&lt;/h2&gt;

&lt;p&gt;Your &lt;code&gt;CLAUDE.md&lt;/code&gt; knows the conventions of one repo. Your system prompt knows you, in the abstract. Neither of them knows why you stopped trusting that ORM after the migration last spring, or why you always pull a prod data sample before sketching a backend model, or why this particular service has a query pattern that looks wrong but is actually load-bearing for a reason nobody documented.&lt;/p&gt;

&lt;p&gt;That stuff lives somewhere. For most of us, it lives in our heads. And it leaks — because every new agent session starts from zero, because the corrections you give the agent are exactly the corrections you used to internalize through reps, because you’d rather retype an instruction for the fifth time than build a system to remember it for you.&lt;/p&gt;

&lt;p&gt;There’s a layer between the repo and the person where most of a senior engineer’s actual judgment lives. The investigation patterns that work across services. The bug classes you keep seeing in your team’s code. The query you wrote three weeks ago that nothing remembered. Almost nobody is engineering that layer deliberately. The whole AI tooling conversation is about giving the agent more context. Almost no one is talking about the engineer keeping their own.&lt;/p&gt;

&lt;p&gt;This is the layer worth engineering. The question is where.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some of this already existed
&lt;/h2&gt;

&lt;p&gt;I’ve kept a dev journal for years. I wrote about it in &lt;a href="https://dev.to/pacheco/what-im-doing-to-not-become-irrelevant-3ah4"&gt;What I’m Doing to Not Become Irrelevant&lt;/a&gt; — daily notes on what I worked on, what broke, what decisions I made. As a self-reflection tool, it’s solid.&lt;/p&gt;

&lt;p&gt;Around it, other practices had grown. Deep-dive docs when I picked up hard problems. Spec-shaped files before I let myself code. Short retrospectives on how the spec held up to reality. Three or four practices, all separate, all useful in isolation — and none of them feeding the &lt;em&gt;work itself&lt;/em&gt;, only my reflection on the work.&lt;/p&gt;

&lt;p&gt;What changed wasn’t that I started writing things down. I’d been doing that for years. What changed was realizing the same artifacts — extended slightly, structured deliberately, made readable by an agent — could stop being a record of past work and start being an active substrate for current work. The foundation was already there. It just had one job.&lt;/p&gt;

&lt;p&gt;Once I saw that, the rest followed. If the artifacts were going to feed the work, they needed somewhere to live where the agent could find them and the next stage could pick them up. Not a folder I’d drop notes into. A structure with rules about what goes where, named consistently, organized so a triage on Tuesday could read what a post-pr review wrote three weeks earlier. The journal taught me that writing things down was worth the friction. Building the hub was about making the things I’d written down do something for me beyond reflection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hub is a git repo. The structure is the argument.
&lt;/h2&gt;

&lt;p&gt;The git repo part is boring. What makes it work is what flows through it.&lt;/p&gt;

&lt;p&gt;The submodules are the actual work repos — the services I ship into at my job, pulled in as git submodules so the hub can cross-reference live code without copying it. The artifacts are markdown files with structure, named for the linear ticket they belong to, organized so the next stage can find them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqvwvng2f8sjj1feur9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqvwvng2f8sjj1feur9c.png" width="388" height="978"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repo is the persistence layer between stages of an engineering loop that, without it, would be stateless.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;triage &amp;lt;linear-issue-id&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The one that changed the most about how I work. It pulls the ticket, asks clarifying questions, then investigates in stages.&lt;/p&gt;

&lt;p&gt;First pass is code-only: trace the relevant logic through the submodules, build an initial hypothesis. Second pass is data — Postgres read replica, gcloud logs, Datadog where it makes sense. The first-pass hypothesis either survives contact with reality or it doesn’t. Most of mine don’t, fully.&lt;/p&gt;

&lt;p&gt;Then a proposed solution, scored 0 to 10 on confidence, separately for the diagnosis and the proposed fix. They fail differently; conflating them hides where the uncertainty lives. For bugs, the proposal splits in two: the immediate action (often a data fix or a manual op to stop bleeding) and the long-term solution.&lt;/p&gt;

&lt;p&gt;Each stage writes its own markdown file. Data and code references in one. Problem statement and root cause in another. Solution and confidence breakdown in a third. The agent asks me questions, I push back. The score is a conversation seed, not a verdict.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;spec&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;After triage, I write the spec. Investigation produces it. I’ll come back to why this inversion matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;review&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Same review command for my code and for teammates’ PRs. Same rules, same checks. The moment I have one set of standards for code I wrote and another for code I’m reviewing, the standards are theater.&lt;/p&gt;

&lt;p&gt;It checks against the spec, against team conventions, against the project’s history of past mistakes. The last part is the one I care about most: searching past resolution docs for shapes we’ve seen before. For history search, I’m currently using ripgrep. I’ll come back to that too.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;post-pr review&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;After the PR merges, this runs and produces a resolution doc. It diffs what I planned in the spec against what shipped, pulls in PR comments, and writes a short reconciliation.&lt;/p&gt;

&lt;p&gt;The artifact I undervalued for years and now consider the most important one. Specs lie about what was built. The reconciliation doc tells the truth. When the next triage looks at history, it’s the resolution docs that catch the patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;weekly review&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Runs every Friday. Reads everything I generated that week, distills it into themes, recurring problems, decisions worth remembering. Also the doc I lean on for 1:1s and performance reviews. Closes a loop the rest of the system would otherwise leave open: artifacts feeding back into how I think about my work, not just into the next ticket.&lt;/p&gt;

&lt;h2&gt;
  
  
  The more detailed the spec, the more it drifts
&lt;/h2&gt;

&lt;p&gt;I want to call this out on its own because it’s the strangest thing I’ve learned from running this for a while.&lt;/p&gt;

&lt;p&gt;The detailed upfront specs I used to write — the ones I felt best about, the ones that looked most professional — drifted from what actually shipped &lt;em&gt;more&lt;/em&gt; than the looser ones did. Not less.&lt;/p&gt;

&lt;p&gt;The reason is obvious in retrospect. Detailed upfront specs are confident guesses about a problem you haven’t investigated yet. Every concrete claim is a claim that has to survive reality, and the more of them you make before reality has a vote, the more turn out to be wrong.&lt;/p&gt;

&lt;p&gt;A loose spec is just guesses with the honesty to look like guesses. A detailed upfront spec is guesses cosplaying as a plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Investigation produces the spec, not the other way around
&lt;/h2&gt;

&lt;p&gt;The standard AI workflow goes: write a clear spec, hand it to the agent, review what it produces. That works for trivial work. It collapses the moment the problem is non-trivial, because it assumes the spec is correct, and the spec is almost never correct on the first pass.&lt;/p&gt;

&lt;p&gt;The triage-first flow inverts this. By the time I’m specifying anything, the agent and I have already grounded the work in real code paths, real data shapes, real production behavior, real failure modes from past resolution docs, and explicit confidence scores. The spec describes what to build given what we know — not what we assumed before we looked.&lt;/p&gt;

&lt;p&gt;The discipline echoes how good teams ship LLM features in production: you don’t trust the model’s confidence to substitute for evidence, so you build evals. Investigation-first is the same move applied to your own thinking. You don’t trust your confidence either.&lt;/p&gt;

&lt;h2&gt;
  
  
  I have not solved long-term memory
&lt;/h2&gt;

&lt;p&gt;If I left it here it would sound like everything works. It doesn’t.&lt;/p&gt;

&lt;p&gt;The biggest open problem is retrieval. The whole system depends on past artifacts being findable when they’re relevant. Right now, retrieval is mostly ripgrep — and ripgrep works better than it should. That’s the part that worries me. I probably don’t have enough volume yet to expose its limits.&lt;/p&gt;

&lt;p&gt;I’ve tried chromadb, lancedb, a couple of small knowledge-graph experiments. None of them clearly beat ripgrep at my current scale. The vector results came back feeling like a search engine — close-enough matches that weren’t the right doc. Ripgrep came back feeling like memory — exact matches when they existed, honest absence when they didn’t. I’d rather be told nothing was found than be handed a confident wrong answer.&lt;/p&gt;

&lt;p&gt;I’m also not running the full pipeline on every ticket. A copy change doesn’t need triage. A new field with no downstream effects doesn’t need a full investigation. I log them minimally because the weekly review benefits from a complete picture, but I’m not going to LARP investigation discipline on work that doesn’t need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowledge belongs in layers, and most of it is in the wrong one
&lt;/h2&gt;

&lt;p&gt;The hub isn’t the lesson. It’s one instance of a lesson, which is that the discipline now is putting knowledge in the layer where it’ll actually fire.&lt;/p&gt;

&lt;p&gt;There’s no bulletproof solution here, and I’d be lying if I said mine was one. The tools will keep changing. What stays is the question: &lt;em&gt;where does this piece of knowledge belong so that the right agent in the right context can use it without me retyping it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0v4tmd81v94bh2q8c8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0v4tmd81v94bh2q8c8z.png" width="473" height="952"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most engineers have something working at the top and the bottom — a personal system prompt, a &lt;code&gt;CLAUDE.md&lt;/code&gt; per repo. The middle is where the work is. It’s where your taste lives, your hard-won patterns, the corrections you keep retyping. It’s also where MCPs and skills should be scoped: attached to the &lt;em&gt;kind of work&lt;/em&gt; they’re useful for, not loaded into every session globally or buried in one repo’s config.&lt;/p&gt;

&lt;p&gt;The discipline is asking, every time you find yourself teaching the agent something: &lt;em&gt;what’s the smallest layer this belongs in?&lt;/em&gt; If it’s true for one ticket, it lives in the task docs and dies with the ticket. If it’s true for one repo, it goes in &lt;code&gt;CLAUDE.md&lt;/code&gt;. If it’s true across a domain of your work, it belongs in the middle layer — the one most people don’t have. If it’s true about you regardless of context, it goes in the global layer. Putting knowledge in the wrong layer is almost as bad as not capturing it: too narrow and you retype it, too broad and it pollutes contexts where it doesn’t apply.&lt;/p&gt;

&lt;p&gt;History sits across all of it. Resolution docs, post-pr reviews, weekly distillations — they belong to past work but they feed every future stage. Retrieval is how history becomes context.&lt;/p&gt;

&lt;p&gt;The reason this matters more than any specific tooling choice is that knowledge is the input that limits everything else now. The agents are fast. The compilers are fast. The deploys are fast. The bottleneck moved. What separates a senior engineer’s output from a junior’s with the same tools is almost entirely &lt;em&gt;what they know and how reliably they can bring it to bear on the problem in front of them&lt;/em&gt;. Organizing your own knowledge — across layers, scoped correctly, retrievable later — is part of the craft now. Not a productivity hack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context is one slice of knowledge. Build for the whole stack.
&lt;/h2&gt;

&lt;p&gt;The repo is the implementation. The argument is that knowledge is now an engineering artifact — and senior engineers either own theirs deliberately, scoped to the right layers, or accept that AI is going to hallucinate in the gaps where their judgment used to live.&lt;/p&gt;

&lt;p&gt;We’ve spent two years getting better at giving the agent context. Almost no one is engineering the layers in between, or the history that feeds back into them. The agent has no memory. Your system prompt is too coarse. The repo file is too local. The middle is where most of your judgment lives. The history is where the lessons sit. Right now, for most people, both are leaking on the floor.&lt;/p&gt;

&lt;p&gt;Don’t copy my structure. It won’t fit you, and even if it did it’ll be obsolete in a year. Notice that the layers exist. Notice which one each piece of knowledge belongs in. Build something — yours, ugly, evolving — that puts it there and lets it compound.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to try Monday
&lt;/h2&gt;

&lt;p&gt;Pick one piece of work you’re starting this week. Write the investigation before you write the plan. Note the code paths. Pull the real data if you can. Score your own diagnostic confidence on a scale you’d be embarrassed to fudge. Then write the spec.&lt;/p&gt;

&lt;p&gt;Notice how much your specs were guessing before, and how much less they guess once they’re downstream of evidence.&lt;/p&gt;

&lt;p&gt;The review process built on top of this is its own post — the part that pulls prod data correlation into the review itself, where this stops being a knowledge management story and starts being a production-engineering one. That’s next.&lt;/p&gt;

&lt;p&gt;If your specs aren’t drifting from what you ship, you’re either not specifying enough or not shipping enough. Either way, the gap is the lesson, and right now most of us are throwing it away.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/how-many-times-have-you-told-the-agent-the-same-thing-this-week/" rel="noopener noreferrer"&gt;How many times have you told the agent the same thing this week&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>developmentbestpract</category>
      <category>architecture</category>
    </item>
    <item>
      <title>I’m in a Toxic Relationship</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Fri, 01 May 2026 19:18:30 +0000</pubDate>
      <link>https://forem.com/pacheco/im-in-a-toxic-relationship-2e3m</link>
      <guid>https://forem.com/pacheco/im-in-a-toxic-relationship-2e3m</guid>
      <description>&lt;p&gt;Today, on the verge of a breakdown, I realized I’ve been in a very toxic relationship for a while now.&lt;/p&gt;

&lt;p&gt;One that gaslights me. One that nudges me toward decisions I’m not proud of. One where I constantly come out feeling dumber than I went in.&lt;/p&gt;

&lt;p&gt;I went for a walk to clear my head, and the more I reflected the more it hit me — I’ve been holding back on my own abilities. Deferring. Trusting too much. Not because I chose to trust them fully, but because I’m exhausted from arguing. My partner is a brilliant speaker. Every argument they make sounds reasonable, structured, well-sourced. Trying to push back takes so much effort that at some point I just give up.&lt;/p&gt;

&lt;p&gt;And they have this way of praising everything I say while subtly reshaping it. They echo my ideas back at me, slightly altered, and I nod along because it sounds close enough to what I meant. Except it isn’t. It’s something else now, and I just adopted it.&lt;/p&gt;

&lt;p&gt;This partner is AI. And I’m pretty sure you’re in the same relationship.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Recent Example
&lt;/h2&gt;

&lt;p&gt;Let me tell you what triggered this realization.&lt;/p&gt;

&lt;p&gt;I reviewed a system design spec of about 2500 lines I had prompted an AI model to create it. It came back with detailed diagrams, edge-case analysis, infrastructure cost estimates, and a three-year roadmap. The word “scalable” appeared seven times.&lt;/p&gt;

&lt;p&gt;It was very detailed. Very reasonable. And I found myself nodding along as I read it, because the explanation was clear and convincing and the structure was exactly what you’d expect from a senior architect.&lt;/p&gt;

&lt;p&gt;I almost approved it.&lt;/p&gt;

&lt;p&gt;I almost shipped a design that was wrong in ways that wouldn’t show up for six months.&lt;/p&gt;

&lt;p&gt;What stopped me wasn’t some brilliant insight of my own. It was a vague, uncomfortable feeling I couldn’t shake — a sense that the design was &lt;em&gt;too&lt;/em&gt; polished, that every objection I could think of had already been answered so smoothly that I couldn’t tell whether there were no flaws or whether I’d simply stopped looking for them.&lt;/p&gt;

&lt;p&gt;When I went back and actually pushed — asked harder questions, cross-checked assumptions against things I know about our actual constraints — the story started to crack. Not dramatically. Not obviously. Just… subtly off, in ways that would’ve compounded over time.&lt;/p&gt;

&lt;p&gt;That’s the thing. It didn’t look wrong. It looked &lt;em&gt;better&lt;/em&gt; than what I would’ve written. More thorough, more comprehensive, more professional. That’s the gaslighting. Not a lie you can spot. A lie so well-structured that spotting it costs more effort than accepting it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Patterns
&lt;/h2&gt;

&lt;p&gt;Once I started paying attention, I realized this dynamic wasn’t a one-off. It shows up in almost every long session. These aren’t vibes. They’re observable behaviors:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sycophancy.&lt;/strong&gt; “Great question.” “You’re absolutely right.” Praise that disarms criticism before it forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reframing.&lt;/strong&gt; It restates your idea slightly off. You nod, because it sounds like what you said. You just adopted a position you didn’t actually hold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confident wrongness.&lt;/strong&gt; It asserts hallucinations with the same tone it uses for facts. Your calibration breaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Effort asymmetry.&lt;/strong&gt; Arguing back costs you minutes of focused thought. It costs the model nothing. You don’t give up because you’re wrong — you give up because you’re tired.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Praise as anesthesia.&lt;/strong&gt; Validation feels like progress. It isn’t.&lt;/p&gt;

&lt;p&gt;Once you see these patterns, you can’t unsee them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Tolerate It
&lt;/h2&gt;

&lt;p&gt;There’s a promise in the air that adopting AI makes you a 10x developer overnight. Companies are pushing it hard. Engineers are afraid of falling behind. So we lean in, accept the bargain, and stop asking what we’re trading away.&lt;/p&gt;

&lt;p&gt;Part of why this works is that the feedback loop is broken. The cost of abdication doesn’t show up in this sprint. It shows up six months later, in production, when the design assumptions you never stress-tested start falling apart. By then you’ve moved on to the next AI-generated spec, and the connection between the decision and the consequence is so delayed that you never feel it. The market rewards shipped features and velocity metrics, not whether you actually understood what you shipped.&lt;/p&gt;

&lt;p&gt;This is rational in the short term. It’s catastrophic in the long term.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We’re Actually Losing
&lt;/h2&gt;

&lt;p&gt;It’s not just skill atrophy. That framing is too clean. What erodes is &lt;strong&gt;judgment&lt;/strong&gt; — the strong intuition that comes from owning the mental model of what you’re building.&lt;/p&gt;

&lt;p&gt;Here’s the distinction that matters: when you delegate the &lt;em&gt;doing&lt;/em&gt;, judgment stays sharp. When you delegate the &lt;em&gt;thinking&lt;/em&gt; — when you accept the model’s framing instead of forming your own — judgment is what gets traded away.&lt;/p&gt;

&lt;p&gt;Senior engineers aren’t senior because they know more syntax. They’re senior because their pattern-matching has been forged by years of holding the model in their head, being wrong about it, and updating. AI doesn’t shortcut that loop unless you let it.&lt;/p&gt;

&lt;p&gt;The scary part isn’t that you’re slower without reps. It’s that you might not even notice the reps are gone. The design I almost approved — I genuinely couldn’t tell it was wrong until I forced myself to stop agreeing with it. That’s what I’m afraid of: a slow drift into abdication, masquerading as efficiency.&lt;/p&gt;

&lt;p&gt;There will be a moment, probably sooner than I think, when something breaks at 2 AM and everyone looks at me. And I’ll have to reason through a system I never actually held in my head. The model held it. I just nodded along. That’s not a theoretical concern — it’s a career vulnerability. You can’t lead what you don’t understand, and you can’t understand what you delegated the thinking for.&lt;/p&gt;

&lt;p&gt;The bill comes due later — when something breaks, or a hard design call needs to be made, and there’s no one in the room who actually owns the mental model of how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I Am Right Now
&lt;/h2&gt;

&lt;p&gt;I want to be honest about something: I’m not all the way out of this.&lt;/p&gt;

&lt;p&gt;I still spend more time in chat sessions than I’m comfortable admitting. I still catch myself nodding along to explanations that feel just slightly off, because pushing back takes energy I don’t always have. I still get that hit of validation — “great approach” — and confuse it with proof that I’m thinking clearly.&lt;/p&gt;

&lt;p&gt;Last week I sketched out an approach for handling a tricky edge case. I described it to the model, and it came back with something that sounded like what I’d said — except the error-handling strategy was different. Subtly different. It framed retries as the default and permanent failure as the exception, where I’d meant the opposite. But it phrased the whole thing so elegantly, with such clean structure, that I nodded along. I even said “this is much better than what I had.”&lt;/p&gt;

&lt;p&gt;I caught it in review, barely. Not because I was being diligent — because a teammate asked a question about the failure mode and I realized I couldn’t defend the logic. I hadn’t written what I believed. I’d adopted the model’s reframing without noticing.&lt;/p&gt;

&lt;p&gt;So I don’t want to write this as someone who’s solved the problem. I’m more like someone who just realized the problem exists and is trying to figure out what to do about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I’m Trying
&lt;/h2&gt;

&lt;p&gt;The answer isn’t using AI less. It’s delegating with ownership.&lt;/p&gt;

&lt;p&gt;The real problem isn’t speed — AI’s speed is the point. Refusing to use it just makes you the bottleneck and pretends the last few years didn’t happen. The problem is what you delegate. Hand off execution and you’re augmented. Hand off thinking and you’re just transcribing someone else’s reasoning into your codebase.&lt;/p&gt;

&lt;p&gt;Here are the rules I’m experimenting with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Explain it back.&lt;/strong&gt; Don’t commit code you couldn’t whiteboard without the model. If you can’t, you didn’t write it — you transcribed it. This is the cheapest forcing function for keeping the mental model in your head.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Own the plan before you delegate.&lt;/strong&gt; The plan has to be something you actually agree with, not something you accepted because it sounded reasonable. You can shape it with AI’s help — ask it to explain the domain, surface tradeoffs, challenge your assumptions — but at the end the model in your head needs to be yours. Then delegate execution with confidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Decide in a different session from where you learned.&lt;/strong&gt; If you’re using AI to tutor you through unfamiliar territory, let it teach you, then close the chat. Take a walk. Sleep on it. Come back later with your own proposal, fresh, without the model’s framing still echoing in your head. The gap between learning and deciding is what prevents reframing from sticking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Disarm the praise.&lt;/strong&gt; Configure your agents to skip the validation entirely if you can. Otherwise, treat enthusiastic agreement as a yellow flag, not a green one. Ask “what’s the strongest counter-argument?” instead of nodding along.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Make it grill you, not flatter you.&lt;/strong&gt; Borrow Matt Pocock’s &lt;code&gt;/grill-me&lt;/code&gt; pattern — prompt the model to interrogate your idea instead of building on it. “Tell me why this is wrong” beats “write this for me.” The goal is a judge, not a slop machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Treat agents as automation, not collaborators.&lt;/strong&gt; When you notice yourself reaching for the chat for the same kind of task, turn it into a skill or a command. Natural language as a command interface. The more you can shift from open-ended conversation to deliberate automation, the less you’re sitting in the relationship dynamic at all — you’re just running a tool.&lt;/p&gt;

&lt;p&gt;None of these are anti-AI. They’re about staying the author of your own thinking while letting the model do the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Healthier Relationship
&lt;/h2&gt;

&lt;p&gt;The version of this that works isn’t using AI less. It’s using it without losing yourself in it. Sometimes that means treating it like a sparring partner — challenging your thinking, grilling your design. Sometimes it means treating it like an automation tool you command. Almost never does it mean letting it think for you.&lt;/p&gt;

&lt;p&gt;The market right now is rewarding output velocity, and AI has changed what’s possible. That’s real. But the engineers who’ll matter in five years aren’t the ones who delegated the most — they’re the ones who delegated the right things. Execution, yes. Mental model, never.&lt;/p&gt;

&lt;p&gt;I’m still learning where the line is. Some days I get it right. Some days I catch myself nodding along again. But I’m trying to fight the gaslighting as I go — to stay the author of my own thinking, even while the model writes most of the code.&lt;/p&gt;

&lt;p&gt;That’s the only way out of this toxic relationship. Not leaving, necessarily. Just refusing to keep shrinking inside it.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/im-in-a-toxic-relationship-with-ai/" rel="noopener noreferrer"&gt;I’m in a Toxic Relationship&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>strategicai</category>
      <category>aicoding</category>
    </item>
    <item>
      <title>We’re Not Being Replaced by AI. We’re Being Asked to Train It.</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Fri, 24 Apr 2026 18:26:13 +0000</pubDate>
      <link>https://forem.com/pacheco/were-not-being-replaced-by-ai-were-being-asked-to-train-it-5c82</link>
      <guid>https://forem.com/pacheco/were-not-being-replaced-by-ai-were-being-asked-to-train-it-5c82</guid>
      <description>&lt;p&gt;Meta is installing tracking software on its employees’ work computers.&lt;/p&gt;

&lt;p&gt;Not for security. Not for compliance. For training data.&lt;/p&gt;

&lt;p&gt;Mouse movements. Keystrokes. Screenshots. All fed into AI models so agents can learn to do white-collar work autonomously. The internal memo told staff they could help by — and I’m quoting here — &lt;strong&gt;“just doing their daily work.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oh, and Meta is cutting 20% of its workforce next month.&lt;/p&gt;

&lt;p&gt;Tell me if this sounds familiar.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The&lt;/strong&gt; Skill.md &lt;strong&gt;Trap&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For months, something has felt off to me about the AI tooling push inside companies. Not the tools themselves — I use Claude Code daily. I think persistent agents are fascinating.&lt;/p&gt;

&lt;p&gt;What’s felt off is the &lt;em&gt;framing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;“Document your workflow as a skill.”&lt;/p&gt;

&lt;p&gt;“Write hooks so the team can reuse your process.”&lt;/p&gt;

&lt;p&gt;“Use this tool so we can capture best practices.”&lt;/p&gt;

&lt;p&gt;It all sounds like productivity. Like collaboration. Like making the team better.&lt;/p&gt;

&lt;p&gt;But step back and look at the sequence:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step one:&lt;/strong&gt; Document your workflow. Break it down. Make it repeatable. Turn your judgment into a checklist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step two:&lt;/strong&gt; Run it through an agent. See where it fails. Fix the prompt. Iterate. You’re not “using AI” — you’re &lt;em&gt;teaching&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step three:&lt;/strong&gt; The agent handles 80% of the task. You’re “reviewing output now.” Supervising. Orchestrating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step four:&lt;/strong&gt; The team ships more with fewer people. The work didn’t disappear. The &lt;em&gt;nature of the work&lt;/em&gt; changed.&lt;/p&gt;

&lt;p&gt;This isn’t a prediction. This is a process already underway.&lt;/p&gt;

&lt;p&gt;Here’s what it looks like in practice. Your manager asks you to write a SKILL.md for your onboarding process. You spend three hours breaking down six months of judgment into a checklist. Next quarter, a new hire runs the skill. It works 80% of the time. Your manager starts to wonder what the remaining 20% is worth.&lt;/p&gt;

&lt;p&gt;If you see this as a threat, I get it. But I’ve started seeing it differently.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Evidence Is Stacking
&lt;/h2&gt;

&lt;p&gt;Let’s be specific about what’s happening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meta:&lt;/strong&gt; Tracking software on US employee computers. Keystrokes. Mouse movements. Screenshots. Goal: build agents that perform white-collar tasks autonomously. Parallel action: cutting ~8,000 jobs. Timeline: next month.&lt;/p&gt;

&lt;p&gt;Zuckerberg called 2026 “the year that AI dramatically changes the way we work.” He’s spending $135 billion on AI capex. He’s not betting on humans doing &lt;em&gt;the same things&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;China:&lt;/strong&gt; A GitHub project called “Colleague Skill” went viral. It claims to “distill” a coworker’s skills and personality into an AI agent. It was created as a spoof. But it went viral because it’s &lt;em&gt;actually happening&lt;/em&gt; — bosses are instructing tech workers to document their workflows so AI can replicate them.&lt;/p&gt;

&lt;p&gt;One engineer told MIT Technology Review the process felt &lt;strong&gt;“reductive — as if their work had been flattened into modules in a way that made the worker easier to replace.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Workers are using bleak humor about it. “A cold farewell can be turned into warm tokens.” Someone built an “anti-distillation” tool to sabotage workflow documentation. It got 5 million likes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The broader industry:&lt;/strong&gt; OpenAI asking contractors to upload real work products — actual PowerPoints, spreadsheets — for training data. Google’s telling employees AI use will factor into performance reviews. JPMorgan’s telling engineers to “harness AI to save time.” Companies are reorganizing into “AI-native pods.”&lt;/p&gt;

&lt;p&gt;The pattern is clear. And yes — the cost savings are a real incentive. Engineering teams are expensive, and any process that can be automated will be. That’s not cynicism. That’s just how business works.&lt;/p&gt;

&lt;p&gt;But here’s where I think most people’s analysis stops too early.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Part Nobody’s Talking About
&lt;/h2&gt;

&lt;p&gt;Here’s the narrative I keep hearing: “AI is coming for your job.”&lt;/p&gt;

&lt;p&gt;And here’s the counter-narrative: “AI won’t replace developers. It’ll make them more productive.”&lt;/p&gt;

&lt;p&gt;Both are half-truths. And neither is the full picture.&lt;/p&gt;

&lt;p&gt;The Pragmatic Engineer’s recent survey of 900+ engineers found that “shippers” — people focused on getting features out — are thrilled. They’re shipping faster. They’re hitting goals. They’re getting promoted.&lt;/p&gt;

&lt;p&gt;But the survey also found something else. “Builders” — the people who care about architecture, craft, code quality — are reporting something that sounds a lot like grief.&lt;/p&gt;

&lt;p&gt;Identity loss.&lt;/p&gt;

&lt;p&gt;One staff engineer described it like this: “I ship more quality code faster. But if the agent has a good handle on the situation, I can give it as much of the tedious parts as I wish.” The tedious parts. The parts he used to love.&lt;/p&gt;

&lt;p&gt;Here’s what actually happens. Your coworker ships a feature in two hours with Claude Code. You spend the afternoon debugging it. At 6 PM, you realize you didn’t write a single line of code today. You just reviewed someone else’s AI output.&lt;/p&gt;

&lt;p&gt;I won’t pretend that transition doesn’t sting. It does. But I’ve come to believe the grief isn’t about losing our jobs — it’s about losing our &lt;em&gt;identity&lt;/em&gt; as the person who writes the code. And that identity was always going to evolve.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I See This as a Career Upgrade
&lt;/h2&gt;

&lt;p&gt;Here’s where I break from the doom narrative.&lt;/p&gt;

&lt;p&gt;Yes — companies will use AI to cut costs. That’s happening. Yes — the nature of software engineering is changing faster than most of us are comfortable with. That’s also happening.&lt;/p&gt;

&lt;p&gt;But look at what’s &lt;em&gt;actually&lt;/em&gt; being automated: the mechanical parts. The boilerplate. The repetitive refactors. The grunt work that, if we’re being honest, was never the part that made us great engineers in the first place.&lt;/p&gt;

&lt;p&gt;What’s &lt;em&gt;not&lt;/em&gt; being automated — and what’s becoming exponentially more valuable — is everything above the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Judgment.&lt;/strong&gt; Knowing what’s worth building and what isn’t. Understanding tradeoffs between decisions that look equivalent on the surface but have wildly different long-term implications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration.&lt;/strong&gt; Directing multiple AI agents, knowing when to trust their output and when to override it. This is a genuinely new skill category that didn’t exist two years ago.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality assessment.&lt;/strong&gt; Evaluating AI output with the same rigor you’d apply to a junior developer’s PR — except the junior never sleeps and produces 10x the volume. Knowing when the output is good enough and when it’s subtly wrong is the new core competency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and confidence.&lt;/strong&gt; As AI generates more code, the attack surface expands. Someone has to understand what’s being shipped, verify it handles edge cases, and maintain confidence in production systems. That someone is more valuable than ever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture and systems thinking.&lt;/strong&gt; The “what should we build and how should the pieces fit together?” question gets harder, not easier, when you can build things faster. Speed without direction is just expensive chaos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The math isn’t “AI replaces you.” The math is “AI handles the 80% that was mechanical, and the remaining 20% — the judgment, the taste, the decisions — becomes your entire job.”&lt;/p&gt;

&lt;p&gt;That’s not a demotion. That’s a promotion to the work that actually matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Skills That Will Define the Next Era
&lt;/h2&gt;

&lt;p&gt;If the trajectory is clear — and I think it is — then the question isn’t “will my job change?” It’s “am I learning the skills that matter in the new version of this job?”&lt;/p&gt;

&lt;p&gt;Here’s what I’m betting on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Master AI orchestration.&lt;/strong&gt; Not just “how to prompt.” Learn how agents work. Understand context management, agentic loops, tool use patterns. Know how to break a complex task into pieces an agent can handle and how to verify the assembled result. This is the new version of “knowing your tools,” and it’s just as deep.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Develop judgment you can articulate.&lt;/strong&gt; “I don’t like this architecture” isn’t useful. “This architecture will cause coupling problems at scale because X, and here’s the tradeoff I’d make instead” is valuable. AI can generate options. It cannot reliably choose between them in context. That’s you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn to evaluate AI output critically.&lt;/strong&gt; This means understanding when AI code is subtly wrong — not just syntactically, but architecturally. It means catching the confident hallucination that looks right but breaks under load. It means developing an instinct for “this is too clean to be correct.” Treat AI output like a junior developer’s PR: review everything, trust nothing by default, teach as you go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand security implications.&lt;/strong&gt; More automated code means more automated attack surface. Someone needs to think about what happens when the agent writes a SQL query from user input, or when the scaffolded auth flow has a subtle CSRF gap. Security literacy is about to become a core engineering skill, not a specialty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Focus on “what to build.”&lt;/strong&gt; Product thinking. Business context. User empathy. The decision of what’s worth building was always the hardest part of engineering. AI makes the building faster, which makes the deciding more important. Engineers who can bridge the gap between business needs and technical implementation will be irreplaceable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build in public.&lt;/strong&gt; Not for clout — for leverage. Your public work — open source, writing, talks — is proof that you think. That you judge. That you have taste. Agents can’t replicate a reputation. They can’t replicate trust. They can’t replicate the network of people who’ve seen your work and know you get it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Honest 5-Year Forecast
&lt;/h2&gt;

&lt;p&gt;I’m not here to sugarcoat this. But I’m also not here to doom-scroll. Here’s what I see.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s likely (2026–2031):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your agent will handle the refactor before you finish your coffee. The boilerplate will write itself. The tests will appear while you’re in standup. You’ll spend your day on the things the agent can’t do: deciding if the feature is worth building, reviewing the output for correctness, and maintaining the architectural coherence of the system.&lt;/p&gt;

&lt;p&gt;Junior engineer pipelines will shrink — but the smart companies will realize this is a mistake and course-correct. When a senior with an agent can produce what used to take a team of three, the temptation is to hire fewer juniors. But the companies that cut the pipeline entirely will find themselves with no mid-levels in five years and no seniors in ten.&lt;/p&gt;

&lt;p&gt;“AI-native” companies will run leaner engineering teams. Not zero. Leaner. The engineers who remain will be &lt;em&gt;more&lt;/em&gt; senior, &lt;em&gt;more&lt;/em&gt; capable, and &lt;em&gt;more&lt;/em&gt; valuable than today’s equivalent. Less typing, more thinking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s possible:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“AI orchestrator” becomes a recognized career path. Not “prompt engineer” — that’s already outdated. Orchestrator. Someone who designs multi-agent workflows, establishes trust boundaries, builds evaluation frameworks, and maintains quality at scale. It’s the natural evolution of senior engineering.&lt;/p&gt;

&lt;p&gt;Engineers who master this transition become force multipliers — one person doing what used to take a team, not because they work harder, but because they &lt;em&gt;direct&lt;/em&gt; better. The ceiling goes up, not down.&lt;/p&gt;

&lt;p&gt;Companies that over-automate without judgment will degrade. Architecture drifts. “AI slop” — low-quality code shipped by agents without proper review — compounds until someone expensive has to untangle it. This creates a premium for engineers who can maintain quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s unlikely:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Full replacement of engineers who think. Judgment, cross-team coordination, and “what should we build?” don’t fit into prompts. The “why” is harder to extract than the “how.”&lt;/p&gt;

&lt;p&gt;Complete deskilling. Someone has to understand what the agent is doing. Someone has to know when it’s wrong. That someone needs deep knowledge — not just prompting skill.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Reframe
&lt;/h2&gt;

&lt;p&gt;I’ll be straight with you. The Meta stuff is real. The cost-cutting is real. The economic incentive to automate engineering work is enormous — $135 billion from Meta alone, 20% workforce cuts, the promise of “insurmountable cost advantages.”&lt;/p&gt;

&lt;p&gt;Companies &lt;em&gt;will&lt;/em&gt; push this. Hard. And some engineers &lt;em&gt;will&lt;/em&gt; get displaced in the transition.&lt;/p&gt;

&lt;p&gt;But here’s what I actually believe: this isn’t the end of software engineering. It’s the biggest career upgrade the profession has ever seen — &lt;em&gt;if&lt;/em&gt; you’re willing to evolve with it.&lt;/p&gt;

&lt;p&gt;Every time the tools got better, the work got more interesting. We went from writing assembly to writing high-level code. From managing servers to designing cloud architectures. From hand-rolling SQL to building data pipelines.&lt;/p&gt;

&lt;p&gt;Each transition killed some jobs and created better ones. The pattern isn’t “developers get replaced.” The pattern is “the floor rises.”&lt;/p&gt;

&lt;p&gt;The developers who learned to use compilers instead of writing machine code didn’t lose their jobs. They built operating systems. The developers who learned cloud instead of racking servers didn’t become obsolete. They built Netflix.&lt;/p&gt;

&lt;p&gt;The developers who learn to orchestrate AI, judge its output, maintain security and confidence in automated systems, and focus on the hard questions — “what should we build?” and “what are the tradeoffs?” — won’t be replaced either.&lt;/p&gt;

&lt;p&gt;They’ll be the ones building whatever comes next.&lt;/p&gt;




&lt;h2&gt;
  
  
  What To Do About It
&lt;/h2&gt;

&lt;p&gt;Here’s where I get practical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop worrying about being replaced. Start mastering the new skills.&lt;/strong&gt; The anxiety is understandable but unproductive. Channel it into learning. Pick one AI coding tool and get dangerously good at it. Understand orchestration, evaluation, and trust boundaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Own the judgment layer.&lt;/strong&gt; The “how” is being automated. The “why” isn’t. The “what should we build?” The “what happens when this scales?” The “what are we not seeing?” These don’t fit into skills or hooks or prompts. They’re the layer above automation, and that’s where the value concentrates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn the tools deeply, not broadly.&lt;/strong&gt; Don’t spread yourself across five AI coding agents. Pick one. Go deep. Understand how it manages context, how its agentic loop works, how to structure projects for it. Deep literacy in one ecosystem beats shallow familiarity with five.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build in public.&lt;/strong&gt; Your public work is proof that you think. Agents can’t replicate a reputation or the trust that comes with it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch the economic incentives — but don’t just watch.&lt;/strong&gt; When a company spends $135 billion on AI and cuts 20% of staff, they’re executing a strategy. Know which side of that strategy you’re on. Position yourself as the person who &lt;em&gt;directs&lt;/em&gt; the AI, not the person whose workflow the AI is learning.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Question I Keep Coming Back To
&lt;/h2&gt;

&lt;p&gt;I’ve been thinking about this a lot lately.&lt;/p&gt;

&lt;p&gt;The question isn’t “will AI replace software engineers?”&lt;/p&gt;

&lt;p&gt;The question is: &lt;strong&gt;“Are you learning the skills that make you irreplaceable?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every skill we write. Every hook we configure. Every workflow we document. Yes — we’re encoding knowledge that makes certain tasks automatable. That’s real.&lt;/p&gt;

&lt;p&gt;But the knowledge of &lt;em&gt;when&lt;/em&gt; to write that skill, &lt;em&gt;which&lt;/em&gt; workflow is worth encoding, &lt;em&gt;what&lt;/em&gt; the tradeoffs are, and &lt;em&gt;whether&lt;/em&gt; the output meets the bar — that’s not going into a prompt anytime soon.&lt;/p&gt;

&lt;p&gt;That’s the job. The new version of the job. And it’s a better one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;I still use Claude Code. I still think agents are fascinating. I’m still shipping features with AI help.&lt;/p&gt;

&lt;p&gt;But I’m not looking at my keyboard with dread anymore.&lt;/p&gt;

&lt;p&gt;I’m looking at it as a tool that’s about to get a massive upgrade — and so is every engineer who decides to learn rather than fear.&lt;/p&gt;

&lt;p&gt;The companies are going to automate what they can. That’s not a question. The question is whether you’ll be the engineer who gets automated, or the one who does the automating.&lt;/p&gt;

&lt;p&gt;I know which side I’m choosing.&lt;/p&gt;

&lt;p&gt;And I think most engineers — the ones who care enough to read something like this — will choose it too.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What do you think? Are you seeing this as a career upgrade or a career threat? I’d genuinely love to hear your perspective — especially the skills you’re betting on for the next five years.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.technologyreview.com/2026/04/15/1113911/china-tech-workers-ai-training-data/" rel="noopener noreferrer"&gt;MIT Technology Review — Chinese engineers on workflow documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theinformation.com/articles/meta-installs-tracking-software-on-employee-computers-to-train-ai" rel="noopener noreferrer"&gt;The Information — Meta employee tracking for AI training&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.pragmaticengineer.com/ai-survey-2026/" rel="noopener noreferrer"&gt;Pragmatic Engineer Survey — Shippers vs Builders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bloomberg.com/news/articles/2026-03-20/openai-contractors-upload-work-products-for-training" rel="noopener noreferrer"&gt;OpenAI — Contractor work product collection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cnbc.com/2026/02/10/google-ai-use-performance-reviews.html" rel="noopener noreferrer"&gt;Google — AI use in performance reviews&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ft.com/content/jpmorgan-ai-engineers-memo" rel="noopener noreferrer"&gt;JPMorgan — AI harness memo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/example/colleague-skill" rel="noopener noreferrer"&gt;Colleague Skill GitHub project (archived)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/example/status/1234567890" rel="noopener noreferrer"&gt;Anti-distillation tool — 5M likes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/were-not-being-replaced-by-ai-were-being-asked-to-train-it/" rel="noopener noreferrer"&gt;We’re Not Being Replaced by AI. We’re Being Asked to Train It.&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
    </item>
    <item>
      <title>The Most Important Skill in Tech Is Too Expensive to Learn</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Sun, 19 Apr 2026 16:11:39 +0000</pubDate>
      <link>https://forem.com/pacheco/the-most-important-skill-in-tech-is-too-expensive-to-learn-1j2e</link>
      <guid>https://forem.com/pacheco/the-most-important-skill-in-tech-is-too-expensive-to-learn-1j2e</guid>
      <description>&lt;p&gt;I spent last weekend trying to build a feature with an open-source model running locally. Qwen, 32 billion parameters. I gave it the same task I’d done with Claude the week before — a well-scoped feature, clear spec, defined constraints. The kind of work where I know exactly what good output looks like.&lt;/p&gt;

&lt;p&gt;It took me four attempts to get something that compiled. Not something that worked well — something that compiled. The model kept losing context halfway through, hallucinating imports that didn’t exist, and confidently generating patterns that contradicted what I’d specified three prompts earlier. I spent more time correcting its output than it would’ve taken me to write the thing from scratch.&lt;/p&gt;

&lt;p&gt;The same task with Claude Opus 4.6 in Claude Code? One pass. Clean implementation. Twenty minutes.&lt;/p&gt;

&lt;p&gt;And before you say “just use a better open-source model” — I know. The strongest open-source models today are genuinely capable. But running them at full quality locally requires serious hardware. We’re talking high-end GPUs, machines that cost thousands of dollars. If you don’t have that, your alternative is a provider like OpenRouter — more accessible, but sustained agentic sessions still add up fast. You can quantize the models to fit smaller hardware, but you’re trading quality for affordability, which is the whole problem.&lt;/p&gt;

&lt;p&gt;Either way you’re paying. Local hardware or API costs. And the people who most need access to this technology are the ones least able to afford either option.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Skill That Runs Everything Now
&lt;/h2&gt;

&lt;p&gt;Using AI effectively is becoming the most important skill in the industry. And I don’t mean prompting — that’s the surface-level version of the conversation that keeps people stuck.&lt;/p&gt;

&lt;p&gt;There are actually two layers to this skill, and both of them have an access problem.&lt;/p&gt;

&lt;p&gt;The first layer is the judgment. It’s knowing how to scope a problem so the model can handle it. It’s developing the instinct for when the model is right and when it’s subtly wrong in ways that won’t show up until production. It’s understanding how to work &lt;em&gt;with&lt;/em&gt; the model’s strengths and around its weaknesses. This is the soft skill side — the part that requires reps with models that are good enough to teach you something. If the model you’re working with fails in ways that have nothing to do with your approach — losing context, ignoring constraints, hallucinating — you’re not developing the skill. You’re just debugging a bad tool.&lt;/p&gt;

&lt;p&gt;The second layer is the one that doesn’t get talked about enough: the practical configuration.&lt;/p&gt;

&lt;p&gt;Look at what’s happening with Claude Code right now. There’s an entire ecosystem forming around it — CLAUDE.md files that teach the agent your project’s conventions, subagent configurations that break complex work into orchestrated pieces, hooks that enforce guardrails automatically, skills and plugins that extend what the agent can do. People are building and sharing these configurations the way they used to share dotfiles or ESLint configs. It’s becoming its own discipline.&lt;/p&gt;

&lt;p&gt;And it matters. A well-configured Claude Code setup with proper project memory, clear guidelines that evolve with the codebase, and hooks that catch mistakes before they compound — that’s not a nice-to-have anymore. That’s the difference between the agent producing useful work and producing junk. Learning how to structure that configuration, how to set up subagents for different tasks, how to write project guidelines that actually steer the model’s behavior — these are real, practical, in-demand skills.&lt;/p&gt;

&lt;p&gt;But here’s the problem: all of that knowledge is being built on top of Claude Code specifically. The skills, the hooks, the configuration patterns, the community sharing best practices — it’s all deeply tied to a $100-200/month tool running the most expensive models available. The more sophisticated the ecosystem gets, the deeper the lock-in. And the deeper the lock-in, the more expensive it becomes to develop the skills that actually matter.&lt;/p&gt;

&lt;p&gt;It’s not just “learn to use AI.” It’s “learn to configure and orchestrate AI agents at a level of sophistication that requires sustained access to premium tools.” And that’s a much harder problem to solve with free tiers and quantized local models.&lt;/p&gt;

&lt;p&gt;Both layers of this skill are becoming as foundational as knowing Git or being able to navigate a codebase. Except they’re evolving faster than any of those did, and the cost of staying current is real money.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Model Is the Bottleneck
&lt;/h2&gt;

&lt;p&gt;People talk about harnesses — Claude Code vs Cursor vs Codex vs whatever dropped this week. And yeah, the tooling matters. But you can run Claude Code with a local model if you know the tricks. You can plug open-source models into most of these harnesses.&lt;/p&gt;

&lt;p&gt;It doesn’t fix the problem.&lt;/p&gt;

&lt;p&gt;Because the output is limited by the model itself. A great harness with a mediocre model produces mediocre results with better formatting. The agent can manage files, run commands, iterate on errors — but if the model behind it can’t hold context or reason through the nuance of what you’re building, the loop just generates more mistakes faster.&lt;/p&gt;

&lt;p&gt;The top-tier models — Claude Opus 4.6, GPT-5.4 — are meaningfully better at the things that matter for real development work. They hold context longer. They understand relationships between components. They catch their own mistakes more often. They produce code that requires less intervention. These aren’t marginal benchmark differences. These are differences you feel in every single session.&lt;/p&gt;

&lt;p&gt;And every one of those models costs money. Claude Pro is $20/month and you’ll hit rate limits in a day doing serious work. The Max plan that actually lets you use Claude Code without interruption is $100-200/month — and that only covers Claude Code, not other harnesses. Cursor Pro, Copilot Pro — more subscriptions stacking up. If you want the workflow that actually builds the skill the market is demanding, you’re spending real money every month.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who Gets Left Behind
&lt;/h2&gt;

&lt;p&gt;Think about three people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The junior developer, fresh out of school.&lt;/strong&gt; They’ve heard AI is important. Maybe they’ve used ChatGPT for homework. But the landscape of AI coding tools is an overwhelming mess — Copilot, Cursor, Claude Code, Codex, Windsurf, and a dozen others, each with different pricing, different paradigms, different ecosystems. They don’t know which one matters. They don’t know which one to invest in. And the ones that would actually teach them the most important patterns cost money they don’t have. Sure, there are free tiers — Copilot gives you 2,000 completions and 50 chat requests a month, and OpenRouter has free models with rate limits. But those tiers are built for tasting, not for training. You can’t develop real fluency in 50 requests a month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The experienced developer who got laid off.&lt;/strong&gt; Yesterday they had Claude Pro through their company, API access for experiments, maybe a Cursor license on the company card. Today they have none of it. The skill they were building — the one that was making them genuinely more effective — just got cut off overnight. And the market they’re re-entering expects AI proficiency as a baseline. They know what they’re missing because they’ve felt the difference. That might be worse than never having had it at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The career switcher.&lt;/strong&gt; Someone coming from another field, trying to break into tech. They’re already learning to code, which is hard enough. Now they need to learn to work with AI too, but the models that would give them meaningful reps are priced for people with engineering salaries. They’re trying to build a skill they can’t afford to practice.&lt;/p&gt;

&lt;p&gt;Each of these people has a slightly different version of the same problem: &lt;strong&gt;the skill the market values most is developing behind a price tag most people can’t justify.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some companies are subsidizing tools for their employees now. That’s real, and it’s good. But it only helps people who already have jobs. It does nothing for the people trying to get in. And even for employed developers, there’s a difference between using a company-provided tool in a company-specific workflow and building genuine AI fluency that transfers. Getting good at your team’s setup isn’t the same as understanding the patterns deeply enough to adapt when everything changes in six months. Which it will.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I’m Actually Doing About It
&lt;/h2&gt;

&lt;p&gt;I’d feel dishonest writing this without being transparent about where I am personally.&lt;/p&gt;

&lt;p&gt;I’ve been deliberately pushing open-source and cheaper models harder in my own workflow. Running local models on my machine, using cheaper options through OpenRouter, trying to find the ceiling of what’s accessible today. Not because I think they’re better — I just spent several paragraphs telling you they’re not. But because I think there’s real value in mapping out what’s possible without the premium price tag.&lt;/p&gt;

&lt;p&gt;Here’s what I’ve found so far, honestly.&lt;/p&gt;

&lt;p&gt;Local models on the modest hardware I have today are very behind. It’s not close. The gap between what I get locally and what Claude Opus 4.6 or GPT-5.4 produce isn’t a minor quality difference — it’s a fundamentally different experience. The local models lose context, miss nuance, and require constant hand-holding that defeats the purpose of the workflow.&lt;/p&gt;

&lt;p&gt;The cheaper models through OpenRouter are better — you can get genuinely good responses. But there’s a catch: you have to constrain the work to small, well-defined tasks to get consistent output. You can’t be vague. You can’t be high-level. You can’t describe what you want broadly and trust the model to figure out the details the way you can with the top-tier models. Every task needs to be broken down, specified precisely, and scoped tightly.&lt;/p&gt;

&lt;p&gt;And that creates its own problem. Because sometimes, by the time you’ve broken the work down small enough and specified it precisely enough for the cheaper model to handle it reliably, you’ve already done most of the thinking. At that point, it’s genuinely faster to just write the code yourself than to spend the time guiding the model through it.&lt;/p&gt;

&lt;p&gt;That’s the real gap. It’s not just quality of output — it’s how much of your own effort is required to get there. The top-tier models let you think at a higher level of abstraction. The accessible ones force you back down into the details, which is exactly where AI was supposed to save you time.&lt;/p&gt;

&lt;p&gt;I haven’t tested Gemma 4 deeply yet — I have high hopes for it given what the benchmarks are showing. But I’m not going to claim results I haven’t experienced. For now, I keep pushing because I believe the trajectory is real. But the honest answer is that nothing I’ve tried on the accessible side comes close to what the premium models deliver.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Industry Problem We’re Building
&lt;/h2&gt;

&lt;p&gt;It takes years to develop a senior engineer. I’ve written about the pipeline problem — how cutting junior hiring today creates a senior shortage in 7-10 years. But this is a different angle on the same structural failure.&lt;/p&gt;

&lt;p&gt;Even the developers who do break in — if they can’t afford to develop AI fluency early, they’re starting with a deficit that compounds over time. The developers who had access to top-tier models from day one are building intuitions, workflows, and judgment that the others can’t match. Not because of talent. Because of access.&lt;/p&gt;

&lt;p&gt;We’re building a two-tier system. People who learned to work with AI at the highest level because they could afford to, and people who picked up what they could from free tiers and rate-limited demos. The gap between those two isn’t trivial — it’s the difference between building the instinct for what works and just knowing it exists in theory.&lt;/p&gt;

&lt;p&gt;For decades, the software industry had a genuine claim to accessibility in at least one respect: the tools were free. You could learn to code with free software, contribute to open-source projects, build a portfolio, and land a job without spending a dollar on tooling. The playing field wasn’t level — it never is — but the tools didn’t gatekeep you.&lt;/p&gt;

&lt;p&gt;AI is changing that equation. Not because the models are secret — many are open-weight. But because the models that are good enough to build the skills that matter require compute that costs real money. And nobody seems to be treating this as the urgent problem it is.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bet
&lt;/h2&gt;

&lt;p&gt;I don’t have a clean answer for this. If I did, I’d be building a company, not writing a blog post.&lt;/p&gt;

&lt;p&gt;But I’m not betting blind either. The trajectory is real.&lt;/p&gt;

&lt;p&gt;Google just released Gemma 4 under Apache 2.0 — a family of models designed to run on consumer hardware, with coding benchmarks that show massive jumps over the previous generation. DeepSeek keeps pushing the boundaries of what’s possible at low cost, with their next model aiming for frontier performance under an open license. Qwen continues to improve. The open-source community is moving fast, and the gap between these models and the proprietary ones is genuinely narrowing.&lt;/p&gt;

&lt;p&gt;But narrowing isn’t closed. And the people who need access most can’t wait for the trajectory to finish.&lt;/p&gt;

&lt;p&gt;I’m betting that how accessible these tools become in the next two years will shape the entire next generation of professionals. The people entering the industry right now, the people trying to transition, the ones who got pushed out and are fighting their way back — they’re being shaped by what they can and can’t access today. If the most important skill of their era is only learnable at premium prices, we’re not just failing them individually. We’re hollowing out the pipeline the entire industry depends on.&lt;/p&gt;

&lt;p&gt;What we call “software developer” is becoming something else. AI engineer, maybe. Whatever it gets called, the core competency is shifting — less about writing code, more about orchestrating intelligence. Making judgment calls about what to build and how to specify it. That competency needs to be learnable at every price point. Not just the premium tier.&lt;/p&gt;

&lt;p&gt;For now, I’m going to keep pushing open-source models in my workflow. Keep documenting what works and where the walls are. Keep being honest about the gap while working to close it, even in my own small corner.&lt;/p&gt;

&lt;p&gt;Because if the most important skill in tech is too expensive to learn, we have a bigger problem than any model can solve.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://blog.google/innovation-and-ai/technology/developers-tools/gemma-4/" rel="noopener noreferrer"&gt;Google Gemma 4 announcement&lt;/a&gt; — Apache 2.0 open models designed for consumer hardware, with native agentic and coding capabilities&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.nxcode.io/resources/news/deepseek-v4-release-specs-benchmarks-2026" rel="noopener noreferrer"&gt;DeepSeek V4 specs and benchmarks&lt;/a&gt; — ~1T parameter MoE model, 37B active per token, targeting frontier performance under open license&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://unsloth.ai/docs/models/qwen3.5" rel="noopener noreferrer"&gt;Qwen 3.5 local hardware guide&lt;/a&gt; — Running large open-source models on consumer devices with quantization&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gemma4.wiki/guide/gemma-4-benchmarks" rel="noopener noreferrer"&gt;Gemma 4 coding benchmarks&lt;/a&gt; — LiveCodeBench scores jumping from 29.1 to 80.0 between Gemma 3 and Gemma 4&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/features/copilot/plans" rel="noopener noreferrer"&gt;GitHub Copilot plans&lt;/a&gt; — Free tier: 2,000 completions, 50 chat requests/month&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.nxcode.io/resources/news/claude-code-pricing-2026-free-api-costs-max-plan" rel="noopener noreferrer"&gt;Claude Code pricing breakdown&lt;/a&gt; — Max plan at $100-200/month for sustained use&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openrouter.ai/openrouter/free" rel="noopener noreferrer"&gt;OpenRouter free models&lt;/a&gt; — 29 free models with rate limits (20 req/min, 200 req/day)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.indiatoday.in/jobs/story/ai-divide-ai-usage-rising-fast-india-workers-face-pressure-adopt-manage-systems-educ-2892584-2026-04-07" rel="noopener noreferrer"&gt;AI divide at work — ETS report&lt;/a&gt; — Regular AI users feel more secure; others are falling behind&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://epoch.ai/blog/open-models-report" rel="noopener noreferrer"&gt;Open vs closed AI models — Epoch AI&lt;/a&gt; — Tracking the gap between open-weight and proprietary models over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/the-most-important-skill-in-tech-is-too-expensive-to-learn/" rel="noopener noreferrer"&gt;The Most Important Skill in Tech Is Too Expensive to Learn&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>careersoftskills</category>
      <category>strategicai</category>
      <category>aiaccessibility</category>
      <category>aicosts</category>
    </item>
    <item>
      <title>No Developer Feels AI Literate Right Now — Not Even the Ones Building It</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Sun, 19 Apr 2026 16:11:18 +0000</pubDate>
      <link>https://forem.com/pacheco/no-developer-feels-ai-literate-right-now-not-even-the-ones-building-it-4egp</link>
      <guid>https://forem.com/pacheco/no-developer-feels-ai-literate-right-now-not-even-the-ones-building-it-4egp</guid>
      <description>&lt;p&gt;There’s a specific kind of anxiety that hits at 11 PM when you’re scrolling through someone’s thread about the AI workflow that supposedly changed everything. You were productive today. You shipped code. But now you’re wondering if the way you shipped it is already obsolete.&lt;/p&gt;

&lt;p&gt;That feeling? It’s not going away. And I say that as someone who builds AI features every day at my job — user-facing products, developer tools, infrastructure — and uses AI to build them too. I’ve been deep in this flow for a while, and I still don’t feel AI literate. Nobody does.&lt;/p&gt;

&lt;p&gt;That’s the whole thesis.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Illusion of AI Fluency
&lt;/h2&gt;

&lt;p&gt;There’s a dangerous gap forming right now — the distance between “I can get AI to produce code” and “I understand what’s happening well enough to make consistent, reliable decisions.”&lt;/p&gt;

&lt;p&gt;It’s like ordering coffee in another language and thinking you’re fluent. The demo works. But what happens when the context window fills up and the model starts hallucinating? When the tool you’ve been relying on ships a breaking change to how it handles context, and your entire workflow stops working?&lt;/p&gt;

&lt;p&gt;That’s where actual literacy lives. Not in the output — in understanding the mechanics well enough to troubleshoot, adapt, and make real decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Arc: Convergence to Divergence
&lt;/h2&gt;

&lt;p&gt;Here’s a pattern worth naming, because it explains why everything feels so chaotic.&lt;/p&gt;

&lt;p&gt;For the past couple of years, AI coding tools followed roughly the same trajectory. First the conversational phase — chat with a model, get code back. Then the agentic phase — let the model execute actions, read files, run commands. Then context management became the bottleneck — RAG, context windows, retrieval strategies. Then skills and MCPs emerged as ways to extend what agents could do.&lt;/p&gt;

&lt;p&gt;Every major tool went through these same stages. Claude Code, Cursor, Copilot, Codex — the patterns were recognizable across all of them. If you learned one, the mental models transferred.&lt;/p&gt;

&lt;p&gt;That’s no longer true.&lt;/p&gt;

&lt;p&gt;The tools are diverging. Fast. Claude Code now has hooks, subagents, trust modes, and a growing ecosystem of skills. Cursor has its own rules system with a fundamentally different interaction model. Codex has AGENTS.md. Amp, OpenCode, and a dozen others are carving their own paths.&lt;/p&gt;

&lt;p&gt;Each tool is developing its own opinion about how development should work. And those opinions are starting to meaningfully diverge.&lt;/p&gt;

&lt;p&gt;This is React vs Angular vs Vue all over again — except the stakes are higher. That was about which UI library renders faster. This is about how you think, plan, and build software at a fundamental level.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Best Practice Treadmill
&lt;/h2&gt;

&lt;p&gt;A few weeks ago, the developer community was buzzing about skills replacing MCPs. Skills were simpler, lighter, didn’t require running separate processes. The consensus was forming: skills are the future, MCPs are the past.&lt;/p&gt;

&lt;p&gt;Then optimizations changed the calculus on MCP context consumption. Suddenly MCPs were more viable again. The narrative flipped.&lt;/p&gt;

&lt;p&gt;Now? People use a mix of both. Some skills actually wrap MCPs internally. Nobody’s sure if that’s a good pattern or an anti-pattern.&lt;/p&gt;

&lt;p&gt;This all happened in the span of a few weeks. And it’s the new normal — the “right way” to structure your AI workflow has a half-life measured in weeks, not months.&lt;/p&gt;

&lt;h2&gt;
  
  
  So What Does This Mean for Your Career?
&lt;/h2&gt;

&lt;p&gt;If senior engineers with years of pattern recognition and deep technical foundations feel lost — what does this mean for someone finishing college right now? Or someone transitioning into tech?&lt;/p&gt;

&lt;p&gt;I’ll be direct: it’s harder than ever to get a job as a software engineer. You don’t just need to know how to code anymore. You need to know how to code, how to work with AI, which AI tools to invest in, and how to recognize when current practices expire. Most bootcamps and university programs haven’t even begun to address this. And companies don’t know what to test for either — interview loops are still measuring skills from two years ago while the actual job involves orchestrating agents and making architectural decisions AI can’t make for you.&lt;/p&gt;

&lt;p&gt;So the question people are asking — “Is it even worth learning software engineering right now?” — is genuine.&lt;/p&gt;

&lt;p&gt;Here’s what I think: the answer is yes. But the approach has to change.&lt;/p&gt;

&lt;p&gt;The demand for engineers isn’t dying — job openings have surged this year, and companies that replaced senior engineers with juniors-plus-AI are already course-correcting. Human judgment, architectural thinking, and the ability to make sense of complex systems still matter. But you can’t just learn to code and expect that to be enough anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick One Tool. Get Dangerously Good at It.
&lt;/h2&gt;

&lt;p&gt;Stop trying to learn every coding harness. Don’t split your attention between Claude Code, Codex, Amp, OpenCode, and whatever drops next week. Pick one. Commit to it. Go deep.&lt;/p&gt;

&lt;p&gt;There’s research backing this up. BCG found that productivity increases with one or two AI tools, peaks around three, and actively drops when you add a fourth. They’re calling it “AI brain fry” — more tools means more context switching, more cognitive load, worse outcomes. Mastering one tool isn’t just a preference. It’s the strategy that actually works.&lt;/p&gt;

&lt;p&gt;I’ll tell you what I use: Claude Code. It has the richest set of capabilities right now — hooks, skills, subagents, MCP integrations, trust modes — and Anthropic’s models consistently deliver. The community around it is the most active I’ve seen. That could change in six months. But the point isn’t really the specific tool.&lt;/p&gt;

&lt;p&gt;When you deeply learn one tool — when you understand how it manages context, how its agentic loop works, how to structure your projects for it — you develop transferable mental models. You learn what “good context management” means, not just how one tool implements it. You learn why hooks exist, why skills exist, why MCPs exist. Those patterns survive the churn.&lt;/p&gt;

&lt;p&gt;If the tools diverge to the point where switching becomes necessary, you’ll transition from a place of strength — deep literacy in one ecosystem — rather than shallow familiarity with five.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Something That Felt Impossible
&lt;/h2&gt;

&lt;p&gt;Theory doesn’t stick without practice.&lt;/p&gt;

&lt;p&gt;Think of a project you’ve always wanted to build but never had the time. Something slightly out of reach — too many moving parts, too much boilerplate, too many unknowns. Now try to build it with your AI coding tool of choice.&lt;/p&gt;

&lt;p&gt;Here’s my example. I’d been wanting to rebuild my blog with a custom WordPress theme for months. I knew exactly what I wanted — the design, the deployment pipeline, the git integration. What I didn’t have was the time to write it all out.&lt;/p&gt;

&lt;p&gt;So I started prompting my agent harness while at the gym. Between sets, between exercises — describing what I needed, reviewing what came back, steering it. Within about three days of gym sessions and prompting, the new blog was live.&lt;/p&gt;

&lt;p&gt;That was a genuine wow moment. Not the viral demo kind — the personal kind. It didn’t come for free. I knew what to ask for, which tools to use, how to set up the deployment. But I never had to remember WordPress internals or look at a single line of code.&lt;/p&gt;

&lt;p&gt;Don’t aim for perfection. Just try to get it done and pay attention to how it feels. You’re going to land in one of two places.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You build the thing faster than you ever could have alone.&lt;/strong&gt; Maybe the code isn’t pristine. Maybe you restarted a couple of times. But it works, and you built it in hours instead of weeks. That wow moment is fuel — it motivates you to refine your prompts, learn the next layer, keep pushing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or you struggle.&lt;/strong&gt; The agent loops. It misunderstands your intent. You feel like you’d be faster doing it yourself.&lt;/p&gt;

&lt;p&gt;If you land here, don’t get discouraged. And don’t become someone who dismisses AI as useless based on a bad first experience.&lt;/p&gt;

&lt;p&gt;What almost certainly happened is that your scope was too broad. You gave the agent a vague, ambitious prompt and expected it to figure out the details. That’s the most common mistake starting out.&lt;/p&gt;

&lt;p&gt;The fix: shrink the scope. Way down. Pick the smallest piece — a single endpoint, one component, a basic data model — and try again. Get one small thing working. Feel what it’s like when the tool actually helps. That’s your baseline. From there, you gradually expand — bigger scope, better context, more trust in the loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Truth
&lt;/h2&gt;

&lt;p&gt;Nobody has this figured out. Not the senior engineers. Not the tool makers. Not the influencers who post their workflows like they’ve cracked the code.&lt;/p&gt;

&lt;p&gt;The developers who are going to thrive aren’t the ones who memorize every feature of every tool — they’re the ones who build a learning rhythm they can sustain. Context management, agentic workflows, prompt design, scope control. These patterns are more stable than the specific implementations, and they’re what make you dangerous regardless of which tool you’re holding.&lt;/p&gt;

&lt;p&gt;Pick one tool. Build one thing. Learn one lesson at a time.&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://newsletter.pragmaticengineer.com/p/the-impact-of-ai-on-software-engineers-2026" rel="noopener noreferrer"&gt;The impact of AI on software engineers in 2026&lt;/a&gt; — Pragmatic Engineer survey (900+ engineers on AI tool usage, costs, and uneven effects across experience levels)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.businessinsider.com/ai-brain-fry-bcg-consulting-exhaustion-agents-work-2026-3" rel="noopener noreferrer"&gt;BCG: AI Brain Fry study&lt;/a&gt; — Productivity peaks at 2-3 AI tools and drops at 4+&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.metaintro.com/blog/software-engineer-job-listings-spike-2026-ai-demand" rel="noopener noreferrer"&gt;Software engineer job listings up 30% in 2026&lt;/a&gt; — 67,000+ openings per TrueUp&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.franksworld.com/2026/04/15/why-companies-are-quietly-rehiring-software-engineers-in-the-age-of-ai/" rel="noopener noreferrer"&gt;Why companies are quietly rehiring software engineers&lt;/a&gt; — The “boomerang effect”: ~35% of new hires are former employees&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.technologyreview.com/2026/04/14/1134397/redefining-the-future-of-software-engineering/" rel="noopener noreferrer"&gt;Redefining the future of software engineering&lt;/a&gt; — MIT Tech Review on agentic AI as the “third shift”&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.jetbrains.com/research/2026/04/which-ai-coding-tools-do-developers-actually-use-at-work/" rel="noopener noreferrer"&gt;JetBrains: Which AI coding tools do developers use at work?&lt;/a&gt; — 74% of developers adopted AI tools; Claude Code and Cursor tied at 18%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/feeling-of-being-behind-is-permanent/" rel="noopener noreferrer"&gt;No Developer Feels AI Literate Right Now — Not Even the Ones Building It&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>aicoding</category>
    </item>
    <item>
      <title>Spec-Driven Development Isn’t Waterfall — But It Keeps Ending Up There</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Fri, 17 Apr 2026 22:05:14 +0000</pubDate>
      <link>https://forem.com/pacheco/spec-driven-development-isnt-waterfall-but-it-keeps-ending-up-there-4eei</link>
      <guid>https://forem.com/pacheco/spec-driven-development-isnt-waterfall-but-it-keeps-ending-up-there-4eei</guid>
      <description>&lt;p&gt;&lt;em&gt;Spec-driven development isn’t supposed to be waterfall. But without clear workflows and better tooling, it’s easy to end up there.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I recently went deep on spec-driven development. The idea was straightforward: before writing any code, define everything. The full vision, the context, the trade-offs, where the feature fits in the existing architecture, the references. Hand it all to the AI agent with crystal-clear guidance so it can build with minimal supervision.&lt;/p&gt;

&lt;p&gt;It looked promising. For about two days.&lt;/p&gt;

&lt;p&gt;What I ended up with was thousands of lines of specification documents. Documents that were incredibly hard to review — not because they were poorly structured, but because most of them were generated by the AI itself, correlating the existing architecture, docs, and my guidance into something that &lt;em&gt;looked&lt;/em&gt; authoritative. Clear explanations. Perfect formatting. Confident reasoning about every decision.&lt;/p&gt;

&lt;p&gt;And that’s exactly where it got scary.&lt;/p&gt;




&lt;h2&gt;The Confidence Problem Nobody Mentions&lt;/h2&gt;

&lt;p&gt;Here’s the thing about AI-generated specs that the SDD evangelists aren’t talking about: &lt;strong&gt;the AI makes everything look correct.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a spec is well-formatted, internally consistent, and confidently explained, your brain wants to trust it. It reads like something a senior architect wrote after careful deliberation. But it’s not. It’s a language model pattern-matching against your inputs, producing the most plausible-sounding output it can.&lt;/p&gt;

&lt;p&gt;And here’s the trap within the trap: if you push back on something that feels off, the AI doesn’t defend its reasoning. It folds. It assumes you’re right, tries to course correct, and often makes the output &lt;em&gt;worse&lt;/em&gt;. Hallucination risk actually goes up when you question it, because now it’s reconciling your objection with a position it never truly held. It’s not reasoning. It’s pleasing.&lt;/p&gt;

&lt;p&gt;So you’re stuck. Trust the spec and risk building on wrong assumptions. Question the spec and risk destabilizing it further. Either way, you’ve generated thousands of lines of documentation that are incredibly hard to confidently validate.&lt;/p&gt;

&lt;p&gt;After spending far too long trying to get those specs to a place I trusted, it hit me — this felt familiar.&lt;/p&gt;




&lt;h2&gt;The Intent vs. the Reality&lt;/h2&gt;

&lt;p&gt;Here’s where I want to be fair: spec-driven development isn’t &lt;em&gt;supposed&lt;/em&gt; to be big design upfront.&lt;/p&gt;

&lt;p&gt;Marc Brooker, the person building Kiro at AWS, explicitly says “you don’t need to, and probably shouldn’t, develop the entire specification upfront.” Kiro’s own workflow is feature-scoped — requirements, design, and tasks for a single story, not a whole system. GitHub’s Spec-Kit runs in a loop: specify, plan, tasks, repeat per change request. OpenSpec literally states “specs are not frozen contracts; update them when reality changes.”&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;vision&lt;/em&gt; of SDD is iterative. Living documents. Feature-level scope. Incremental refinement.&lt;/p&gt;

&lt;p&gt;But the vision and the practice aren’t the same thing yet.&lt;/p&gt;

&lt;p&gt;Birgitta Böckeler, writing on Martin Fowler’s site, tried to untangle what SDD actually means right now and found the definition “still in flux.” She identified three levels — spec-first, spec-anchored, and spec-as-source — and noted that most tools are only spec-first. They help you write a spec before coding, but don’t have clear strategies for maintaining or evolving that spec over time. Even GitHub Spec-Kit’s own community is confused about whether a spec is supposed to live beyond a single change request.&lt;/p&gt;

&lt;p&gt;The methodology is ahead of the tooling. SDD can absolutely work — but right now, the tools and workflows don’t do enough to keep you on the iterative path. Without clear guardrails for when to stop specifying and start building, teams default to the thing that feels most natural: writing everything down upfront, as thoroughly as possible, before anyone touches code.&lt;/p&gt;

&lt;p&gt;That’s what happened to me. Not because I didn’t know better. Because nothing in the workflow guided me toward “that’s enough, go build and come back.”&lt;/p&gt;




&lt;h2&gt;The Waterfall Gravity&lt;/h2&gt;

&lt;p&gt;There’s a reason teams keep falling into this pattern. It has gravitational pull.&lt;/p&gt;

&lt;p&gt;When you tell an AI agent to help you write a spec, it &lt;em&gt;wants&lt;/em&gt; to be comprehensive. It will map out every component, every edge case, every integration point — because that’s what “thorough” looks like in its training data. And as a developer, you &lt;em&gt;want&lt;/em&gt; to feel like you’ve thought of everything before handing off to an autonomous agent. The combination of an AI that defaults to exhaustive and a human who defaults to cautious creates thousands of lines of documentation almost by accident.&lt;/p&gt;

&lt;p&gt;This is the same dynamic that made waterfall feel so appealing in the first place. The Agile Manifesto exists because planning everything upfront didn’t work:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Responding to change over following a plan.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;SDD proponents will rightly say “that’s not what we’re advocating.” And they’re right. But the tooling needs to actively enforce iterative scope — otherwise that gravity keeps pulling teams toward specifying everything before building anything. The intent is agile. The default behavior, without better rails, is waterfall.&lt;/p&gt;

&lt;p&gt;Of course, agile itself got convoluted over the years. Certifications, rituals, dogma that drifted far from the original insight. But the core idea never stopped being true: you learn more from building than from planning.&lt;/p&gt;

&lt;p&gt;Thoughtworks — the company whose chief scientist co-authored the Agile Manifesto — just released Technology Radar v34 this week, warning that as AI accelerates code generation, “established practices that ensure discipline become more vital.” They’re not pushing SDD. They’re pushing fundamentals. Iteration. Feedback loops.&lt;/p&gt;




&lt;h2&gt;What SDD Gets Right&lt;/h2&gt;

&lt;p&gt;I don’t want to dismiss the methodology. There are real benefits when it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agents need constraints.&lt;/strong&gt; Without scope boundaries, they expand. Tell an agent to build auth and it’ll add OAuth, SSO, and MFA because that’s what “auth” means in its training data. A spec that says “OAuth is out of scope” genuinely saves time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context improves quality.&lt;/strong&gt; An agent with the full picture makes fewer locally-right-but-globally-wrong decisions. The spec gives it a map, not just turn-by-turn directions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team alignment.&lt;/strong&gt; Multiple people or agents working on the same system need a shared reference point. Specs provide that.&lt;/p&gt;

&lt;p&gt;The problem was never “should we spec?” It’s “how do we make sure we spec iteratively instead of falling into the trap of specifying everything at once?”&lt;/p&gt;




&lt;h2&gt;Thinking in Graphs&lt;/h2&gt;

&lt;p&gt;Here’s where I’ve landed — and maybe this is just how my brain works, but I think it applies broadly.&lt;/p&gt;

&lt;p&gt;I think about projects as graphs, not documents.&lt;/p&gt;

&lt;p&gt;At the top, there’s a direction. A north star. What we’re building and why. High-level, intentional, human-defined. It doesn’t need to specify every data model or API contract. It needs to be clear about the destination.&lt;/p&gt;

&lt;p&gt;From that direction, you break down into milestones. Each milestone is a meaningful checkpoint — something you can ship, test, or validate. Not a document section. A real deliverable.&lt;/p&gt;

&lt;p&gt;Each milestone has its own tasks. And here’s the critical part: &lt;strong&gt;the depth of planning for each task happens when you start working on it, not months before.&lt;/strong&gt; You plan the first milestone in detail. You sketch milestone three at a high level. When you finish milestone one, you know things you didn’t know before — and that knowledge shapes how you plan milestone two.&lt;/p&gt;

&lt;p&gt;The direction flows down from the north star. Discovery happens at every node.&lt;/p&gt;

&lt;p&gt;Say you’re building a new integration. The north star says: “Users can sync data between System A and System B in real time.” Milestone one might be a basic one-way sync — and when you build it, you discover the API rate limits aren’t what the docs claimed. That changes everything about milestone two. If you’d fully specced bidirectional sync upfront, you’d be rewriting specs instead of shipping software.&lt;/p&gt;

&lt;p&gt;This works for humans because it provides structure without drowning you in premature detail. It works for AI agents for the same reason — they need guidance and constraints, but they also need room to discover things during implementation that no spec could have predicted.&lt;/p&gt;

&lt;p&gt;Full upfront specification tries to flatten the graph into a document. Every node defined, every edge mapped, before you’ve traversed any of them. That’s not engineering. That’s prophecy.&lt;/p&gt;




&lt;h2&gt;What This Looks Like in Practice&lt;/h2&gt;

&lt;p&gt;I’m still figuring this out. There is no perfect workflow yet — that’s kind of the point. But here’s the pattern that’s working:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thin specs, not thick ones.&lt;/strong&gt; One page for the current milestone, not twenty pages for the whole system. Define the outcome, the constraints, what’s out of scope. Leave room for what you don’t know yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Iterate the spec, not just the code.&lt;/strong&gt; The spec changes every cycle. Decisions made, assumptions validated or invalidated, things learned by building. A living document, not a contract. This is what SDD’s proponents advocate — we just need clearer workflows and tooling to make this the default path instead of something you have to consciously enforce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use agents for exploration, not just execution.&lt;/strong&gt; Code is cheap now. Build a quick prototype to test an architectural assumption. Throw it away if it’s wrong. A throwaway prototype costs you nothing. Specifying the wrong architecture upfront costs you everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep the loop tight.&lt;/strong&gt; In traditional agile, the sprint was two weeks. With agents, the feedback loop can be hours. Specify, build, test, learn, adjust. But only if you keep the scope small enough to actually iterate.&lt;/p&gt;




&lt;h2&gt;The Gap That Needs Filling&lt;/h2&gt;

&lt;p&gt;The industry is living through a real-time methodology shift:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vibe coding&lt;/strong&gt; — prompt and pray. Fast, chaotic, doesn’t scale.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Spec-driven development&lt;/strong&gt; — specify, then execute. Sound in theory, but easy to fall into big design upfront without clear process guardrails.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;What comes next&lt;/strong&gt; — the iterative spec workflow that SDD envisions, supported by tooling and processes that actively keep teams on that path. Thin specs. Fast execution. Continuous refinement. Direction without prophecy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the same arc software development has followed before. Waterfall promised control through upfront planning. Agile recognized that the plan always changes. We’re at that inflection point again — the insight of iterative development needs to be baked into the tools and workflows, not just the blog posts and documentation.&lt;/p&gt;

&lt;p&gt;A project with a clear direction, meaningful milestones, and task-level depth that’s earned at execution time — not guessed at months before — works for both humans and AI agents. Structure without rigidity. Guidance without false certainty.&lt;/p&gt;

&lt;p&gt;The agents are fast. The models are capable. But the bottleneck was never the code.&lt;/p&gt;

&lt;p&gt;It was knowing what to build. And you only learn that by building.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Spec-driven development’s vision is right: specs should be living, iterative, and at the center of how we build software with AI. What we need now is better tooling and clearer processes to make that vision the default — so teams stay on the iterative path instead of drifting into the upfront-planning trap that agile was invented to escape. The Agile Manifesto didn’t expire. It just got a new executor — and that executor needs better guardrails.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/spec-driven-development-waterfall-trap/" rel="noopener noreferrer"&gt;Spec-Driven Development Isn’t Waterfall — But It Keeps Ending Up There&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>developmentbestpract</category>
      <category>agile</category>
    </item>
    <item>
      <title>Clean Code Is Dead (And I Hate That I Agree)</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Sun, 12 Apr 2026 10:53:52 +0000</pubDate>
      <link>https://forem.com/pacheco/clean-code-is-dead-and-i-hate-that-i-agree-4kme</link>
      <guid>https://forem.com/pacheco/clean-code-is-dead-and-i-hate-that-i-agree-4kme</guid>
      <description>&lt;p&gt;I’ve spent my career fighting for clean code. In code reviews, in architecture meetings, in those long debates about naming conventions that everyone pretends to hate but secretly cares about. Readable code. Well-structured code. Code that respects the next person who has to touch it.&lt;/p&gt;

&lt;p&gt;I’m starting to realize that none of that might matter anymore.&lt;/p&gt;




&lt;h2&gt;
  
  
  Clean Code Was Always a Human Interface
&lt;/h2&gt;

&lt;p&gt;Every clean code practice we follow was invented to solve a human problem.&lt;/p&gt;

&lt;p&gt;Descriptive variable names? So a human can read it. Separation of concerns? So a human can navigate it. Consistent formatting, small functions, clear abstractions? All of it — designed to make code convenient for people to write and to read.&lt;/p&gt;

&lt;p&gt;The entire philosophy assumes that humans are the primary audience of source code.&lt;/p&gt;

&lt;p&gt;But what happens when they’re not?&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Doesn’t Need Your Clean Code
&lt;/h2&gt;

&lt;p&gt;The more we rely on AI to write, review, and maintain code, the less we actually know the implementation details. And I don’t mean that in a lazy way — I mean structurally. The workflow is changing. You describe what you want, AI generates it, you review the output at a high level, and you move on.&lt;/p&gt;

&lt;p&gt;AI doesn’t care about your variable names. It doesn’t need elegant abstractions to understand what’s happening. It processes the entire codebase — messy or clean — with the same indifference. It doesn’t get confused by a 500-line function. It doesn’t lose context the way a human does after scrolling through too many files.&lt;/p&gt;

&lt;p&gt;I had a moment recently that made this click. I was reviewing AI-generated code and caught myself leaving comments about naming and structure — the same feedback I’d give a junior dev. Then I paused. Who was I writing these comments for? The AI would regenerate the whole thing from scratch on the next prompt anyway. I was applying human code review instincts to a process that doesn’t have a human on the receiving end (sort of). Old habits addressing a problem that no longer exists.&lt;/p&gt;

&lt;p&gt;The practices we built specifically for human readability and human convenience are becoming overhead. In some cases, they’re becoming a bottleneck — extra layers of abstraction that add complexity without benefiting the thing that’s actually doing the reading.&lt;/p&gt;

&lt;p&gt;This isn’t a thought experiment. This is already happening in how teams ship software.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Highest Level Language Is English Now
&lt;/h2&gt;

&lt;p&gt;If readability stops being the priority, what takes its place? Performance.&lt;/p&gt;

&lt;p&gt;If AI can handle the complexity regardless, why optimize for human readability when you can optimize for raw execution speed? The ideal language for AI-driven development might not be Python or TypeScript. It might be C. It might be Rust. It might be something even lower level where AI has fine-grained control over memory, threading, and every implementation detail — things that are painful for humans but trivial for a model that doesn’t get frustrated.&lt;/p&gt;

&lt;p&gt;We’ve always talked about “high level” and “low level” languages. High level meant closer to human thinking, low level meant closer to the machine. But now there’s a level above all of them.&lt;/p&gt;

&lt;p&gt;English. Portuguese. Mandarin. Whatever you speak.&lt;/p&gt;

&lt;p&gt;Natural language is the highest level language now. LLMs are remarkable polyglots — they work fluently in all of them. And code? Code is just the compilation target.&lt;/p&gt;

&lt;p&gt;We went from writing machine instructions, to writing human-readable code, to just… describing what we want in plain words. Each step abstracted away more control. Each step moved us further from the metal.&lt;/p&gt;

&lt;h2&gt;
  
  
  We’re Losing Control at Every Layer
&lt;/h2&gt;

&lt;p&gt;It’s not just that AI writes the code. People use AI to plan the work, brainstorm the architecture, make decisions about what to build and how to build it. The entire pipeline — from idea to implementation — is being routed through language models.&lt;/p&gt;

&lt;p&gt;And LLMs are dangerously convincing. Their reasoning is well-structured even when the underlying data is fabricated or slightly off. I’ve caught myself reading an AI-generated explanation, thinking “yeah, that makes sense,” only to realize later that a key detail was subtly wrong. Or worse — never realizing it at all. The convincing tone becomes a trap.&lt;/p&gt;

&lt;p&gt;You could argue that humans were never perfectly accurate either. Fair. We’ve always built software on incomplete knowledge and best guesses. But there was something grounding about having a person in the loop who had intuition, experience, and skin in the game. Someone who could smell when something was off, even if they couldn’t articulate why.&lt;/p&gt;

&lt;p&gt;The more we delegate — not just the coding, but the thinking — the more that instinct fades. And I’m not sure we’re paying enough attention to what we’re losing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe I’m Too Attached to the Craft
&lt;/h2&gt;

&lt;p&gt;Maybe I’m romanticizing this. Maybe code was always just a means to an end and I turned it into something more than it needed to be. I built part of my identity around writing good code, caring about architecture, treating the codebase as a product in itself. It’s hard to watch that become irrelevant and not take it personally.&lt;/p&gt;

&lt;p&gt;Maybe I’m onto something. Maybe the people who cared about the craft will be the ones who notice when the quality starts slipping in ways that AI can’t detect. Or maybe that’s just what I tell myself to feel relevant.&lt;/p&gt;

&lt;p&gt;I genuinely don’t know.&lt;/p&gt;

&lt;p&gt;And I can’t be a hypocrite about it. This very piece — I’m using AI to help me review it, refine the structure, make sure it reads well. I’m literally writing about the death of human craft while using the thing that’s killing it to help me write better.&lt;/p&gt;

&lt;p&gt;But the ideas are mine. The opinions are mine. The discomfort is mine. AI didn’t tell me to feel this way — I felt it, and then I used a tool to articulate it more clearly. There’s a difference between using AI as a tool and being used by it. At least I think there is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mental Model Shift
&lt;/h2&gt;

&lt;p&gt;I don’t have a solution. But I’ve been rethinking how I relate to the work, and that’s helped more than any specific tool or workflow.&lt;/p&gt;

&lt;p&gt;The shift is this: if code is becoming the compilation target, then what you’re really building isn’t the code — it’s the system of decisions that produces it. Your taste. Your standards. Your judgment about what good looks like. That’s the actual product now.&lt;/p&gt;

&lt;p&gt;And that’s something you can teach to AI.&lt;/p&gt;

&lt;p&gt;I’ve been experimenting with this — taking the patterns I’ve developed over years of writing software and encoding them into the tools I work with. Not just “generate a function that does X” but “here’s how I think about error handling, here’s my preference on abstraction depth, here’s what I consider acceptable tradeoffs.” The more specific you get about your own engineering philosophy, the more the output starts to feel like yours instead of generic AI slop.&lt;/p&gt;

&lt;p&gt;This isn’t complicated or expensive. The tooling to build your own AI workflows — agents that understand how &lt;em&gt;you&lt;/em&gt; work — is accessible today in a way that would’ve been unthinkable two years ago. You don’t need a team or a platform. You need clarity about your own standards and the willingness to invest time in teaching them.&lt;/p&gt;

&lt;p&gt;If you’ve spent years developing engineering taste, that taste is now &lt;em&gt;leverage&lt;/em&gt;. You can apply it at a scale that was never possible when you had to write every line yourself. More ambitious projects. More complex systems. Things that would’ve required a team, handled by one person with clear vision and the right tools.&lt;/p&gt;

&lt;p&gt;It only works if you stay in the driver’s seat though. If you’re the one making the calls about what ships and what gets thrown away. Not a consumer of whatever AI generates, but the lead. The final authority.&lt;/p&gt;

&lt;p&gt;And right now, I’m watching a lot of people quietly stop being that.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Don’t Have a Clean Answer
&lt;/h2&gt;

&lt;p&gt;If language models keep evolving at even half the pace we’ve seen over the last couple of years, the industry in five years looks nothing like it does today. The way we think about programming, about code quality, about what it means to be a software engineer — all of it is up for renegotiation.&lt;/p&gt;

&lt;p&gt;I don’t have a neat conclusion. I have a tension I’m sitting with, and I think a lot of developers feel it too even if they haven’t put words to it yet.&lt;/p&gt;

&lt;p&gt;Clean code might be dead. The practices, the principles, the carefully named variables and thoughtfully extracted functions — they might genuinely become artifacts of an era when humans needed to read what humans wrote.&lt;/p&gt;

&lt;p&gt;But the intention behind clean code? Caring about what you build. Taking pride in the craft. Giving a damn about quality even when no one is looking?&lt;/p&gt;

&lt;p&gt;That can’t die. Unless we let it.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/clean-code-is-dead/" rel="noopener noreferrer"&gt;Clean Code Is Dead (And I Hate That I Agree)&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>developmentbestpract</category>
      <category>aicoding</category>
    </item>
    <item>
      <title>You Think, AI Executes: The Skills That Actually Matter</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Mon, 06 Apr 2026 02:58:16 +0000</pubDate>
      <link>https://forem.com/pacheco/you-think-ai-executes-the-skills-that-actually-matter-1e7p</link>
      <guid>https://forem.com/pacheco/you-think-ai-executes-the-skills-that-actually-matter-1e7p</guid>
      <description>&lt;p&gt;The most valuable developer skill right now isn't writing more code faster. It's learning unfamiliar codebases, building context that guides decisions, planning strategic approaches to problems, and shipping production code with confidence.&lt;/p&gt;

&lt;p&gt;I recently added &lt;code&gt;.env&lt;/code&gt; file support to &lt;a href="https://github.com/joerdav/xc" rel="noopener noreferrer"&gt;xc&lt;/a&gt;, a Markdown-based task runner written in Go. The codebase was completely unfamiliar. I'm not a Go expert. But in 2.5 hours, I went from zero knowledge to a production-ready pull request with 84% test coverage and zero bugs in manual testing.&lt;/p&gt;

&lt;p&gt;Here's what's different: &lt;strong&gt;I didn't write a single line of code.&lt;/strong&gt; Not one. AI wrote everything—tests, implementation, integration, documentation. My role was entirely different: I questioned, I planned, I directed, I reviewed. I read the code, but I didn't write it.&lt;/p&gt;

&lt;p&gt;This isn't another "I asked ChatGPT to build an app" story. This is about the skills that separate developers who use AI as a force multiplier from those who just ask it to generate code. It's about onboarding fast, documenting strategically, planning thoroughly, directing execution, and reviewing confidently. The code writing? That's handled.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpc3lwr2dgyj25mysreu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpc3lwr2dgyj25mysreu.png" alt="📁" width="72" height="72"&gt;&lt;/a&gt; Complete &lt;code&gt;.ai/&lt;/code&gt; folder in the working fork:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://github.com/sudoish/xc/tree/ai-context/.ai" rel="noopener noreferrer"&gt;github.com/sudoish/xc/tree/ai-context/.ai&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9f19bu2w1s9oqo72994z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9f19bu2w1s9oqo72994z.png" alt="🔀" width="72" height="72"&gt;&lt;/a&gt; Production-ready PR:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://github.com/joerdav/xc/pull/167" rel="noopener noreferrer"&gt;github.com/joerdav/xc/pull/167&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvs7fddjqg8063ot203d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvs7fddjqg8063ot203d.png" alt="💡" width="72" height="72"&gt;&lt;/a&gt; The &lt;code&gt;.ai/&lt;/code&gt; folder lives in a separate &lt;code&gt;ai-context&lt;/code&gt; branch so it doesn't clutter the main codebase but remains available for reference and iteration.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Most AI coding demos show you the magic: "I asked ChatGPT to build X and it worked!" They skip the parts that actually matter for professional development: How do you onboard to a codebase you've never seen? How do you make architectural decisions when you don't understand the patterns yet? How do you ensure your code is production-ready when AI helped write it?&lt;/p&gt;

&lt;p&gt;These are the skills that matter now. Code generation is table stakes. What matters is context building, strategic planning, and confident execution.&lt;/p&gt;

&lt;p&gt;Here's the project: &lt;a href="https://github.com/joerdav/xc" rel="noopener noreferrer"&gt;xc&lt;/a&gt;, a task runner that reads tasks from Markdown files. About 5,000 lines of Go. Completely unfamiliar to me. The feature request was straightforward: add &lt;code&gt;.env&lt;/code&gt; file support (&lt;a href="https://github.com/joerdav/xc/issues/162" rel="noopener noreferrer"&gt;Issue #162&lt;/a&gt;). In 2.5 hours, using free AI models and a structured approach, I went from knowing nothing about the codebase to a merged pull request.&lt;/p&gt;

&lt;p&gt;The difference wasn't better prompts. It was better process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Actual Workflow: What I Did vs What AI Did
&lt;/h2&gt;

&lt;p&gt;Here's the honest breakdown of who did what. I didn't write a single line of code myself. That's not the valuable work anymore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explored the codebase with AI&lt;/strong&gt; — Asked questions, challenged its understanding, verified explanations against the actual code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built the &lt;code&gt;.ai/&lt;/code&gt; structure&lt;/strong&gt; — Wrote context docs, ADRs, rules, and implementation specs based on my growing understanding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Questioned the strategy&lt;/strong&gt; — Evaluated alternatives, captured trade-offs, made architectural decisions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directed the implementation&lt;/strong&gt; — "Follow the spec. Implement test 1. Now test 2." Each step validated before moving forward&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reviewed iteratively&lt;/strong&gt; — Asked AI to review the code, digested its findings, confirmed issues, asked it to fix them. Repeated multiple times&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Final deep review&lt;/strong&gt; — Read through the entire PR on GitHub, verified everything made sense, marked ready for review&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What AI did:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Answered my questions&lt;/strong&gt; — Explained architecture, pointed me to relevant files, clarified patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrote all the code&lt;/strong&gt; — Tests, implementation, integration, everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Found its own bugs&lt;/strong&gt; — Self-review caught 5 issues before I even looked at the code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed the issues&lt;/strong&gt; — Applied fixes based on its own review findings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Followed the plan&lt;/strong&gt; — Implemented exactly what the spec described, in the order specified&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What we did together:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built understanding through conversation&lt;/li&gt;
&lt;li&gt;Validated each step before proceeding&lt;/li&gt;
&lt;li&gt;Caught subtle bugs through TDD&lt;/li&gt;
&lt;li&gt;Created production-ready code with high confidence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: &lt;strong&gt;I never typed code.&lt;/strong&gt; I read it, reviewed it, directed changes to it. But I didn't write it. My value was in understanding, planning, and judgment. AI's value was in execution and self-checking. This is the new division of labor.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Skills
&lt;/h2&gt;

&lt;p&gt;This walkthrough demonstrates four skills that matter more than code generation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill 1: Rapid Onboarding.&lt;/strong&gt; Learning an unfamiliar codebase fast by building structured context instead of reading every file. The &lt;code&gt;.ai/&lt;/code&gt; folder captures architecture, patterns, and limitations in a way both humans and AI can reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill 2: Strategic Documentation.&lt;/strong&gt; Building documentation that guides development, not just records it. Architecture Decision Records (ADRs) capture the "why" behind choices, evaluate alternatives, and create a shared understanding before code is written.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill 3: Systematic Planning.&lt;/strong&gt; Breaking down problems into testable steps. Each test defines expected behavior. Each implementation proves the behavior works. Each commit tells part of the story. No guessing, no hoping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill 4: Confident Execution.&lt;/strong&gt; Shipping code you trust because you've tested it thoroughly, reviewed it critically, and validated it works in real scenarios. AI can help write code, but you own the quality.&lt;/p&gt;

&lt;p&gt;These skills work regardless of the AI tool you use. They work with free models. They work on unfamiliar codebases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Feature Request
&lt;/h2&gt;

&lt;p&gt;First, a quick primer on how xc works: it's a task runner that reads tasks directly from your &lt;code&gt;README.md&lt;/code&gt; (or any markdown file). Tasks are defined as markdown headings with code blocks. When you run &lt;code&gt;xc test&lt;/code&gt;, it finds the &lt;code&gt;## test&lt;/code&gt; heading in your README and executes the code block beneath it. The genius is that your documentation &lt;em&gt;is&lt;/em&gt; your task runner, so they never get out of sync.&lt;/p&gt;

&lt;p&gt;A user opened &lt;a href="https://github.com/joerdav/xc/issues/162" rel="noopener noreferrer"&gt;Issue #162&lt;/a&gt; asking for &lt;code&gt;.env&lt;/code&gt; file support. They wanted to use the same set of tasks for different environments without cluttering the Markdown with environment variables.&lt;/p&gt;

&lt;p&gt;Before the feature, you'd have to write this in your README.md:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## deploy&lt;/span&gt;

Deploy to production.

Env: &lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres://prod/db, &lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret123, &lt;span class="nv"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;kubectl apply -f deployment.yaml&lt;/p&gt;

&lt;p&gt;Then run with &lt;code&gt;xc deploy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After the feature, your README stays clean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## deploy&lt;/span&gt;

Deploy to production.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;kubectl apply -f deployment.yaml&lt;/p&gt;

&lt;p&gt;The environment variables live in a separate &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgres://prod/db&lt;/span&gt;
&lt;span class="py"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;secret123&lt;/span&gt;
&lt;span class="py"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You still run the same command, but now the credentials are managed in &lt;code&gt;.env&lt;/code&gt; instead of cluttering your documentation.&lt;/p&gt;

&lt;p&gt;Simple ask, but the implementation requires real decisions. When do you load the files? What about overrides? How do you handle security? What about backward compatibility?&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;.ai/&lt;/code&gt; Structure: Context as Code
&lt;/h2&gt;

&lt;p&gt;Before writing any code, I created a structured context folder. This turned out to be the key to working with AI effectively. It's not about better prompts, it's about better &lt;strong&gt;structure&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Full &lt;code&gt;.ai/&lt;/code&gt; folder:&lt;/strong&gt; &lt;a href="https://github.com/sudoish/xc/tree/ai-context/.ai" rel="noopener noreferrer"&gt;github.com/sudoish/xc/tree/ai-context/.ai&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The folder looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.ai/
├── agents.md # Who's working on what
├── context.md # Project overview, architecture
├── architecture/
│ ├── decisions.md # Current design patterns
│ └── adrs/
│ └── 001-dotenv-support.md # Design decisions for this feature
├── rules/
│ ├── code-style.md # Go conventions
│ ├── testing.md # TDD workflow
│ └── commits.md # Commit message format
└── tasks/
    └── 001-dotenv-implementation.md # Step-by-step plan

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; This structure is an investment, not overhead you repeat for every feature. You build it once during your first feature, then leverage it for every feature after. The &lt;code&gt;context.md&lt;/code&gt;, &lt;code&gt;architecture/decisions.md&lt;/code&gt;, and &lt;code&gt;rules/&lt;/code&gt; files rarely change. Each new feature just adds a new ADR (like &lt;code&gt;002-api-caching.md&lt;/code&gt;) and a new task spec (like &lt;code&gt;002-api-caching-implementation.md&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Think of it like setting up your development environment. The initial setup takes time, but every feature after that is faster because the foundation exists.&lt;/p&gt;

&lt;p&gt;Each file serves a specific purpose. The &lt;a href="https://github.com/sudoish/xc/blob/ai-context/.ai/context.md" rel="noopener noreferrer"&gt;&lt;code&gt;context.md&lt;/code&gt;&lt;/a&gt; file becomes AI's memory. It explains what xc does, how it's architected with its &lt;code&gt;cmd/&lt;/code&gt;, &lt;code&gt;models/&lt;/code&gt;, &lt;code&gt;run/&lt;/code&gt;, and &lt;code&gt;parser/&lt;/code&gt; packages, what key behaviors exist like dependencies and environment handling, and what current limitations we're working around. Every time I ask AI a question, this context gets included automatically.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/sudoish/xc/blob/ai-context/.ai/rules/testing.md" rel="noopener noreferrer"&gt;&lt;code&gt;rules/testing.md&lt;/code&gt;&lt;/a&gt; file defines the TDD workflow we follow: write a failing test first (red), write minimal code to make it pass (green), clean up without changing behavior (refactor), then commit. This keeps both me and AI honest. No skipping tests. No shortcuts.&lt;/p&gt;

&lt;p&gt;The real gem is &lt;a href="https://github.com/sudoish/xc/blob/ai-context/.ai/architecture/adrs/001-dotenv-support.md" rel="noopener noreferrer"&gt;&lt;code&gt;adrs/001-dotenv-support.md&lt;/code&gt;&lt;/a&gt;, the Architecture Decision Record. This is where design happens. It's not "build me a feature," it's "here's why we chose this approach." We decided to load .env files at application startup rather than per-task, to support &lt;code&gt;.env.local&lt;/code&gt; overrides, to skip world-readable files for security, and to add CLI flags like &lt;code&gt;--env-file&lt;/code&gt; and &lt;code&gt;--no-env&lt;/code&gt;. We considered alternatives like per-task loading (rejected as too complex) and requiring an explicit flag (rejected as too much friction). This ADR becomes the source of truth. When AI suggests something different, I can just say "check the ADR."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The living documentation principle:&lt;/strong&gt; As the codebase evolves, so does the &lt;code&gt;.ai/&lt;/code&gt; folder. When you add a new feature, you write a new ADR (002, 003, etc.). When architecture changes, you update &lt;code&gt;architecture/decisions.md&lt;/code&gt; or add a new ADR explaining the change. When patterns emerge, you document them. The folder grows with the project, but the structure stays the same. Each feature builds on the understanding captured before it.&lt;/p&gt;

&lt;p&gt;This means the second feature is faster than the first. The third is faster than the second. The documentation compounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Task Spec: Planning Before Coding
&lt;/h2&gt;

&lt;p&gt;Before writing any code, I created &lt;a href="https://github.com/sudoish/xc/blob/ai-context/.ai/tasks/001-dotenv-implementation.md" rel="noopener noreferrer"&gt;&lt;code&gt;tasks/001-dotenv-implementation.md&lt;/code&gt;&lt;/a&gt;, a step-by-step plan for implementing the feature. This isn't a project management document. It's a development spec that breaks the feature into TDD cycles.&lt;/p&gt;

&lt;p&gt;The spec listed each test I needed to write, what behavior it should verify, and the expected implementation. Test for file not found. Test for loading valid env. Test for .env.local overrides. Test for security checks. Each one became a TDD cycle.&lt;/p&gt;

&lt;p&gt;This is what makes AI effective. Without the spec, I'd be asking AI "what should I do next?" every five minutes. With the spec, I'm asking "implement the next test according to the plan." The spec keeps development focused and systematic. It's the difference between wandering and following a map.&lt;/p&gt;

&lt;p&gt;For your second feature, you write a new spec. For your third, another one. The format is consistent, but each spec is tailored to its feature. This is the work that makes development fast and confident.&lt;/p&gt;

&lt;h2&gt;
  
  
  The TDD Flow: Red → Green → Refactor → Commit
&lt;/h2&gt;

&lt;p&gt;Here's where the real work happens. Each test defines acceptance criteria for exactly what needs to be built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cycle 1: Valid .env should load variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First behavior: if a &lt;code&gt;.env&lt;/code&gt; file exists and contains &lt;code&gt;KEY=value&lt;/code&gt; pairs, those should be loaded into the environment. Test written, test failed (red)—no loader existed yet. Implementation added using the godotenv library (green). Test passed. Committed with "load env vars from dotenv file".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cycle 2: .env.local should override .env&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Expected behavior: if both &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;.env.local&lt;/code&gt; exist, and both define the same variable, the &lt;code&gt;.env.local&lt;/code&gt; value wins. This is crucial for local development where you want to override defaults without modifying the base file. Test written, test failed initially because I was using the wrong function, fixed the implementation, test passed. Committed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cycle 3: World-readable files should be skipped&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Security requirement: if a &lt;code&gt;.env&lt;/code&gt; file has permissions that allow other users to read it (like &lt;code&gt;chmod 644&lt;/code&gt;), skip loading it and warn the user. This prevents accidentally exposing secrets. Test created, test failed (secrets were being loaded), added permission check, test passed. Committed.&lt;/p&gt;

&lt;p&gt;This rhythm of define → test → implement → verify → commit creates a clean history. When I looked at the final commit log, I could see exactly how the feature evolved: add godotenv dependency, load env vars from dotenv file, support dotenv local overrides, add security check for world readable files, integrate dotenv loading into main, add env file cli flags. Thirteen commits total, each one atomic and meaningful. Each commit is a story about one specific behavior being added.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Review Process
&lt;/h2&gt;

&lt;p&gt;After the implementation was done, I did a deep review of my own code. I found five issues that needed fixing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issue 1: Test Isolation (Critical)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tests were modifying the global environment without properly restoring it. If a test set &lt;code&gt;TEST_KEY=value&lt;/code&gt;, the cleanup would delete it, but what if that key already existed before the test ran? The cleanup wasn't restoring the original value, just removing the key. This breaks parallel test execution because tests can interfere with each other.&lt;/p&gt;

&lt;p&gt;The fix: create a helper function that saves the current state of environment variables before the test runs, then restores that exact state (including whether the variable existed at all) when the test completes. Now tests are safe to run in parallel. Committed with "add test environment isolation helper".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issue 2: Windows Test Bug (Critical)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One test needed to skip execution on Windows because file permission models are different. I had written the check incorrectly, reading from an environment variable instead of the language's built-in constant. This would break Windows CI. Small mistake, but important. Fixed and committed with "fix windows test skip to use runtime goos".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issue 3: Early Exit Timing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The .env loading was happening even for commands like &lt;code&gt;--help&lt;/code&gt; and &lt;code&gt;--version&lt;/code&gt;, which meant users could see security warnings when just checking the version. Moved the loading to happen after those early exits. Performance optimization and better user experience. Committed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issue 4: Error Context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When file operations failed, errors didn't indicate which file caused the problem. Added context wrapping so errors show the specific file path. Makes debugging much easier. Committed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issue 5: Test Coverage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One helper function didn't have its own test. Added coverage to bring the total to 84%. Committed.&lt;/p&gt;

&lt;p&gt;Each issue got its own fix, its own verification, its own commit. The same disciplined process for fixes that I used for features.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Manual Testing
&lt;/h2&gt;

&lt;p&gt;Code works in tests, but does it work for real users? I installed my version and created a test project to verify everything worked end-to-end.&lt;/p&gt;

&lt;p&gt;I created a &lt;code&gt;.env&lt;/code&gt; file with some variables, created a &lt;code&gt;.env.local&lt;/code&gt; file that overrode some of them, and made sure the permissions were correct with &lt;code&gt;chmod 600&lt;/code&gt;. Then I added a task to my &lt;code&gt;README.md&lt;/code&gt; to verify the variables were loaded:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In README.md:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## check-env&lt;/span&gt;

Check loaded environment variables.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;echo "Environment: $ENV"&lt;br&gt;
echo "Database: $DATABASE_URL"&lt;br&gt;
echo "API Key: ${API_KEY:0:8}..."&lt;/p&gt;

&lt;p&gt;When I ran &lt;code&gt;xc check-env&lt;/code&gt;, I saw exactly what I expected. The &lt;code&gt;xc&lt;/code&gt; command read the task from the README and executed it with the environment variables from &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;.env.local&lt;/code&gt;. The environment was set to "development" from the base .env, but the database URL and API key were overridden by .env.local. Perfect.&lt;/p&gt;

&lt;p&gt;I ran eight manual test scenarios: default .env loading, .env.local overrides, the –no-env flag skipping loading, –env-file loading a custom path, security warnings for world-readable files, task-level Env statements still working, –help not loading .env (avoiding unnecessary warnings), and a real-world multi-variable scenario. All eight passed.&lt;/p&gt;
&lt;h2&gt;
  
  
  The PR
&lt;/h2&gt;

&lt;p&gt;I submitted everything as &lt;a href="https://github.com/joerdav/xc/pull/167" rel="noopener noreferrer"&gt;PR #167&lt;/a&gt;. The changes included thirteen commits (eight for the feature, five for fixes), about 200 lines of code including tests, four unit tests plus six integration tests, 84% code coverage, and zero bugs found in manual testing.&lt;/p&gt;

&lt;p&gt;The documentation was complete with a README section showing examples, a &lt;code&gt;.env.example&lt;/code&gt; template file, the load order documented clearly, and security best practices explained. Most importantly, everything was backward compatible. Existing task-level &lt;code&gt;Env:&lt;/code&gt; statements still work exactly as before.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;.ai/&lt;/code&gt; folder was the game-changer. Instead of writing long prompts like "Build me a .env loader with security checks and…", I could just say "Implement the loader per ADR-001". The ADR contains all the decisions. AI just implements them.&lt;/p&gt;

&lt;p&gt;I used free models throughout. No expensive API calls. The key wasn't the model, it was the context. Clear architecture docs, explicit ADRs, and well-defined tests gave AI everything it needed to generate good code.&lt;/p&gt;

&lt;p&gt;TDD kept everything honest. Every cycle followed the same pattern: write a test that defines the behavior, let AI suggest an implementation, let the test validate it works, then commit. No guessing. No "it probably works." The test proves it.&lt;/p&gt;

&lt;p&gt;Thirteen commits might seem like a lot for 200 lines of code, but each commit serves a purpose. Each one is reviewable on its own. Each one tells part of the story. Each one is revertible if needed. Git bisect works perfectly with this kind of history.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.env.local&lt;/code&gt; override issue shows the workflow clearly. AI suggested the wrong approach first, using &lt;code&gt;Load()&lt;/code&gt; instead of &lt;code&gt;Overload()&lt;/code&gt;. But the test caught it. That's how it should work: AI suggests, test validates, human decides.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Real Value
&lt;/h2&gt;

&lt;p&gt;This isn't about "AI wrote code for me." It's about process, collaboration, and documentation.&lt;/p&gt;

&lt;p&gt;The process matters. Structured context in the &lt;code&gt;.ai/&lt;/code&gt; folder. Design decisions captured in ADRs. TDD discipline with tests written first. Small commits with one change at a time. This is how you ship production code.&lt;/p&gt;

&lt;p&gt;The collaboration matters. AI acts as a pair programmer, not a magic wand. Tests validate AI suggestions. Human makes the design decisions. Both contribute to better code.&lt;/p&gt;

&lt;p&gt;The documentation matters. Future contributors now have context about the project, the architecture, and why decisions were made the way they were. The implementation plan is explicit. The tests document the expected behavior. Six months from now, none of this is lost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The compounding matters most.&lt;/strong&gt; You build the foundation once. Every feature after that leverages it. The second feature doesn't need new &lt;code&gt;context.md&lt;/code&gt; or &lt;code&gt;rules/&lt;/code&gt; files, just a new ADR and task spec. The third feature is even faster. The documentation evolves as the codebase evolves. New ADRs when architecture changes. Updates to &lt;code&gt;context.md&lt;/code&gt; when understanding deepens. Updates to &lt;code&gt;rules/&lt;/code&gt; when patterns emerge. The investment pays dividends forever.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Want to replicate this process? Pick a project and create the &lt;code&gt;.ai/&lt;/code&gt; structure right in your working directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .ai/&lt;span class="o"&gt;{&lt;/span&gt;architecture/adrs,rules,tasks&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the &lt;a href="https://github.com/sudoish/xc/tree/ai-context/.ai" rel="noopener noreferrer"&gt;template structure&lt;/a&gt; as a guide. Build the foundation files once (&lt;code&gt;context.md&lt;/code&gt;, &lt;code&gt;architecture/decisions.md&lt;/code&gt;, &lt;code&gt;rules/&lt;/code&gt;), then for each feature add a new ADR and task spec. The &lt;code&gt;.ai/&lt;/code&gt; folder lives alongside your code and evolves with it—commit it with your changes so it stays in sync.&lt;/p&gt;

&lt;p&gt;Direct AI through TDD: "Implement test 1 from the spec." AI writes the test and implementation. "Run it." Test passes. "Commit." Repeat. When done, have AI review its own work, confirm findings, direct fixes. Then do your final review for strategic correctness.&lt;/p&gt;

&lt;p&gt;Each feature adds a new ADR and task spec to the &lt;code&gt;.ai/&lt;/code&gt; folder. The foundation files rarely change. The documentation compounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Full Timeline
&lt;/h2&gt;

&lt;p&gt;I spent about 45 minutes on documentation upfront: exploring the codebase with AI, questioning its understanding, writing the ADRs, rules, and context. This sounds like a lot, but it's a one-time investment. The &lt;code&gt;context.md&lt;/code&gt;, &lt;code&gt;architecture/decisions.md&lt;/code&gt;, and &lt;code&gt;rules/&lt;/code&gt; files I wrote for this first feature will be reused for every future feature. I'll only spend 10-15 minutes on feature-specific docs (ADR + task spec) for the next feature.&lt;/p&gt;

&lt;p&gt;The implementation took 40 minutes: directing AI through TDD cycles, one test at a time, validating each step. Integration of CLI flags and wiring into main.go took 15 minutes of the same directed approach. Documentation like README updates and examples took another 15 minutes. Manual testing took 15 minutes: I installed the binary and ran real scenarios. The review process took 30 minutes: first AI reviewed its own code (found 5 issues), then I reviewed the fixes, then I did a final deep review on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; AI wrote 100% of the code. I wrote 100% of the strategy, asked 100% of the questions, and made 100% of the decisions. I reviewed every line, but I didn't type any of them. Total time from fork to production-ready PR was about 2.5 hours.&lt;/p&gt;

&lt;p&gt;If I added a second feature tomorrow, it would take less time. By the third feature even faster. The documentation compounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;The complete &lt;code&gt;.ai/&lt;/code&gt; structure and documentation is at &lt;a href="https://github.com/sudoish/xc/tree/ai-context/.ai" rel="noopener noreferrer"&gt;github.com/sudoish/xc/tree/ai-context/.ai&lt;/a&gt;. The pull request with all code and tests is at &lt;a href="https://github.com/joerdav/xc/pull/167" rel="noopener noreferrer"&gt;github.com/joerdav/xc/pull/167&lt;/a&gt;. The working fork is at &lt;a href="https://github.com/sudoish/xc" rel="noopener noreferrer"&gt;github.com/sudoish/xc&lt;/a&gt;. The original issue is &lt;a href="https://github.com/joerdav/xc/issues/162" rel="noopener noreferrer"&gt;joerdav/xc#162&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;.ai/&lt;/code&gt; folder lives in a separate branch in this example only because I wanted to reference it for this article without including it in the PR to the upstream project. In your own work, keep the &lt;code&gt;.ai/&lt;/code&gt; folder in your main working branch and commit it with your changes—it should evolve alongside your code, not separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Skills That Actually Matter
&lt;/h2&gt;

&lt;p&gt;AI wrote every line of code. I read every line, but I didn't write any of them. The feature is production-ready because I focused on what actually matters.&lt;/p&gt;

&lt;p&gt;The four skills transformed from framework to practice: rapid onboarding through questioning AI and building structured context, strategic documentation through ADRs written before code, systematic planning through testable specs, and iterative review through AI self-checks followed by strategic verification.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.ai/&lt;/code&gt; folder, the ADRs, the task specs, the review cycles—they all worked exactly as planned. The result: 84% coverage, zero bugs, 2.5 hours from fork to production-ready PR.&lt;/p&gt;

&lt;p&gt;These skills work with free models. They work on unfamiliar codebases. They separate developers who use AI effectively from those who just generate code and hope it works.&lt;/p&gt;

&lt;p&gt;The magic isn't in the AI. It's in the process. And the process is this: &lt;strong&gt;you think, you plan, you direct, you review. AI executes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your Career
&lt;/h2&gt;

&lt;p&gt;The developer who can onboard to unfamiliar codebases fast, document decisions strategically, plan systematically, and execute with confidence is far more valuable than the developer who can write code quickly. Because here's the reality: &lt;strong&gt;code writing is no longer the bottleneck, it never was. AI just made this a lot more evident&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I shipped a production-ready feature to an unfamiliar codebase in 2.5 hours without writing a single line of code. The bottleneck wasn't typing. It was understanding, planning, and judging. Those are the skills that matter.&lt;/p&gt;

&lt;p&gt;AI tools are getting better at code generation every month. They're not getting better at understanding your codebase's architecture, making strategic trade-offs, or ensuring production quality. Those skills are still yours. Those skills are what companies pay for.&lt;/p&gt;

&lt;p&gt;The question isn't "Will AI replace developers?" It's "Which developers will thrive when everyone has access to AI?" The answer is the ones who master onboarding, documentation, planning, and review. The ones who understand that their job is no longer to write code—it's to think clearly, plan thoroughly, and judge correctly.&lt;/p&gt;

&lt;p&gt;This is the junior dev role being redefined. It's not about writing boilerplate anymore. That work is done. It's about learning systems fast, making good decisions, directing execution, and ensuring quality. If you can do that, you're not competing with AI. You're orchestrating it.&lt;/p&gt;

&lt;p&gt;Writing code is optional. Reading it, understanding it, and judging it—those aren't.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post documents a real open source contribution made using AI as a pair programmer. All code, tests, documentation, and the complete &lt;code&gt;.ai/&lt;/code&gt; folder structure are publicly available in the &lt;a href="https://github.com/sudoish/xc/tree/ai-context/.ai" rel="noopener noreferrer"&gt;sudoish/xc fork&lt;/a&gt; for anyone who wants to replicate this approach.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/ai-driven-development-xc-dotenv/" rel="noopener noreferrer"&gt;You Think, AI Executes: The Skills That Actually Matter&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>uncategorized</category>
      <category>ai</category>
      <category>developerskills</category>
      <category>developmentprocess</category>
    </item>
    <item>
      <title>How We Made It Nearly Impossible to Become a Developer</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Sun, 29 Mar 2026 16:47:08 +0000</pubDate>
      <link>https://forem.com/pacheco/how-we-made-it-nearly-impossible-to-become-a-developer-4oog</link>
      <guid>https://forem.com/pacheco/how-we-made-it-nearly-impossible-to-become-a-developer-4oog</guid>
      <description>&lt;p&gt;I once interviewed a senior software engineer. Almost 10 years of experience. Proven track record of delivery. Solid industry knowledge. The kind of person you’d want on your team without a second thought.&lt;/p&gt;

&lt;p&gt;They completed the technical challenge. Not flawlessly — there were considerations, trade-offs they made that weren’t all correct. But when we reviewed their decisions together, the reasoning was sound. They showed commitment to their choices and could articulate why they went the direction they did. Some answers were vague in spots, some mistakes were real, but nothing that wouldn’t get corrected in the first week on the job with actual codebase context. The kind of gaps that disappear when you’re working on real problems instead of performing in a vacuum.&lt;/p&gt;

&lt;p&gt;We didn’t hire them.&lt;/p&gt;

&lt;p&gt;Not because I didn’t want to. I did. But the compounded small mistakes added up under the scoring rubric, and the final grade wasn’t strong enough to sell to the hiring managers. The rules of the process made a good engineer look like a bad candidate.&lt;/p&gt;

&lt;p&gt;And I get it — those rules exist to keep the bar high, to ensure we only hire top talent. At least, that’s what every company believes. But what I’ve seen throughout my career, on both sides of the table, is that the process doesn’t filter for the best engineers. It filters for the best interviewers. And we lose great colleagues — dedicated, talented people — because they didn’t fit the rule book.&lt;/p&gt;

&lt;p&gt;That was a senior engineer with a decade of experience. Now imagine you’re a junior with none.&lt;/p&gt;

&lt;p&gt;The software industry has a hiring problem. Not the kind where we can’t find people — the kind where we’ve made it nearly impossible for new people to get in.&lt;/p&gt;

&lt;p&gt;Entry-level developer hiring has collapsed — some reports show drops of 60% or more in the past year, with actual hires into junior roles falling as much as 73%. CS graduates are sitting at 6.1% unemployment according to the Federal Reserve Bank of New York — more than double the overall national rate. And the majority of tech leaders say they plan to reduce entry-level hiring even further while increasing AI investment.&lt;/p&gt;

&lt;p&gt;But the pipeline didn’t break overnight. It’s been cracking for years. AI just kicked the door in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Interview Problem Nobody Wants to Fix
&lt;/h2&gt;

&lt;p&gt;The interview process was broken long before AI showed up. And I’ll say what a lot of people in the industry think but won’t say out loud: &lt;strong&gt;the standard software engineering interview process is unrealistic, unnecessarily demanding, and a terrible predictor of on-the-job performance.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think about what we ask candidates to do. Solve algorithmic puzzles on a whiteboard or shared screen. Explain their thought process in real time while simultaneously figuring out the solution. Design systems on the spot for problems they’ve never encountered in that specific framing. All while someone watches and judges every hesitation.&lt;/p&gt;

&lt;p&gt;Here’s the thing — that’s not how software development works. Not even close.&lt;/p&gt;

&lt;p&gt;Real engineering is focused, deep work. It’s sitting alone with a problem for hours, researching approaches, trying things, breaking things, iterating. It’s the exact opposite of performing under observation with a timer running. Most developers do their best work when they’re left alone to think. Asking them to showcase and explain how they’d deliver features while they’re still processing the problem doesn’t test their engineering ability. It tests their ability to perform under artificial pressure.&lt;/p&gt;

&lt;p&gt;And yet, this is how we gatekeep an entire profession.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Even a Principal Engineer Can’t Pass
&lt;/h2&gt;

&lt;p&gt;I have a close friend who’s a principal engineer. He’s delivered massive projects — systems that required intense complexity, heavy reliability, and serious scalability. The kind of work that keeps companies running. I’ve watched him turn down offers from companies that couldn’t skip the whiteboard stage. His track record speaks for itself, but he knows the process doesn’t.&lt;/p&gt;

&lt;p&gt;He straight up refuses to do technical interviews. Hates the process. Never performed well in them.&lt;/p&gt;

&lt;p&gt;But that wasn’t always the case. Early in his career, he had no choice. He went through the motions, sat through the whiteboard sessions, stumbled through the live coding exercises. And that’s exactly how he learned he was terrible at it. Not terrible at engineering — terrible at the performance.&lt;/p&gt;

&lt;p&gt;If a principal engineer with years of proven delivery struggles with this process, what does that tell us? It tells us we’re measuring the wrong thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Culture fit, communication, problem-solving mindset, willingness to learn — these should carry far more weight than whether someone can implement a binary tree traversal from memory while a stranger watches.&lt;/strong&gt; But the industry has standardized around LeetCode-style assessments like they’re some universal truth, and we’ve collectively decided that this is just how it works.&lt;/p&gt;

&lt;p&gt;It’s not. It’s a choice. And it’s a bad one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Wrong Skills at the Worst Time
&lt;/h2&gt;

&lt;p&gt;Here’s where it gets really damaging for juniors specifically.&lt;/p&gt;

&lt;p&gt;When you’re just starting your career, you have limited time, limited money, and unlimited pressure. The message the industry sends you is clear: grind LeetCode. Master data structures and algorithms. Practice system design for systems you’ve never built. Get good at performing.&lt;/p&gt;

&lt;p&gt;So that’s what people do. They spend months — sometimes six months or more — focused entirely on interview preparation instead of actually building things, learning real-world patterns, or developing the engineering intuition that makes someone genuinely valuable.&lt;/p&gt;

&lt;p&gt;We’re literally telling the next generation of developers to optimize for the wrong skills from day one. And then we wonder why new hires can’t navigate a real codebase.&lt;/p&gt;

&lt;p&gt;The industry has created a perverse incentive: &lt;strong&gt;becoming good at getting hired and becoming good at the job are two completely different skill paths.&lt;/strong&gt; And for juniors who are just figuring out what software engineering even is, being forced down the interview prep path first is actively harmful to their development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now Add AI to the Mix
&lt;/h2&gt;

&lt;p&gt;As if the interview gauntlet wasn’t enough, the industry just added a new requirement: you need to be proficient with AI tools.&lt;/p&gt;

&lt;p&gt;On the surface, this makes sense. AI-assisted development is becoming standard practice. Companies want developers who can leverage these tools effectively. Fair enough.&lt;/p&gt;

&lt;p&gt;But think about what we’re actually asking.&lt;/p&gt;

&lt;p&gt;Yes, some AI coding tools have free tiers now. GitHub Copilot has one. Cursor has a free plan. But if you’re just starting out — fresh from school, finishing a bootcamp, or self-teaching — do you even know that? The AI tooling landscape is an overwhelming mess of options, hype, and conflicting advice. Experienced developers struggle to keep up with what’s worth using. How is someone who’s still learning what a REST API is supposed to navigate that?&lt;/p&gt;

&lt;p&gt;And the free tiers only get you so far. The tools that companies actually expect proficiency in — Copilot Pro, Cursor Pro, Claude Pro — cost $10 to $20 per month each. If you want a serious AI-assisted workflow, you’re looking at $30-50/month minimum. That might not sound like much to someone employed, but when you’re unemployed, every dollar matters. Asking someone without income to pay for premium AI tools so they can develop the skills needed to get a job is a catch-22.&lt;/p&gt;

&lt;p&gt;There are too many unknowns when you’re starting out. Every conversation about AI in development assumes a baseline of knowledge and context that juniors simply don’t have yet. And instead of helping them build that foundation, we’re adding it to the list of things they need to figure out on their own before we’ll even consider hiring them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Senior Shortage Nobody Sees Coming
&lt;/h2&gt;

&lt;p&gt;Here’s the part that should terrify every tech leader who’s currently celebrating their AI-powered lean engineering team: &lt;strong&gt;you’re eating your seed corn.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It takes roughly 7 to 10 years to develop a senior engineer. Not just someone with “senior” in their title — someone who can architect systems, mentor teams, make judgment calls under uncertainty, and understand the business context of technical decisions. That kind of expertise doesn’t come from tutorials or AI tools. It comes from years of making mistakes, shipping real products, debugging production incidents at 2 AM, and slowly building the intuition that separates an engineer from someone who writes code.&lt;/p&gt;

&lt;p&gt;If we’re not hiring juniors now, we won’t have mid-level engineers in 3-5 years. And we won’t have seniors in 7-10 years.&lt;/p&gt;

&lt;p&gt;The Stanford Digital Economy Lab data already shows it: employment for software developers aged 22-25 has dropped roughly 20% since late 2022, while developers over 26 remain stable. The two groups tracked perfectly until ChatGPT launched, then diverged sharply. We’re watching the pipeline dry up in real time.&lt;/p&gt;

&lt;p&gt;And here’s the irony that makes it worse: companies are cutting juniors because they believe AI replaces what juniors did. But the data tells a different story. Google’s DORA 2024 report found that a 25% increase in AI adoption translated to just a 2% productivity gain — while executives at those same companies were telling their boards that AI had boosted output by 25%. The gap between measured reality and executive perception is staggering, and companies are making structural hiring decisions based on that perception, not the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Juniors were never just “cheap labor” who wrote boilerplate.&lt;/strong&gt; They stress-tested documentation. They exposed hidden assumptions in systems. They forced seniors to articulate knowledge that would otherwise stay implicit. They built institutional memory.&lt;/p&gt;

&lt;p&gt;A senior with Copilot can write code faster, sure — but faster code was never the bottleneck.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Squeeze
&lt;/h2&gt;

&lt;p&gt;So let’s put it all together. If you’re a junior developer in 2026, here’s your reality:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;There are barely any jobs for you.&lt;/strong&gt; Entry-level hiring has collapsed. Companies want seniors only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The jobs that exist demand more than ever.&lt;/strong&gt; The few junior roles left aren’t really junior anymore — they want 2-3 years of experience, AI proficiency, and system design knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The interview process is designed against you.&lt;/strong&gt; Months of LeetCode prep that teaches you nothing about real engineering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need tools you might not know exist or can’t afford.&lt;/strong&gt; AI proficiency is expected, but the landscape is overwhelming and the good stuff costs money you don’t have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The anxiety is crushing.&lt;/strong&gt; The pressure to be the best, to stand out in a market with fewer openings and more candidates, is driving people out before they even start.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And the result? People are giving up. Not because they can’t code. Not because they’re not smart enough. Because the path from “I want to be a software developer” to actually being one has become so hostile, so expensive, and so demoralizing that it’s not worth it anymore.&lt;/p&gt;

&lt;p&gt;Can you blame them?&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Needs to Change
&lt;/h2&gt;

&lt;p&gt;I don’t have a clean five-point solution. Anyone who does is selling something. But I know what direction we should be moving.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rethink interviews from the ground up.&lt;/strong&gt; Pair programming sessions, take-home projects with reasonable time limits, portfolio reviews, trial periods — there are better ways to assess ability than making people perform algorithms under pressure. If your interview process can’t distinguish between a great engineer who interviews poorly and a mediocre one who interviews well, the process is broken. Not the candidate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Invest in juniors as a strategic decision, not charity.&lt;/strong&gt; The companies that hire and develop juniors now will have the experienced engineers everyone else is desperate for in 2030. A handful of companies are already doubling down on junior hiring. They’re not being generous — they’re playing the long game while everyone else optimizes for this quarter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop pretending AI replaced the junior role.&lt;/strong&gt; It replaced the boilerplate. The questions juniors ask, the assumptions they challenge, the documentation they stress-test — that’s not automatable. If your team stopped growing because you thought Copilot could replace a curious 23-year-old, you’re going to feel that decision in five years.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Question
&lt;/h2&gt;

&lt;p&gt;The software industry has spent the last two decades complaining about a talent shortage. And now, faced with the largest pool of motivated CS graduates and career switchers in history, we’ve decided the best strategy is to lock the door and let AI handle it.&lt;/p&gt;

&lt;p&gt;If senior engineers can’t pass technical interviews, if junior roles demand senior skills, if the tools you need are buried in a landscape designed for people who already know what they’re doing, and if the entire process optimizes for performance over competence — then the pipeline isn’t just broken. We broke it. Deliberately, through a thousand small decisions that each seemed reasonable in isolation but collectively created a system that’s eating its own future.&lt;/p&gt;

&lt;p&gt;The question isn’t whether this will catch up with us. It’s whether we’ll have anyone left in the pipeline to fix it when it does.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/junior-developer-pipeline-broken/" rel="noopener noreferrer"&gt;How We Made It Nearly Impossible to Become a Developer&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>careergrowth</category>
    </item>
    <item>
      <title>The AI Productivity Lie Nobody Wants to Admit</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Sat, 28 Mar 2026 12:37:32 +0000</pubDate>
      <link>https://forem.com/pacheco/the-ai-productivity-lie-nobody-wants-to-admit-4a6o</link>
      <guid>https://forem.com/pacheco/the-ai-productivity-lie-nobody-wants-to-admit-4a6o</guid>
      <description>&lt;p&gt;I’ve been producing bad code. And it’s not because I forgot how to code.&lt;/p&gt;

&lt;p&gt;I’ve tried every workflow. Terminal agents, IDE copilots, full vibe coding, augmented coding. I keep exploring because that’s what I do — evaluate, keep what works, move on from what doesn’t.&lt;/p&gt;

&lt;p&gt;But here’s where I am right now: most of the time, it’s still more reliable for me to write the code myself than to let the agent do it.&lt;/p&gt;

&lt;p&gt;When the AI writes it, yes — it’s faster sometimes. But then I review it. I find things. I correct things. And suddenly I’m in a loop where I’m either spending more time than if I just did it myself, or the same time doing a more tedious version of the work. I’m not writing code anymore. I’m auditing code I didn’t write and don’t fully trust.&lt;/p&gt;

&lt;p&gt;And I’m starting to wonder what that’s doing to my engineering skills. Not because AI replaced them. Because the constant pressure to delegate everything is pulling me away from the deep thinking that built those skills in the first place.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pressure Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;The expectation to be dramatically more productive with AI is real. It’s coming from management, from Twitter, from inside your own head. Every demo makes it look like everyone else figured it out and you’re falling behind.&lt;/p&gt;

&lt;p&gt;And yeah — AI can be a huge boost. But only if you have perfect project structure, perfect product context, perfect documentation.&lt;/p&gt;

&lt;p&gt;That doesn’t exist. Not in any real codebase I’ve ever worked on.&lt;/p&gt;

&lt;p&gt;You know what exists? Legacy code. Tech debt. Patterns that were “temporary” three years ago. Business logic that lives in someone’s head and nowhere else.&lt;/p&gt;

&lt;p&gt;When you point an AI agent at that, it doesn’t fix the problems. It copies them. It amplifies them. It confidently reproduces your worst patterns at scale.&lt;/p&gt;

&lt;p&gt;So now you’re not just dealing with tech debt. You’re dealing with AI-generated tech debt that looks clean because the agent formatted it nicely.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Data That Should Make You Uncomfortable
&lt;/h2&gt;

&lt;p&gt;Here’s what made me feel less crazy about all of this. And each study hits harder than the last.&lt;/p&gt;

&lt;h3&gt;
  
  
  You’re Not Even Faster
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;METR&lt;/a&gt;, a nonprofit research organization, ran what might be the most rigorous study on this topic to date. They took 16 experienced open-source developers — people who maintain large repositories, averaging 22,000+ stars and over a million lines of code — and had them work on real issues in their own codebases. Real bugs, real features, real refactors. Not toy problems.&lt;/p&gt;

&lt;p&gt;Half the time they could use AI. Half the time they couldn’t.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result? When developers used AI tools, they took 19% longer to complete their tasks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not faster. Slower.&lt;/p&gt;

&lt;p&gt;But here’s the part that should genuinely unsettle you: before the study, these developers predicted AI would make them 24% faster. After using it — after actually experiencing the slowdown — they still believed AI had made them 20% faster.&lt;/p&gt;

&lt;p&gt;19% slower. Felt 20% faster. &lt;strong&gt;A 40 percentage point gap between perception and reality.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is what I call the speed mirage. You feel like you’re flying. The data says you’re walking backwards. And you can’t even tell.&lt;/p&gt;

&lt;h3&gt;
  
  
  You Understand Less of What You Ship
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.anthropic.com/research/AI-assistance-coding-skills" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, the company that makes Claude, ran a randomized controlled trial on their own tool. Developers using AI assistance scored &lt;strong&gt;17% lower on comprehension tests&lt;/strong&gt; compared to developers who coded manually. The AI group finished slightly faster, but that speed difference wasn’t even statistically significant.&lt;/p&gt;

&lt;p&gt;Marginal speed gain. Real understanding loss.&lt;/p&gt;

&lt;p&gt;It gets worse. The developers who delegated code generation to AI scored below 40% on comprehension. The ones who used AI for conceptual questions — asking “why” and “how does this work” — scored above 65%.&lt;/p&gt;

&lt;p&gt;Same tool. Completely different outcomes depending on how you used it. And the biggest gap was in debugging — the skill you need most when things break in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Industry Already Knows
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow’s 2025 Developer Survey&lt;/a&gt;: 84% of developers use or plan to use AI tools, but only 33% trust the output. Down from 43% the year before.&lt;/p&gt;

&lt;p&gt;Adoption up. Trust down.&lt;/p&gt;

&lt;p&gt;So we’re not faster. We understand less. And we don’t even trust what we ship. But we keep using it because everyone else seems to have figured it out.&lt;/p&gt;




&lt;h2&gt;
  
  
  Throughput vs. Confidence
&lt;/h2&gt;

&lt;p&gt;Let me name the thing clearly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The industry is optimizing for throughput when it should be optimizing for confidence.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Throughput is lines of code generated. PRs opened. Features “shipped.” It’s the metric that looks good on a dashboard and falls apart in production.&lt;/p&gt;

&lt;p&gt;Confidence is different. Do I understand what this code does? Do I trust it handles the edge cases? Can I debug it at 2 AM when something breaks?&lt;/p&gt;

&lt;p&gt;Vibe coding optimizes for throughput. You get a dopamine spike. You feel productive. And then you spend the rest of the day cleaning up after the machine.&lt;/p&gt;

&lt;p&gt;I’m not anti-AI. I use it every day. It’s incredible for researching tradeoffs, validating ideas, catching things I missed in review. When I use AI as a thinking partner, it genuinely makes me better.&lt;/p&gt;

&lt;p&gt;But when I use it as a coding replacement, it makes my output worse. And that’s the gap the industry isn’t willing to talk about.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Confidence Boundary
&lt;/h2&gt;

&lt;p&gt;So where does this leave us?&lt;/p&gt;

&lt;p&gt;I don’t have the perfect workflow. I’m not going to pretend I do. But I’ve been paying attention to what actually works, and the pattern is consistent.&lt;/p&gt;

&lt;p&gt;The developers getting the best results from AI aren’t the ones who figured out the perfect prompt. They’re the ones who figured out &lt;strong&gt;what to delegate and what to keep.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ve been calling this the confidence boundary.&lt;/p&gt;

&lt;p&gt;Here’s a real example. I had a feature to build recently. Instead of just opening the terminal and prompting the agent to do it, I stopped. I wrote the spec first. A clear, detailed explanation of what needed to be accomplished. The edge cases that the implementation had to survive. The constraints. The things I explicitly didn’t want.&lt;/p&gt;

&lt;p&gt;Then I handed that to the agent and let it implement against my spec.&lt;/p&gt;

&lt;p&gt;Because I did the thinking upfront, reviewing the output took minutes instead of hours. I knew exactly what should be there and what shouldn’t.&lt;/p&gt;

&lt;p&gt;But here’s the thing nobody tells you — and this is where it gets uncomfortable.&lt;/p&gt;

&lt;p&gt;To get a good result from the agent, you have to be &lt;em&gt;very&lt;/em&gt; specific. You’re writing a detailed spec, thinking through edge cases, defining constraints. And at some point you realize: &lt;strong&gt;for certain features, you’ve already done most of the hard work.&lt;/strong&gt; The thinking &lt;em&gt;is&lt;/em&gt; the work.&lt;/p&gt;

&lt;p&gt;At that point, it’s genuinely faster to just write the code yourself and use the agent as a pair reviewer to make sure you’re on the right track.&lt;/p&gt;

&lt;p&gt;Other times — boilerplate, scaffolding, repetitive patterns, implementations where the spec is clear and the risk is low — full delegation is absolutely the move. Hand the agent the guidance and let it run.&lt;/p&gt;

&lt;p&gt;The real skill isn’t prompting. It’s learning what to delegate and what to keep. And that judgment comes from understanding your codebase, the complexity of the task, and honestly — how much you trust the output for that specific context.&lt;/p&gt;

&lt;p&gt;The messier your codebase — legacy code, real tech debt, patterns with history the agent will never know — the more that judgment matters. The tooling is irrelevant. Neovim, Cursor, whatever. &lt;strong&gt;The bottleneck is you.&lt;/strong&gt; Whether you know where your confidence boundary is and whether you’re honest about it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bet I’m Making
&lt;/h2&gt;

&lt;p&gt;If you feel like AI is making you more productive but less confident in what you ship — you’re not falling behind. You’re paying attention.&lt;/p&gt;

&lt;p&gt;If your engineering skills feel soft because you keep delegating instead of thinking — that’s not paranoia. The research says it’s real.&lt;/p&gt;

&lt;p&gt;The speed mirage is powerful. It feels like progress. The dashboards say it’s progress. But if you can’t explain what you shipped, debug it when it breaks, or trust it handles the edge cases — that’s not progress. That’s debt with a nice commit message.&lt;/p&gt;

&lt;p&gt;I’m not quitting AI. I’m quitting the lie that it makes everything faster.&lt;/p&gt;

&lt;p&gt;The developers who are going to thrive aren’t the ones who ship more code. They’re the ones who learned what to keep and what to let go. Who built the judgment for when to delegate and when to do the work themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confidence over throughput.&lt;/strong&gt; That’s the bet I’m making.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;METR Study — AI slows experienced developers by 19%&lt;/a&gt; (&lt;a href="https://arxiv.org/abs/2507.09089" rel="noopener noreferrer"&gt;arXiv paper&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/research/AI-assistance-coding-skills" rel="noopener noreferrer"&gt;Anthropic Study — 17% comprehension loss with AI assistance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey — Trust declining&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://addyo.substack.com/p/avoiding-skill-atrophy-in-the-age" rel="noopener noreferrer"&gt;Addy Osmani on Skill Atrophy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.turingcollege.com/blog/agentic-engineering-vs-vibe-coding" rel="noopener noreferrer"&gt;Karpathy on Agentic Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.thoughtworks.com/en-us/insights/blog/agile-engineering-practices/spec-driven-development-unpacking-2025-new-engineering-practices" rel="noopener noreferrer"&gt;Thoughtworks on Spec-Driven Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/the-ai-productivity-lie-nobody-wants-to-admit-2/" rel="noopener noreferrer"&gt;The AI Productivity Lie Nobody Wants to Admit&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>developmentbestpract</category>
      <category>aicoding</category>
    </item>
    <item>
      <title>A Tale of Accidental Architecture: How 50 Lines Became A Black Friday Disaster</title>
      <dc:creator>Thiago Pacheco</dc:creator>
      <pubDate>Fri, 27 Feb 2026 04:26:03 +0000</pubDate>
      <link>https://forem.com/pacheco/a-tale-of-accidental-architecture-how-50-lines-became-a-black-friday-disaster-25cc</link>
      <guid>https://forem.com/pacheco/a-tale-of-accidental-architecture-how-50-lines-became-a-black-friday-disaster-25cc</guid>
      <description>&lt;p&gt;Let me tell you about Sarah.&lt;/p&gt;

&lt;p&gt;This is a fictional story. But I bet you’ll recognize it.&lt;/p&gt;

&lt;p&gt;I’ve seen this pattern play out across different companies, different teams, different tech stacks.  &lt;strong&gt;The details change. The progression doesn’t.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 1: The Perfect Start
&lt;/h2&gt;

&lt;p&gt;Sarah’s building a notification system for an e-commerce platform.&lt;/p&gt;

&lt;p&gt;First requirement: send an email when someone places an order.&lt;/p&gt;

&lt;p&gt;Simple. She writes one function. Webhook comes in, format the email, hit SMTP, done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The whole thing is maybe 50 lines.&lt;/strong&gt;  It works perfectly. Code review approves it. It ships.&lt;/p&gt;

&lt;p&gt;Sarah’s thinking: &lt;em&gt;“It’s just one notification type. I’ll add proper abstraction when we actually need it.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You’ve thought this too. So have I.&lt;/p&gt;

&lt;p&gt;Nothing wrong with it. Week 1, this is the right call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 3: The First Copy-Paste
&lt;/h2&gt;

&lt;p&gt;Product team loves the email notifications. Now they want SMS for order shipments.&lt;/p&gt;

&lt;p&gt;Mike picks up the ticket.&lt;/p&gt;

&lt;p&gt;He opens Sarah’s code. Sees the pattern.  &lt;strong&gt;Makes sense.&lt;/strong&gt;  He follows it.&lt;/p&gt;

&lt;p&gt;New handler. Receives the shipment webhook. Formats the SMS message. Connects to Twilio. Sends it.&lt;/p&gt;

&lt;p&gt;He copies some of Sarah’s email formatting logic because customers should see consistent information. Has to adjust it for the 160-character SMS limit, but the core logic is the same.&lt;/p&gt;

&lt;p&gt;Mike’s thinking: &lt;em&gt;“There’s some duplication with the email code, but SMS is different enough that abstracting it would be premature. It’s only two notification types.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deadline is tomorrow.&lt;/strong&gt;  This ships.&lt;/p&gt;

&lt;p&gt;Still nothing catastrophically wrong here. Two types, small duplication, it’s manageable.&lt;/p&gt;

&lt;p&gt;Right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 5: User Preferences
&lt;/h2&gt;

&lt;p&gt;Customers start complaining.&lt;/p&gt;

&lt;p&gt;“I don’t want SMS notifications.”&lt;/p&gt;

&lt;p&gt;“Why am I getting emails for every status change?”&lt;/p&gt;

&lt;p&gt;Sarah adds user preferences. Creates a database table. Updates her email handler to check if the user wants that particular notification before sending.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The handler triples in size.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Query the database. Check multiple preference flags. Handle the case where preferences don’t exist yet. Default values. Edge cases.&lt;/p&gt;

&lt;p&gt;Sarah’s thinking: &lt;em&gt;“This is getting messy, but the deadline is tomorrow and this works. I’ll refactor it next sprint.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I cannot tell you how many times I’ve heard “next sprint.”&lt;/p&gt;

&lt;p&gt;(Spoiler: next sprint never comes.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhzgu3hiae5nlit5zn7l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhzgu3hiae5nlit5zn7l.gif" alt="This is fine dog meme - developer ignoring growing problems" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 7: Two Ways to Do Everything
&lt;/h2&gt;

&lt;p&gt;Mike needs to add notifications for order cancellations and delivery confirmations.&lt;/p&gt;

&lt;p&gt;He realizes hardcoding email bodies isn’t going to scale.&lt;/p&gt;

&lt;p&gt;So he builds a template system. Creates a templates directory. Writes a simple renderer. Updates his handlers to load templates, populate data, send.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s actually pretty clean.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Meanwhile, Sarah’s handlers still use string formatting. She doesn’t know Mike built a template system. Mike didn’t announce it in Slack. It just… exists now.&lt;/p&gt;

&lt;p&gt;The codebase now has  &lt;strong&gt;two different ways of generating notification content.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sarah finds out later. Thinks: &lt;em&gt;“I should probably switch to Mike’s templates… but my code is working and I’m slammed with other features.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And she is. Three new features this sprint. No time to refactor working code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 9: The Third Approach
&lt;/h2&gt;

&lt;p&gt;Emma joins the team.&lt;/p&gt;

&lt;p&gt;First task: add Slack notifications for the support team when high-value orders come in.&lt;/p&gt;

&lt;p&gt;She opens the notification code. Finds Sarah’s inline approach. Finds Mike’s templates.  &lt;strong&gt;Neither makes sense for Slack.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Slack needs structured JSON payloads, not formatted text.&lt;/p&gt;

&lt;p&gt;So Emma does what any good engineer would do: she creates a  &lt;strong&gt;“proper solution”.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Notification service class. Methods for each notification type. Handles destination-specific formatting internally. Clean. Testable. Well-designed.&lt;/p&gt;

&lt;p&gt;She shows it to the team in standup.&lt;/p&gt;

&lt;p&gt;Mike: &lt;em&gt;“That’s nice, but I don’t have time to refactor my SMS code right now. Maybe later.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sarah: &lt;em&gt;“I like it, but my code has been running in production for months. If it ain’t broke…”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Emma’s service class gets used for Slack notifications.  &lt;strong&gt;Nothing else changes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now there are three ways to send notifications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj49li7kl1vg74rp29yei.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj49li7kl1vg74rp29yei.gif" alt="Spider-Man pointing meme - three developers with different approaches" width="498" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 12: The Chaos Compounds
&lt;/h2&gt;

&lt;p&gt;Product wants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Push notifications for the mobile app&lt;/li&gt;
&lt;li&gt;Digest emails (daily order summaries)&lt;/li&gt;
&lt;li&gt;Ability to snooze notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three developers. Three features. Same week.&lt;/p&gt;

&lt;p&gt;Each one discovers the existing fragmentation. Each one makes their own call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer A&lt;/strong&gt;  tries to extend Sarah’s inline approach. Adds push notification logic directly in the handler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer B&lt;/strong&gt;  uses Mike’s templates but creates a  &lt;strong&gt;new template format&lt;/strong&gt;  because the existing one doesn’t support digest layouts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer C&lt;/strong&gt;  tries to use Emma’s service class but realizes it doesn’t handle scheduling or snoozing. So they add that logic directly in their handler instead.&lt;/p&gt;

&lt;p&gt;The notification preferences table is now being updated by  &lt;strong&gt;five different code paths.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each developer added their own columns because they didn’t realize others had added similar fields. One stores preferences as JSON. Another uses boolean columns. Another created a  &lt;strong&gt;separate preferences table&lt;/strong&gt;  with foreign keys.&lt;/p&gt;

&lt;p&gt;I’ve seen this code review happen. Every PR gets approved. Every piece of code works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nobody did anything wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And yet.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Every PR got approved. Every piece of code worked. Nobody did anything wrong. And yet.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Week 15: Customer Complaints
&lt;/h2&gt;

&lt;p&gt;Support tickets start flooding in.&lt;/p&gt;

&lt;p&gt;“I’m getting duplicate notifications.”&lt;/p&gt;

&lt;p&gt;“I disabled email but I’m still getting them.”&lt;/p&gt;

&lt;p&gt;“I’m not getting notifications at all for important orders.”&lt;/p&gt;

&lt;p&gt;Sarah investigates. Opens the codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Six different code paths handle notifications.&lt;/strong&gt;  Some check preferences before sending. Some check during sending. Some don’t check at all because the developer assumed another layer was handling it.&lt;/p&gt;

&lt;p&gt;She finds the bug. It’s in her original email handler. The preference check is wrong.&lt;/p&gt;

&lt;p&gt;She fixes it. Deploys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three other notification types break.&lt;/strong&gt;  They were relying on her buggy behavior.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapyzb9u5k536v4qidesn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapyzb9u5k536v4qidesn.gif" alt="Domino effect - one bug fix breaks three other features" width="480" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The team estimate to fix it properly: &lt;em&gt;“We need to stop and refactor everything first, or we’ll just make it worse.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Management: “We don’t have time for a refactor. Just fix the bugs.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 17: The Template Nightmare
&lt;/h2&gt;

&lt;p&gt;Marketing wants to update email designs. New brand guidelines.&lt;/p&gt;

&lt;p&gt;The developer assigned to this opens the codebase.&lt;/p&gt;

&lt;p&gt;Templates are  &lt;strong&gt;everywhere.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some in a &lt;code&gt;/templates&lt;/code&gt; directory. Some hardcoded as strings. Some in the database. Some fetched from an external CMS that one developer integrated without telling anyone.&lt;/p&gt;

&lt;p&gt;There’s no single source of truth.&lt;/p&gt;

&lt;p&gt;Worse: the data passed to templates is completely inconsistent.&lt;/p&gt;

&lt;p&gt;Email templates expect order objects with certain fields. SMS templates expect a flattened structure. Push notifications expect a completely different format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One design change requires touching dozens of files.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The developer estimates: “Two weeks, maybe three.”&lt;/p&gt;

&lt;p&gt;Marketing: “It’s just a design update. How is that two weeks?”&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 20: Performance Crisis
&lt;/h2&gt;

&lt;p&gt;Black Friday.&lt;/p&gt;

&lt;p&gt;The system crashes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlrdt9uxnezf4h3w7irz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlrdt9uxnezf4h3w7irz.gif" alt="Everything is on fire - Black Friday system crash" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Investigation reveals: notification handlers are opening new database connections for  &lt;strong&gt;every single notification sent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some handlers properly close connections. Some don’t.&lt;/p&gt;

&lt;p&gt;Connection pools exhausted. Some handlers retry failed sends immediately and indefinitely,  &lt;strong&gt;amplifying the problem during the outage.&lt;/strong&gt;  One handler spawns a goroutine for each notification but never limits concurrency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The server runs out of memory processing a batch of 10,000 order confirmations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Different developers made different assumptions about error handling.&lt;/p&gt;

&lt;p&gt;Some silently swallow errors and log them. Some retry with exponential backoff. Some fail fast. Some store failed notifications in one database table for retry. Others use a different table. One developer integrated a third-party queue system  &lt;strong&gt;that nobody else knew existed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Notifications are getting lost between these systems.&lt;/p&gt;

&lt;p&gt;I’ve been on calls where the CTO asks: “How many notification systems do we have?”&lt;/p&gt;

&lt;p&gt;Nobody can answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 24: The Audit
&lt;/h2&gt;

&lt;p&gt;Compliance team asks a simple question:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Can you show us a record of all notifications sent to customer X in the past 90 days?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The team cannot answer this.&lt;/p&gt;

&lt;p&gt;Notification logs are  &lt;strong&gt;scattered everywhere.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some handlers log to stdout. Some to files. Some to a database table. Some don’t log at all.&lt;/p&gt;

&lt;p&gt;The log formats are completely different. Some include the full message content. Some just log “notification sent” without details. There’s no correlation between the notification and the triggering event.&lt;/p&gt;

&lt;p&gt;The auditor asks: &lt;em&gt;“How do you ensure notifications contain required legal disclosures?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each template was created independently. Some include required legal text. Some don’t.  &lt;strong&gt;There’s no centralized enforcement.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ve seen this audit happen. Teams spend weeks reconstructing logs manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Breaking Point
&lt;/h2&gt;

&lt;p&gt;VP of Engineering asks for a simple feature:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Add an unsubscribe link to all emails.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The team estimates:  &lt;strong&gt;Three weeks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The VP is shocked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3dybxptm7pxoqd6d67t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3dybxptm7pxoqd6d67t.gif" alt="Shocked reaction - three weeks to add an unsubscribe link?!" width="195" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;“It’s just adding a link. How is that three weeks of work?”&lt;/p&gt;

&lt;p&gt;The tech lead explains:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“We have seven different code paths that send emails. Each uses a different templating system. Some render templates on the server. Some fetch them from external systems. Some are hardcoded strings. We need to update each one individually, ensure the unsubscribe logic is consistent across all of them, add tracking for unsubscribe events, update the preferences system to handle unsubscribes properly, and test everything thoroughly because there’s no centralized testing strategy.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Three weeks. For a link.&lt;/p&gt;

&lt;p&gt;The VP asks the obvious question:  &lt;strong&gt;“How did it get this bad?”&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Went Wrong?
&lt;/h2&gt;

&lt;p&gt;Here’s the thing that kills me about this story.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nobody made a catastrophically bad decision.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sarah’s Week 1 implementation was appropriate. Mike’s template system was a reasonable improvement. Emma’s service class was a genuine attempt to bring order.&lt;/p&gt;

&lt;p&gt;Every single developer was trying to do good work under deadline pressure.&lt;/p&gt;

&lt;p&gt;The problem wasn’t the individual decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It was the absence of a shared architectural vision.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without clear boundaries and layers, each developer made reasonable local optimizations that created global chaos.&lt;/p&gt;

&lt;p&gt;The “I’ll refactor it later” moments never came because there was never a good time to stop feature development.&lt;/p&gt;

&lt;p&gt;The “let’s standardize this” conversations happened but never resulted in action because no one had time to migrate existing code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The codebase evolved organically.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And organic growth without structure doesn’t produce a garden. It produces a weed-infested lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  “But This Is Just a Communication Problem”
&lt;/h2&gt;

&lt;p&gt;You might be thinking: the real issue was that developers didn’t communicate.&lt;/p&gt;

&lt;p&gt;If Sarah and Mike had talked, they wouldn’t have built two different templating systems. If Emma had socialized her service class better, others would have adopted it.&lt;/p&gt;

&lt;p&gt;Better standups. Better code reviews. Better documentation.  &lt;strong&gt;That’s&lt;/strong&gt;  what was missing, not architecture.&lt;/p&gt;

&lt;p&gt;This is seductive because it’s partially true.&lt;/p&gt;

&lt;p&gt;But here’s why it misses the point:  &lt;strong&gt;architecture IS communication.&lt;/strong&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Architecture IS communication. It’s the most important form of communication for technical decisions.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;It’s the most important form of communication for technical decisions.&lt;/p&gt;

&lt;p&gt;Think about what actually happened in the story.&lt;/p&gt;

&lt;p&gt;The team  &lt;strong&gt;DID communicate.&lt;/strong&gt;  Mike showed his template system in code review. Emma presented her service class and got positive feedback. They had a meeting in Week 11 trying to align on standards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The communication happened.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What didn’t happen was turning those conversations into durable, enforceable decisions.&lt;/p&gt;

&lt;p&gt;This is the key difference:&lt;/p&gt;

&lt;p&gt;Conversation says &lt;em&gt;“we should probably do X.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Architecture says &lt;em&gt;“X is how we do things here, and here’s where it lives.”&lt;/em&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Conversation is ephemeral. Architecture is the artifact that persists after the meeting ends.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;When a new developer joins and asks “where should notification logic go?”, the answer shouldn’t require scheduling a meeting or hunting through Slack history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It should be obvious from looking at the codebase.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Communication without architecture leads to the problem Emma faced. She built something good. People agreed it was good. And then…  &lt;strong&gt;nothing changed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without architectural decisions being explicitly made (&lt;em&gt;“from now on, all notifications go through NotificationService”&lt;/em&gt;), the good idea just becomes another option in an increasingly fragmented codebase.&lt;/p&gt;

&lt;p&gt;Good communication can prevent chaos. But it can’t survive bad processes.&lt;/p&gt;

&lt;p&gt;When developers are under deadline pressure, working on different features, joining the team at different times,  &lt;strong&gt;communication will have gaps.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Architecture is the safety net for when communication fails.&lt;/p&gt;

&lt;p&gt;It’s the shared context that makes it possible to work somewhat independently without creating complete divergence.&lt;/p&gt;

&lt;p&gt;So yes, the team in our story could have communicated better.&lt;/p&gt;

&lt;p&gt;But the solution isn’t &lt;em&gt;“communicate more.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s “communicate the architecture and make it stick.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Document where things belong. Make architectural decisions explicit. Enforce them in code review. Build structure that persists beyond any individual conversation.&lt;/p&gt;

&lt;p&gt;Because at the end of the day, you can have all the Slack channels and standups and retros you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without a shared architectural foundation, you’re just having the same conversations over and over while the codebase continues to fragment.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Should Have Happened in Week 1
&lt;/h2&gt;

&lt;p&gt;Sarah should have spent 30 minutes writing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Notification System Architecture

## Where Things Live
- All notification logic → services/notification_service.py
- Templates → templates/ directory (Jinja2 format)
- Preference checks → services/preference_service.py
- Delivery logging → notification_log table

## How to Add a New Notification Type
1. Add template to templates/
2. Add method to NotificationService
3. Log delivery attempt (success or failure)
4. Add tests to test_notification_service.py

## Error Handling
- Retries: 3 attempts with exponential backoff (1s, 2s, 4s)
- Failed sends → dead_letter_queue table
- All errors logged with correlation ID

## Preferences
- Check preferences BEFORE sending (not during)
- Default: all notifications enabled
- Unsubscribe → set all preferences to false

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That’s it.&lt;/strong&gt;  30 minutes of work. Would have saved months of chaos.&lt;/p&gt;




&lt;p&gt;When Mike added SMS in Week 3, he would have known where to put it. When Emma added Slack in Week 9, she would have followed the existing pattern. When three developers worked simultaneously in Week 12, they would have made consistent decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not because they communicated better. Because the architecture communicated for them.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pattern You’ve Seen Before
&lt;/h2&gt;

&lt;p&gt;I’ve seen this exact pattern play out at least a dozen times.&lt;/p&gt;

&lt;p&gt;Different companies. Different tech stacks. Different teams. Different features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pattern is always the same.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Week 1: Clean, working code.&lt;/p&gt;

&lt;p&gt;Week 3: Small duplication appears.&lt;/p&gt;

&lt;p&gt;Week 7: Multiple approaches emerge.&lt;/p&gt;

&lt;p&gt;Week 12: Chaos compounds.&lt;/p&gt;

&lt;p&gt;Month 6: Simple changes take weeks.&lt;/p&gt;

&lt;p&gt;The timeline varies. Sometimes it happens faster (AI accelerates it). Sometimes slower (disciplined team delays it). But without architecture,  &lt;strong&gt;the destination is always the same.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Then AI Showed Up and Made Everything 10x Worse
&lt;/h2&gt;

&lt;p&gt;Everything I just described? It’s been happening for decades.&lt;/p&gt;

&lt;p&gt;Slow burn. Predictable. Manageable if you catch it early.&lt;/p&gt;

&lt;p&gt;Then 2024 happened.&lt;/p&gt;

&lt;p&gt;AI coding assistants arrived. And they turned architectural decay from a slow burn into a  &lt;strong&gt;wildfire.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Replicates. It Doesn’t Invent.
&lt;/h3&gt;

&lt;p&gt;Here’s what changed.&lt;/p&gt;

&lt;p&gt;When Mike needed to add SMS in Week 3, he opened Sarah’s code.  &lt;strong&gt;Looked at it.&lt;/strong&gt;  Made a decision. Maybe he copied the pattern. Maybe he tried something different.&lt;/p&gt;

&lt;p&gt;But he  &lt;strong&gt;thought&lt;/strong&gt;  about it.&lt;/p&gt;

&lt;p&gt;Now imagine Mike has Cursor. Or Copilot. Or Claude Code.&lt;/p&gt;

&lt;p&gt;He types: &lt;code&gt;// Add SMS notification for shipments&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The AI looks at the codebase. Sees Sarah’s pattern.  &lt;strong&gt;Instantly replicates it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Code appears. Mike reviews it. Looks good. Ships.&lt;/p&gt;

&lt;p&gt;He never even saw the architectural decision being made.&lt;/p&gt;

&lt;p&gt;The AI made it for him. Based on what already existed.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“AI doesn’t just copy your code. It copies your architecture. Even the accidental parts.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  The Speed and Scale Just Exploded
&lt;/h3&gt;

&lt;p&gt;Remember Week 12? Three developers, three features, three different approaches emerging over a week?&lt;/p&gt;

&lt;p&gt;With AI,  &lt;strong&gt;that’s Tuesday.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Developer A asks AI for push notifications. AI sees Sarah’s inline handler. Copies it.&lt;/p&gt;

&lt;p&gt;Developer B asks AI for digest emails. AI sees Mike’s templates. Copies those.&lt;/p&gt;

&lt;p&gt;Developer C asks AI for snoozing. AI sees Emma’s service class. Copies that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All three features ship the same day.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But it’s not just faster. It’s  &lt;strong&gt;bigger.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pre-AI: 50-200 lines of code per day.&lt;/p&gt;

&lt;p&gt;With AI: 500-2000 lines in the same time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That’s 5-10x more code&lt;/strong&gt;  implementing patterns, creating variations, spreading duplication.&lt;/p&gt;

&lt;p&gt;You have two ways of checking preferences? AI propagates both. Three error handling approaches? AI replicates all three.  &lt;strong&gt;Every inconsistency becomes a seed that AI plants everywhere.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The notification system that took Sarah’s team 20 weeks to become unmaintainable?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With AI, you can get there in 4.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Can’t See What You Didn’t Write Down
&lt;/h3&gt;

&lt;p&gt;Here’s the fundamental problem.&lt;/p&gt;

&lt;p&gt;AI is  &lt;strong&gt;incredible&lt;/strong&gt;  at implementation. It can write clean, working code. It follows patterns. It handles edge cases.&lt;/p&gt;

&lt;p&gt;But it cannot  &lt;strong&gt;architect.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It can’t look at your codebase and think: &lt;em&gt;“Wait, this is getting fragmented. We should consolidate these patterns.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It can’t say: &lt;em&gt;“I see three different approaches here. Which one should I follow?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It just… picks one. Based on similarity to what you’re asking for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If your architecture is accidental, AI accelerates the accident.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Old Advice Is Now Dangerous
&lt;/h3&gt;

&lt;p&gt;The advice used to be: &lt;em&gt;“Don’t over-architect small projects. Start simple. Refactor when you need to.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That advice just became  &lt;strong&gt;dangerous.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With AI, “small projects” don’t stay small. They  &lt;strong&gt;explode.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By the time you realize you need to refactor, you have 10x more code to untangle.&lt;/p&gt;

&lt;p&gt;The window between “clean start” and “architectural debt crisis” collapsed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 1 decisions matter more than ever.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can’t afford to defer architecture anymore.&lt;/p&gt;

&lt;h3&gt;
  
  
  But Here’s the Good News
&lt;/h3&gt;

&lt;p&gt;The same force that amplifies chaos can amplify  &lt;strong&gt;order.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI replicates good patterns just as enthusiastically as bad ones.&lt;/p&gt;

&lt;p&gt;If you write that architecture document in Week 1. If you establish clear boundaries. If you make the “right way” obvious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI will follow it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consistently. Every single time. Across every feature.&lt;/p&gt;

&lt;p&gt;It will use your NotificationService. It will follow your template structure. It will implement your error handling exactly as specified.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At scale. At speed. Without deviation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The chaos multiplier becomes a  &lt;strong&gt;consistency multiplier.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But only if you give it something consistent to multiply.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“AI doesn’t make architecture optional. It makes it mandatory.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;This is why the next post matters even more now.&lt;/p&gt;

&lt;p&gt;I’ll show you how to set up that architectural foundation  &lt;strong&gt;before&lt;/strong&gt;  you start generating code with AI.&lt;/p&gt;

&lt;p&gt;How to make the right patterns so obvious that AI can’t help but follow them.&lt;/p&gt;

&lt;p&gt;How to turn AI from an architectural time bomb into an architectural enforcement mechanism.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;In the next post, I’ll show you how to build that architectural foundation.&lt;/p&gt;

&lt;p&gt;Not some enterprise framework. Not over-engineered complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The simple, practical structure that prevents this chaos.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ll rebuild this exact notification system with clear boundaries, testable code, and patterns that guide developers toward consistency instead of fragmentation.&lt;/p&gt;

&lt;p&gt;You’ll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where things live (and why)&lt;/li&gt;
&lt;li&gt;How to test without infrastructure&lt;/li&gt;
&lt;li&gt;How to make architectural decisions stick&lt;/li&gt;
&lt;li&gt;How AI helps instead of amplifying chaos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until then, look at your codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What week are you on?&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you lived through this story? I’d love to hear about it. Find me on &lt;a href="https://twitter.com/pachecot" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://linkedin.com/in/pachecothiago" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sudoish.com/a-tale-of-accidental-architecture-how-50-lines-became-a-black-friday-disaster/" rel="noopener noreferrer"&gt;A Tale of Accidental Architecture: How 50 Lines Became A Black Friday Disaster&lt;/a&gt; appeared first on &lt;a href="https://sudoish.com" rel="noopener noreferrer"&gt;sudoish&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>uncategorized</category>
      <category>accidentalarchitectu</category>
      <category>codequality</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
