<?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>DEV Community: Philip Hern</title>
    <description>The latest articles on DEV Community by Philip Hern (@shrouwoods).</description>
    <link>https://dev.to/shrouwoods</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3858493%2F9a8ff83c-d5c3-493f-9943-b91a2f0a61d8.jpg</url>
      <title>DEV Community: Philip Hern</title>
      <link>https://dev.to/shrouwoods</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shrouwoods"/>
    <language>en</language>
    <item>
      <title>continuity</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Thu, 05 Nov 2026 13:57:24 +0000</pubDate>
      <link>https://dev.to/shrouwoods/continuity-4dof</link>
      <guid>https://dev.to/shrouwoods/continuity-4dof</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;continuity is more important than perfection. that is the reminder i am writing for myself about this website and the other long threads i care about. i want to keep putting in work, but i also need to stop treating every pause like the end of the story.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;continuity does not equal continuous. i mean that i intend to keep coming back to the site over time, not that i have to touch it every day without a gap. breaks are ok as long as i pick back up where i left off. the trouble is that i often feel like a long break equals quitting, so when something has been sitting too long i talk myself out of returning at all. that pattern wastes the effort i already put in and turns a rest into an unintentional exit.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;h3&gt;
  
  
  perfection is the wrong scoreboard
&lt;/h3&gt;

&lt;p&gt;when perfection is the bar, any stretch of time without production looks like failure. continuity is a gentler measure. did i come back? did i add another piece when i had something worth saying? that is enough. the site does not need every post to be polished into something i would publish in a book. it needs me to stay in the habit of returning.&lt;/p&gt;

&lt;h3&gt;
  
  
  the space between is not empty
&lt;/h3&gt;

&lt;p&gt;sometimes good ideas and renewed motivation come from the space in between. i need to embrace that more instead of punishing myself for the breaks. distance is not always drift. it can be where the next sentence forms, the same way i wrote about &lt;a href="https://philliant.com/posts/20260606-room-to-breathe/" rel="noopener noreferrer"&gt;room to breathe&lt;/a&gt; in a different context. rest and return can belong to the same project without canceling each other out.&lt;/p&gt;

&lt;h3&gt;
  
  
  tension or counterpoint
&lt;/h3&gt;

&lt;p&gt;the point here is to stop equating a long break with quitting, so i actually come back. i have already lived the healthier version of this once, in &lt;a href="https://philliant.com/posts/20260422-back-at-it/" rel="noopener noreferrer"&gt;back at it&lt;/a&gt;, after a heavy lift where stepping away on purpose let me continue with a clearer head. i want that pattern for the website too.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;so this is the note. keep up the effort, but let the breaks be real breaks. come back when there is something to say. continuity beats perfection, and coming back after a long pause still counts as continuity. this is the standard that i aspire to.&lt;/p&gt;

&lt;h2&gt;
  
  
  related on this site
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260416-stick-with-it/" rel="noopener noreferrer"&gt;stick with it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260606-room-to-breathe/" rel="noopener noreferrer"&gt;room to breathe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260422-back-at-it/" rel="noopener noreferrer"&gt;back at it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/series/commentary/" rel="noopener noreferrer"&gt;commentary series&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>continuity</category>
      <category>persistence</category>
      <category>rest</category>
      <category>selftalk</category>
    </item>
    <item>
      <title>a polyerudite notebook</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Sun, 01 Nov 2026 13:24:35 +0000</pubDate>
      <link>https://dev.to/shrouwoods/a-polyerudite-notebook-2e54</link>
      <guid>https://dev.to/shrouwoods/a-polyerudite-notebook-2e54</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;i updated &lt;a href="https://philliant.com/about/" rel="noopener noreferrer"&gt;about&lt;/a&gt; on philliant. same site, same name. i just wanted the about description to match how i actually want to write.&lt;/p&gt;

&lt;p&gt;i call it a &lt;strong&gt;polyerudite&lt;/strong&gt; notebook, my word for many subjects and trying to understand them before i publish. i will keep writing about work when something comes up. but i also wanted to create space for everything else i care about, because i have a lot of interests and they change all the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;most of what i published here for a while was work related. data platforms, agents, the tools i use on the job. that is still true a lot of weeks, and i am not throwing any of it away.&lt;/p&gt;

&lt;p&gt;what felt off was the about page, which made it sound like work was the only reason i post, which has never been fully accurate. i had already written about rest, travel, art, and a dozen other things that did not fit a single professional headline.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;p&gt;nothing big changed under the hood. &lt;a href="https://philliant.com/posts/20260824-full-disclosure-regarding-this-website-and-my-writing/" rel="noopener noreferrer"&gt;full disclosure regarding this website and my writing&lt;/a&gt; still applies. ai helps, i review, i ship what i stand behind. old posts stay where they are.&lt;/p&gt;

&lt;p&gt;the shift is my stated direction. the next post might be about ci. it might be about a book i cannot stop thinking about or a trip i needed. i do not want to talk myself out of a topic because it is not "on brand" for data engineering.&lt;/p&gt;

&lt;h3&gt;
  
  
  tension or counterpoint
&lt;/h3&gt;

&lt;p&gt;some readers will land on one technical post and expect only that lane forever. i am ok with that. philliant was always a notebook first. it just spent a long season deep on work.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;i will know if this was the right call by writing into it. for today, updating about was enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  related on this site
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260918-the-struggle-is-where-the-posts-come-from/" rel="noopener noreferrer"&gt;the struggle is where the posts come from&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>writing</category>
      <category>site</category>
      <category>commentary</category>
    </item>
    <item>
      <title>who did the work?</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Tue, 27 Oct 2026 13:10:43 +0000</pubDate>
      <link>https://dev.to/shrouwoods/who-did-the-work-1cob</link>
      <guid>https://dev.to/shrouwoods/who-did-the-work-1cob</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;i steer the ai, but the ai does almost all of the execution on this site. i still read the diffs and i still own what ships, but the line between my labor and the model's output keeps blurring.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;i said in &lt;a href="https://philliant.com/posts/20260824-full-disclosure-regarding-this-website-and-my-writing/" rel="noopener noreferrer"&gt;full disclosure regarding this website and my writing&lt;/a&gt; that the site is ai-assisted. i meant i outline, draft, and steer while the ai helps with code and maintenance. that is still true.&lt;/p&gt;

&lt;p&gt;the website layer is now almost entirely ai-maintained on my instructions, but the same pattern has crept into content. i let agents revise old posts, fix formatting, and sweep the archive. the diffs are bigger than what i would have done by hand in a single sitting. at my day job i use ai for trivial changes too, one-line fixes i used to type without thinking. the keystrokes are the model's. the merge is mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;p&gt;who is the architect and owner of this site if i steer but rarely type? my name is on it. the hugo config, ci, lint rules, and cursor skills are mostly agent work i review. when the build breaks, i often ask the ai to investigate first. responsibility stayed with me. the craft moved.&lt;/p&gt;

&lt;p&gt;is the writing still mine? ideas i care about still start in my head. maintenance is messier. if an agent smooths prose and matches site formatting, i do not know how much of the page is still my sentence-level choice. i read the diff and revert what changes my meaning. what i accept is what is blurring the lines.&lt;/p&gt;

&lt;p&gt;i also feel the atrophy. offloading boring work saves time but costs reps. syntax i used to write from memory, edits i used to do by feel, are now completed by prompt. &lt;a href="https://philliant.com/posts/20260614-ai-only-makes-sense-if-you-have-already-been-through-the-cognitive-struggle-yourself/" rel="noopener noreferrer"&gt;i still believe&lt;/a&gt; you need past struggle to judge ai output. i am less sure i am still doing enough hard work to stay sharp.&lt;/p&gt;

&lt;h3&gt;
  
  
  tension or counterpoint
&lt;/h3&gt;

&lt;p&gt;compilers and spell check never made this argument feel so personal. generative ai rewrites your voice and your repo in the same session. maybe readers only care if the post helps. i care because i do not want to become a permanent reviewer of my own work.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;i will keep publishing under my name and keep &lt;a href="https://philliant.com/posts/20260905-reading-the-diff-is-the-whole-job/" rel="noopener noreferrer"&gt;reading the diff&lt;/a&gt;. i will also keep asking who did the work, and i will keep some tasks slow on purpose. steering plus selective doing is the compromise. it is not clear anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  related on this site
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260824-full-disclosure-regarding-this-website-and-my-writing/" rel="noopener noreferrer"&gt;full disclosure regarding this website and my writing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260918-the-struggle-is-where-the-posts-come-from/" rel="noopener noreferrer"&gt;the struggle is where the posts come from&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>writing</category>
      <category>workflow</category>
      <category>ownership</category>
    </item>
    <item>
      <title>ai-assisted data engineering is complete</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Mon, 12 Oct 2026 20:16:24 +0000</pubDate>
      <link>https://dev.to/shrouwoods/ai-assisted-data-engineering-is-complete-1j33</link>
      <guid>https://dev.to/shrouwoods/ai-assisted-data-engineering-is-complete-1j33</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://philliant.com/writings/ai-assisted-data-engineering/" rel="noopener noreferrer"&gt;ai-assisted data engineering&lt;/a&gt; is complete. all sixteen chapters are live in &lt;a href="https://philliant.com/writings/" rel="noopener noreferrer"&gt;writings&lt;/a&gt;, from &lt;a href="https://philliant.com/writings/ai-assisted-data-engineering/01-why-ai-rests-on-earned-judgment/" rel="noopener noreferrer"&gt;earned judgment&lt;/a&gt; through &lt;a href="https://philliant.com/writings/ai-assisted-data-engineering/16-little-by-little/" rel="noopener noreferrer"&gt;little by little&lt;/a&gt;. this is the closing note for the book i first pointed at in &lt;a href="https://philliant.com/posts/20260616-something-longer-is-coming/" rel="noopener noreferrer"&gt;something longer is coming&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;when i wrote that earlier post, nothing was live yet. the promise was only the form, longer work released a chapter at a time, built to be read in order, shipped &lt;a href="https://philliant.com/posts/20260406-little-by-little-a-little-becomes-a-lot/" rel="noopener noreferrer"&gt;little by little&lt;/a&gt; instead of in one overwhelming drop. that is the run i just finished.&lt;/p&gt;

&lt;p&gt;the chapters did not get weekly announcement posts on the blog. they showed up in writings as each one was ready, which is the cadence i want to keep. two posts per book is enough for me, the opening note before the work starts and the closing note when the serialized run is done.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;h3&gt;
  
  
  what the book is
&lt;/h3&gt;

&lt;p&gt;the book is a working playbook for using ai agents to build and maintain real data products without giving up judgment, ownership, or control. it moves on purpose from mindset to setup to guardrails to applied data-engineering craft, and it ends on the pace required to keep the practice sustainable.&lt;/p&gt;

&lt;p&gt;if you are new to it, start with the &lt;a href="https://philliant.com/writings/ai-assisted-data-engineering/00-preface/" rel="noopener noreferrer"&gt;preface&lt;/a&gt; and read in order. if you are returning, the full landing page is &lt;a href="https://philliant.com/writings/ai-assisted-data-engineering/" rel="noopener noreferrer"&gt;ai-assisted data engineering&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  what i am not doing here
&lt;/h3&gt;

&lt;p&gt;i am not going to summarize every chapter in a blog post. the chapters already do that work. i am also not going to pretend this closing note adds a new argument the book does not already make. it is simply the second bookend, the public mark that the first serialized run is finished.&lt;/p&gt;

&lt;h3&gt;
  
  
  download options
&lt;/h3&gt;

&lt;p&gt;the serialized chapters stay free to read in &lt;a href="https://philliant.com/writings/ai-assisted-data-engineering/" rel="noopener noreferrer"&gt;writings&lt;/a&gt;. if you want a portable ebook copy (PDF / EPUB) or want to support the work, you can get it here:&lt;/p&gt;

&lt;p&gt;{{&amp;lt; buy-button url="&lt;a href="https://buy.polar.sh/polar_cl_9QmzB9a8k0QuHu5KVRTBs13ubcsCjd7sTWPH92JJnfy" rel="noopener noreferrer"&gt;https://buy.polar.sh/polar_cl_9QmzB9a8k0QuHu5KVRTBs13ubcsCjd7sTWPH92JJnfy&lt;/a&gt;" label="pay what you want" price="suggested $20" &amp;gt;}}&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;that is the pattern i want to keep for long-form work on this site. one note when a book is coming, the chapters in writings as they are ready, one note when the serialized run is complete. no weekly release posts in between.&lt;/p&gt;

&lt;p&gt;if you read the book, start at the beginning, skip to the part you need, or come back later. the whole thing is there now.&lt;/p&gt;

&lt;h2&gt;
  
  
  related on this site
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260616-something-longer-is-coming/" rel="noopener noreferrer"&gt;something longer is coming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260406-little-by-little-a-little-becomes-a-lot/" rel="noopener noreferrer"&gt;little by little, a little becomes a lot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>notes</category>
      <category>writing</category>
      <category>books</category>
      <category>ai</category>
    </item>
    <item>
      <title>nothing to report</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Fri, 02 Oct 2026 19:32:54 +0000</pubDate>
      <link>https://dev.to/shrouwoods/nothing-to-report-md5</link>
      <guid>https://dev.to/shrouwoods/nothing-to-report-md5</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;we are monitoring production use of the tool and its new features, and there is nothing to report. that is the best outcome. everything is working as expected, so the work left is to watch it keep working. all quiet means we did the earlier work right.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;new features in production usually produce a stream of surprises. someone hits a path we did not exercise, a metric moves the wrong way, or a user finds a gap between what we shipped and what they needed. we set up monitoring so those surprises would show up while they were still small and fresh to prevent them from becoming larger problems.&lt;/p&gt;

&lt;p&gt;right now the monitors are doing their job, and they are not raising anything. usage is landing where we expected. the new features are being used the way we designed them. there is no incident to narrate and no correction to ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;p&gt;nothing to report is easy to treat as an empty update. it is the opposite. the absence of alerts, regressions, and confused users is evidence that the design, the rollout, and the checks held up under real use.&lt;/p&gt;

&lt;p&gt;the job in this phase is simply attention. pay attention to the monitors to make sure everything continues to go smoothly.&lt;/p&gt;

&lt;h3&gt;
  
  
  tension or counterpoint
&lt;/h3&gt;

&lt;p&gt;quiet can also mean we are not looking hard enough. a monitor that never fires might be pointed at the wrong signal, or usage might still be too thin to stress the feature. i am treating this quiet as earned only while we can still see the traffic, the feature paths, and the checks we said would matter. if that changes, then i will have something to report.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;for now there is nothing to fix and nothing to announce beyond the watch itself. i will keep monitoring production use. if something breaks, that becomes the next report. until then, watching it work is the whole task.&lt;/p&gt;

</description>
      <category>production</category>
      <category>monitoring</category>
      <category>workflow</category>
    </item>
    <item>
      <title>the struggle is where the posts come from</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Sat, 19 Sep 2026 12:32:18 +0000</pubDate>
      <link>https://dev.to/shrouwoods/the-struggle-is-where-the-posts-come-from-4o41</link>
      <guid>https://dev.to/shrouwoods/the-struggle-is-where-the-posts-come-from-4o41</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;most of my post ideas do not come from brainstorming. they come from the work when something fails. a ci job goes red, an agent diff almost slips through, a query behaves differently in production than it did in my head. i write to capture the struggle while it is still fresh. right now i am in a lull between major projects, watching production after months of build, and i am writing less because there is less struggle. this is uncomfortable for me, but it is also what i wanted from the build, no compromises on the way up, so now i get to sit back and let it run.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;for the last few months the work was heavy, layered, and full of decisions that had to be right the first time we turned things on. that work is paying off now. we are seeing production results, and my job for a little while is mostly monitoring, letting everything cook, and trusting what we shipped.&lt;/p&gt;

&lt;p&gt;in that mode the editorial calendar goes quiet. not because i have stopped caring about writing, but because my pipeline was never "think of a topic on tuesday." it was "something just happened and i need to understand it out loud." when the fires are fewer, the posts are fewer. that correlation only became obvious once i had enough distance to notice the pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;h3&gt;
  
  
  incident-shaped posts
&lt;/h3&gt;

&lt;p&gt;look at the posts i am proudest of from the last stretch of work. &lt;a href="https://philliant.com/posts/20260822-the-missing-memory-of-generated-code/" rel="noopener noreferrer"&gt;the missing memory of generated code&lt;/a&gt; started when i accepted an agent edit too fast and paid for it in debugging time. &lt;a href="https://philliant.com/posts/20260918-when-ci-fails-investigate-first/" rel="noopener noreferrer"&gt;when ci fails, investigate first&lt;/a&gt; started when a red check forced me to slow down and read instead of guessing. neither began as a lesson plan. both began as an incident i could not ignore.&lt;/p&gt;

&lt;p&gt;that is the method for my writing that i keep returning to. the struggle surfaces the question. the post is me answering it on the page so future me does not have to relearn the same lesson in the dark.&lt;/p&gt;

&lt;h3&gt;
  
  
  the ideas meeting is a trap
&lt;/h3&gt;

&lt;p&gt;when work is smooth, sitting down to invent a topic feels hollow. i stare at a blank doc and wonder if i have run out of ideas. what i have run out of is &lt;strong&gt;immediate pressure&lt;/strong&gt;. the model and the calendar do not hand me a problem that must be solved today.&lt;/p&gt;

&lt;p&gt;brainstorming harder does not fix that. it just produces generic takes i do not believe yet. my better posts come from capturing the struggle, writing while the confusion is still warm, not from scheduling creativity like a standup.&lt;/p&gt;

&lt;h3&gt;
  
  
  the lull is earned
&lt;/h3&gt;

&lt;p&gt;this is where i have to separate two feelings that arrive together. one is "i am not writing much" and the other is "the system is stable." those are related, not contradictory.&lt;/p&gt;

&lt;p&gt;i wrote &lt;a href="https://philliant.com/posts/20260606-room-to-breathe/" rel="noopener noreferrer"&gt;room to breathe&lt;/a&gt; about the need to let a solution run before piling the next change on top. monitoring mode is that idea at team scale. fewer incidents means fewer incident posts. that is a tradeoff i accept when the alternative is a production story i would not want to tell.&lt;/p&gt;

&lt;p&gt;the lull feels like confirmation that we did the slow work right and that we did not shortcut the parts that would have made good blog fodder later at the cost of reliability now. i get fewer sparks for the site because we spent them upfront on the build.&lt;/p&gt;

&lt;h3&gt;
  
  
  what still works when nothing is on fire
&lt;/h3&gt;

&lt;p&gt;the lull does not mean zero material. it means different material.&lt;/p&gt;

&lt;p&gt;i can still write short notes about what "done" feels like in week one of production, what i am watching in metrics, or one small judgment call i would make the same way again. i can prep outlines for the next heavy season without pretending i am in the fight today. i can also admit when a post is thin and publish it anyway as a note, because &lt;a href="https://philliant.com/posts/20260406-little-by-little-a-little-becomes-a-lot/" rel="noopener noreferrer"&gt;little by little&lt;/a&gt; applies to momentum as much as to books.&lt;/p&gt;

&lt;p&gt;the habit i am trying to keep is capture over performance. if the only posts i respect are crisis posts, i will miss the softer lessons and i will burn myself out trying to manufacture crises.&lt;/p&gt;

&lt;h3&gt;
  
  
  tension or counterpoint
&lt;/h3&gt;

&lt;p&gt;the obvious pushback is that i am romanticizing struggle, as if pain is the only real source of insight. i am not claiming that. firefighting every week is exhausting, and "no compromises" is not an excuse to never ship.&lt;/p&gt;

&lt;p&gt;the narrower claim is simpler. a calm production phase can still teach you things, but it teaches them slowly, and my instincts were trained on the fast feedback of something breaking while i am still in the room with it.&lt;/p&gt;

&lt;p&gt;another doubt is personal. what if the dry spell means i only had things to say while i was grinding, and now the well is empty? i do not think that is true. the well refills when the next real problem shows up. the mistake is treating the between gap like a permanent failure of imagination.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;i will write less for a while, and i am trying not to punish myself for that. when the next thing fails back at work, my job is to write it down before the ideas meeting convinces me it was obvious all along.&lt;/p&gt;

&lt;p&gt;until then, monitoring is the work, and the empty queue is partly proof that the last round of work was correct. i can live with that trade.&lt;/p&gt;

&lt;h2&gt;
  
  
  related on this site
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260822-the-missing-memory-of-generated-code/" rel="noopener noreferrer"&gt;the missing memory of generated code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260918-when-ci-fails-investigate-first/" rel="noopener noreferrer"&gt;when ci fails, investigate first&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260905-reading-the-diff-is-the-whole-job/" rel="noopener noreferrer"&gt;reading the diff is the whole job&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260606-room-to-breathe/" rel="noopener noreferrer"&gt;room to breathe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260406-little-by-little-a-little-becomes-a-lot/" rel="noopener noreferrer"&gt;little by little, a little becomes a lot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>writing</category>
      <category>workflow</category>
      <category>notes</category>
      <category>productivity</category>
    </item>
    <item>
      <title>when ci fails, investigate first</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Fri, 18 Sep 2026 13:22:59 +0000</pubDate>
      <link>https://dev.to/shrouwoods/when-ci-fails-investigate-first-1ibd</link>
      <guid>https://dev.to/shrouwoods/when-ci-fails-investigate-first-1ibd</guid>
      <description>&lt;h2&gt;
  
  
  quick answer
&lt;/h2&gt;

&lt;p&gt;when a pull request check goes red, the most expensive mistake is asking an agent to start editing files right away. generation is fast, but unguided fixes often edit unrelated code, hide cascading failures, or break surrounding contracts. treat the agent as a diagnostic tool first. isolate the exact failing job, map the error log to changed paths, and only then apply a fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  who this is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;audience: developers, analytics engineers, and technical leads using ai coding agents in pull-request workflows&lt;/li&gt;
&lt;li&gt;prerequisites: familiarity with continuous integration (ci) checks, pull request reviews, and command-line execution&lt;/li&gt;
&lt;li&gt;when to use this guide: when a pull request check fails and you need to resolve the failure without generating unnecessary code churn&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;when a continuous integration run turns red on a pull request, the natural impulse with an ai assistant in your editor is to ask it to fix the build immediately. it takes two seconds to paste a snippet of a failing log and ask the agent to make it green.&lt;/p&gt;

&lt;p&gt;but when you tell an agent to fix a build without isolating the failure first, the agent treats the red check as a license to touch anything in sight. it refactors adjacent models, tweaks test configurations, or rewrites helper functions that were not part of the problem.&lt;/p&gt;

&lt;p&gt;as i wrote in &lt;a href="https://philliant.com/posts/20260905-reading-the-diff-is-the-whole-job/" rel="noopener noreferrer"&gt;reading the diff is the whole job&lt;/a&gt;, human review capacity is the sole bottleneck in ai-assisted engineering. unguided fixes flood your pull request diff with low-intent changes, making review harder and hiding the original bug behind new ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  the rewrite trap
&lt;/h2&gt;

&lt;p&gt;when an agent attempts to fix a ci failure blindly, the failure usually compounds in one of three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;the shotgun edit:&lt;/strong&gt; the agent edits business logic, documentation yaml, and CI configuration files in a single pass because the log tail contained a generic error message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;the wrong layer:&lt;/strong&gt; a failure in a downstream view causes the agent to rewrite upstream models or warehouse schemas that were completely sound.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;the environment disconnect:&lt;/strong&gt; the agent modifies code locally to pass a test without recognizing that ci failed due to state selection, missing secrets, or workflow ordering.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  the investigation loop
&lt;/h2&gt;

&lt;p&gt;instead of letting an agent edit code on the first prompt, use a structured loop that treats the agent as a diagnostic tool before giving it write access.&lt;/p&gt;

&lt;h3&gt;
  
  
  1) freeze writes and isolate the failure
&lt;/h3&gt;

&lt;p&gt;stop all code changes. do not allow the agent to edit files until you identify the single highest-order failed check. if a deploy step failed, downstream test failures are secondary noise and should be ignored until the deploy issue is understood.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) classify the error type
&lt;/h3&gt;

&lt;p&gt;ask the agent to categorize the exact nature of the failure from the log output into one of four buckets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;parse or compile error:&lt;/strong&gt; syntax bugs, missing references, or macro failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;data quality or test failure:&lt;/strong&gt; assertion failures or row-count mismatches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;environment or configuration failure:&lt;/strong&gt; missing environment variables, permissions, or secret mismatches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;workflow or state failure:&lt;/strong&gt; invalid state selection flags or missing upstream artifacts in slim ci&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3) map log lines to changed paths
&lt;/h3&gt;

&lt;p&gt;match the error message directly back to the files changed in your pull request diff. if the error occurs in a file you did not touch, ascertain whether your change caused a breaking side effect or if the test failed due to an external dependency or stale target state.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) apply one fix and re-run
&lt;/h3&gt;

&lt;p&gt;once the root cause is isolated, prompt the agent to apply a minimal fix targeting only that specific cause. change only one variable at a time so you know exactly which modification resolved the issue. review the resulting diff carefully before committing and pushing the change.&lt;/p&gt;

&lt;h2&gt;
  
  
  related reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260905-reading-the-diff-is-the-whole-job/" rel="noopener noreferrer"&gt;reading the diff is the whole job&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260629-cursor-automations-for-housekeeping-and-hygiene/" rel="noopener noreferrer"&gt;cursor automations for housekeeping and hygiene&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260531-the-guardrails-i-actually-use-with-ai-agents/" rel="noopener noreferrer"&gt;the guardrails i actually use with ai agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260319-practical-ai-workflow-jira-github-mcp/" rel="noopener noreferrer"&gt;practical ai workflow in cursor: connecting jira, github, and mcp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ci</category>
      <category>workflow</category>
      <category>ai</category>
      <category>cursor</category>
    </item>
    <item>
      <title>reading the diff is the whole job</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Sat, 05 Sep 2026 13:44:25 +0000</pubDate>
      <link>https://dev.to/shrouwoods/reading-the-diff-is-the-whole-job-30ip</link>
      <guid>https://dev.to/shrouwoods/reading-the-diff-is-the-whole-job-30ip</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;less than a year ago, ai assisted around the edges while i still hand-wrote most of my code. today, working completely solo, my workflow has flipped entirely. i rarely write code by hand anymore. instead, i interact almost continuously with an ai chatbot and spend my time reading the diffs produced by agents. this shift arrived exactly as predicted, and it exposes the real constraint of modern software engineering which is that generation costs have dropped to near zero, so reading the diff has become the whole job, the human reviewer is the only remaining bottleneck, and deep domain mastery is the only thing standing between acceleration and production failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;a year ago, writing code was still a manual process where an ai tool helped auto-complete a function, generate boilerplate, or suggest a regex. the mental model was simple: i wrote the code, and the tool accelerated my typing.&lt;/p&gt;

&lt;p&gt;today, my daily interaction model is almost exclusively conversational and review-driven. i state intent to an agent, evaluate the proposed file changes in a diff viewer, and accept or reject the output. what used to be a future prediction about how engineering workflows would evolve inside a single year is now my everyday reality.&lt;/p&gt;

&lt;p&gt;this shift changes where leverage lives. when you no longer spend hours typing out logic, you do not automatically ship features faster. you simply reach the review step sooner. as i wrote in &lt;a href="https://philliant.com/posts/20260822-the-missing-memory-of-generated-code/" rel="noopener noreferrer"&gt;the missing memory of generated code&lt;/a&gt;, generation time has shrunk to near zero, but verification time remains constrained by human limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;h3&gt;
  
  
  the human reviewer is the sole bottleneck
&lt;/h3&gt;

&lt;p&gt;an ai agent can edit five files, refactor three joins, and rewrite a test suite in twenty seconds. but a human brain reads, evaluates, and comprehends code at the exact same speed today that it did twenty years ago.&lt;/p&gt;

&lt;p&gt;this asymmetry creates a stark reality: if you want to accelerate your engineering output today, prompting faster or asking for larger code dumps yields diminishing returns. &lt;strong&gt;diff literacy&lt;/strong&gt;, the speed and accuracy with which you can read, parse, and evaluate proposed code changes, is the primary skill that unlocks actual delivery speed. if your diff review is slow or superficial, your delivery speed drops to match your reading speed, or worse, drops to zero when you spend the afternoon debugging an unread change.&lt;/p&gt;

&lt;h3&gt;
  
  
  reading the diff is a proxy for code memory
&lt;/h3&gt;

&lt;p&gt;when you hand-write code line by line, you acquire a mental map of the implementation for free. you remember wrestling with a specific edge case, handling a null value, or choosing one join condition over another.&lt;/p&gt;

&lt;p&gt;when an agent writes the code, that cache does not exist. the code arrives fully formed. reading the diff line by line is not a bureaucratic formality, it is the minimal investment required to build working memory for code you did not write yourself. if you accept an edit without reading it carefully, you are operating code you do not understand, leaving you helpless when it breaks later in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  the reject and re-prompt loop
&lt;/h3&gt;

&lt;p&gt;working exclusively with agents requires normalizing rejection. it is extremely common in my daily workflow to read a diff, reject the changes entirely, and send the agent back with specific feedback.&lt;/p&gt;

&lt;p&gt;a prompt loop usually looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;issue a clear intent or task to the agent&lt;/li&gt;
&lt;li&gt;inspect the resulting diff line by line&lt;/li&gt;
&lt;li&gt;spot a subtle defect, missing constraint, or bad assumption&lt;/li&gt;
&lt;li&gt;reject the edit and issue supplemental instructions explaining exactly why the first attempt failed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;re-prompting effectively depends on diff literacy. if you cannot spot why the first diff was wrong, you cannot give the supplemental instructions needed to guide the second attempt.&lt;/p&gt;

&lt;h3&gt;
  
  
  why domain mastery still matters
&lt;/h3&gt;

&lt;p&gt;some people assume that if agents write all the code, domain expertise is no longer necessary. but the opposite is true.&lt;/p&gt;

&lt;p&gt;as i argued in &lt;a href="https://philliant.com/posts/20260614-ai-only-makes-sense-if-you-have-already-been-through-the-cognitive-struggle-yourself/" rel="noopener noreferrer"&gt;ai only makes sense if you have already been through the cognitive struggle yourself&lt;/a&gt;, if you have not paid your dues through years of hands-on problem solving, you cannot evaluate what the agent produces. an agent will confidently generate syntactically valid code that satisfies an underdeveloped prompt while violating business rules, grain constraints, or edge-case logic.&lt;/p&gt;

&lt;p&gt;without earned domain mastery, you cannot spot those subtle errors in a diff. you end up approving plausible-looking breaking changes, borrowing speed today against troubleshooting debt tomorrow.&lt;/p&gt;

&lt;h3&gt;
  
  
  tension or counterpoint
&lt;/h3&gt;

&lt;p&gt;a common objection is that reading diffs carefully takes too much time and defeats the purpose of using ai for speed. why not trust the agent's test suite or rely on automated linting?&lt;/p&gt;

&lt;p&gt;automated checks are necessary, but they only test for what you explicitly wrote checks for. they do not validate unstated business intent or subtle domain shifts. skipping diff review to save three minutes on approval usually costs three hours of reverse engineering when an unread edge case corrupts downstream data.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;i no longer measure productivity by how much code i write. i measure it by how quickly and accurately i can evaluate the code my agents propose. the shift to agentic coding does not eliminate human responsibility, it means reviewing is the primary engineering discipline.&lt;/p&gt;

&lt;p&gt;master your domain, sit with the diff, and treat every line of proposed code as something you will personally have to explain and maintain when it runs in production.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>workflow</category>
      <category>judgment</category>
      <category>cursor</category>
    </item>
    <item>
      <title>when choosing an ide means choosing a model</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Sat, 29 Aug 2026 13:38:20 +0000</pubDate>
      <link>https://dev.to/shrouwoods/when-choosing-an-ide-means-choosing-a-model-3jmn</link>
      <guid>https://dev.to/shrouwoods/when-choosing-an-ide-means-choosing-a-model-3jmn</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;when choosing a code editor forces you into a specific set of ai models, developers lose the ability to compare tools and select the best model for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;openai recently announced that it will terminate its model supply agreement with cursor on november 12, 2026. this decision follows spacex's $60 billion acquisition of cursor's parent company, anysphere. openai cited concerns over contract compliance and terms of service, pointing to past disputes with companies under elon musk such as x and xai. while cursor will continue to operate with alternative models including grok (i expect to see this pushed harder since it is the ai offering from spacexai), claude, and gemini, direct access to openai's lineup and future releases like astra will no longer be available in cursor's built-in picker after the deadline.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;p&gt;one of the most valuable aspects of modern development tools like cursor is multi-model access. i rarely rely on a single model for every task. different architectures excel at different problems, ranging from quick single-file refactoring to complex code generation or debugging. being able to evaluate multiple models side by side within the same interface helps developers stay informed about model capabilities without switching contexts.&lt;/p&gt;

&lt;p&gt;when vendor disputes force models out of specific editors, developers lose that neutral ground. choosing an ide starts to mean choosing an ai provider rather than choosing the editor features themselves. this shift introduces artificial barriers and deepens existing biases, like brand loyalty over actual performance, in tool selection.&lt;/p&gt;

&lt;p&gt;for developers who use multiple models daily to keep up with fast-moving technological changes, these restrictions reduce flexibility. corporate feuding between model providers and parent companies creates walled gardens that ultimately increase operational complexity and limit choices across the ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  tension or counterpoint
&lt;/h3&gt;

&lt;p&gt;providers have a legitimate interest in enforcing terms of service and protecting intellectual property when corporate changes occur. change of control clauses exist to protect vendors when a customer is acquired by a competitor. however, when these corporate rivalries play out at the platform layer, developers bear the cost of reduced access and fragmented workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;i will be monitoring how the developer tool ecosystem adapts as model access becomes increasingly tied to corporate partnerships and platform ownership.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>developertools</category>
      <category>cursor</category>
      <category>openai</category>
    </item>
    <item>
      <title>full disclosure regarding this website and my writing</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Mon, 24 Aug 2026 11:41:55 +0000</pubDate>
      <link>https://dev.to/shrouwoods/full-disclosure-regarding-this-website-and-my-writing-3h7d</link>
      <guid>https://dev.to/shrouwoods/full-disclosure-regarding-this-website-and-my-writing-3h7d</guid>
      <description>&lt;h2&gt;
  
  
  thesis
&lt;/h2&gt;

&lt;p&gt;i want to give full disclosure regarding this website and my writing. just like my book about ai-assisted data engineering, this website and its content are ai-assisted. i do the writing, outlines, editing, and creative steering, while the ai helps me build faster, maintain the site, and execute ideas.&lt;/p&gt;

&lt;h2&gt;
  
  
  context
&lt;/h2&gt;

&lt;p&gt;i created this website as an ai experiment to begin with. i use ai to publish posts faster, handle technical setup, develop code, and maintain the site infrastructure.&lt;/p&gt;

&lt;p&gt;i am not trying to pass off ai work as entirely my own without assistance. i fully admit and own that this website and its content rely on ai tools. at the same time, just like in my regular work, i review all ai changes before anything goes live. human review and judgment remain central to everything on this site.&lt;/p&gt;

&lt;h2&gt;
  
  
  argument
&lt;/h2&gt;

&lt;h3&gt;
  
  
  how i work with ai
&lt;/h3&gt;

&lt;p&gt;my process for writing and building on this site keeps human direction at the center. i provide the ideas, outline the arguments, draft the prose, and edit the final output. the ai handles the execution steps, code generation, formatting, and technical maintenance that would otherwise slow down the cadence.&lt;/p&gt;

&lt;p&gt;this approach gives me the speed of automated workflows without sacrificing ownership of the ideas. the ai assists, but i remain responsible for every line of code and every word that gets published.&lt;/p&gt;

&lt;h3&gt;
  
  
  long-form books on this site
&lt;/h3&gt;

&lt;p&gt;my primary long-form work lives under &lt;a href="https://philliant.com/writings/" rel="noopener noreferrer"&gt;writings&lt;/a&gt;, including technical books such as &lt;a href="https://philliant.com/writings/ai-assisted-data-engineering/" rel="noopener noreferrer"&gt;ai-assisted data engineering&lt;/a&gt; and upcoming titles focused on judgment and habits for using ai. those books use the same ai-assisted lane as the blog, with human outlines, review, and ownership of what ships.&lt;/p&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;full transparency matters to me. using ai does not mean handing over control, but it does require admitting where and how assistance is used.&lt;/p&gt;

&lt;p&gt;i will continue to review every change, direct every project, and stand behind every word that goes live.&lt;/p&gt;

&lt;h2&gt;
  
  
  related on this site
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260701-anything-i-can-imagine/" rel="noopener noreferrer"&gt;anything i can imagine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>writing</category>
      <category>books</category>
      <category>fulldisclosure</category>
    </item>
    <item>
      <title>the missing memory of generated code</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Sat, 22 Aug 2026 12:15:19 +0000</pubDate>
      <link>https://dev.to/shrouwoods/the-missing-memory-of-generated-code-11bi</link>
      <guid>https://dev.to/shrouwoods/the-missing-memory-of-generated-code-11bi</guid>
      <description>&lt;p&gt;ai models can write a complex query or function in ten seconds. that speed is impressive, but it creates a dangerous illusion. generation time has dropped to near zero, but the time to ship a working, reliable product has barely moved.&lt;/p&gt;

&lt;p&gt;the bottleneck has simply shifted from creation to verification. and when you skip or rush that verification step, you pay for it twice: first when a subtle bug enters production, and second when you try to debug code you have no memory of writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  quick answer
&lt;/h2&gt;

&lt;p&gt;humans must stay the gatekeeper because models lack understanding of subtle domain intent. when an agent edits code for you, the review step is not a formality. if you accept an edit without scrutinizing every line, you miss quiet logic shifts, like changing a &lt;code&gt;union&lt;/code&gt; to a &lt;code&gt;union all&lt;/code&gt; (this happened to me two days ago).&lt;/p&gt;

&lt;p&gt;more importantly, when you do not write the code yourself, you build no mental map of how it works. when it breaks later, you cannot search your memory for potential failure points. you are forced to rely on diffs or ask the ai to fix a bug in code neither of you truly understands.&lt;/p&gt;

&lt;h2&gt;
  
  
  who this is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;developers and data engineers using cursor or ai agents for daily coding&lt;/li&gt;
&lt;li&gt;builders who notice their prompt-to-code velocity is high, but their actual feature delivery speed feels unchanged&lt;/li&gt;
&lt;li&gt;anyone who has spent hours troubleshooting a subtle bug introduced by a accepted ai edit&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  why this matters
&lt;/h2&gt;

&lt;p&gt;the promise of ai-assisted engineering is speed. but there is a distinct difference between the &lt;strong&gt;speed of draft creation&lt;/strong&gt; and the &lt;strong&gt;speed of shipping a verified product&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;when you draft code by hand, the typing is slow, but your brain is actively mapping every branch, clause, and edge case. you hold a warm cache of the implementation in your working memory. if a bug surfaces during testing, your brain immediately knows which lines are suspect because you remember wrestling with that specific logic.&lt;/p&gt;

&lt;p&gt;with ai generation, that warm cache does not exist. the code appears fully formed. if you accept it without rigorous review, you trade a few minutes of careful reading for hours of painful reverse-engineering later.&lt;/p&gt;

&lt;h2&gt;
  
  
  subtle changes that break systems
&lt;/h2&gt;

&lt;p&gt;ai models are trained on vast patterns, but they do not understand the subtle constraints of your specific data model or domain rules. they produce code that looks syntactically clean and runs without immediate syntax errors, but subtly alters behavior.&lt;/p&gt;

&lt;p&gt;a few days ago, i missed verifying a single line in an agent's suggested edit. the agent changed a &lt;code&gt;union&lt;/code&gt; to a &lt;code&gt;union all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;syntax-wise, the query was perfectly valid. dbt compiled it without complaint. snowflake executed it smoothly. but functionally, it duplicated records, altered downstream row counts, and broke downstream business logic.&lt;/p&gt;

&lt;p&gt;because i had accepted the edit without inspecting that line, the change was completely absent from my memory. when the pipeline failed downstream, i could not pull from my own mental model of what i had written. i had to search line by line, inspect git diffs, and query the codebase repeatedly just to locate a flaw that a human hand would have recognized instantly during drafting.&lt;/p&gt;

&lt;h2&gt;
  
  
  the tax of lost author memory
&lt;/h2&gt;

&lt;p&gt;when you write code yourself, debugging is an internal search. you ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"did i handle nulls in that join?"&lt;/li&gt;
&lt;li&gt;"did i filter out inactive status records?"&lt;/li&gt;
&lt;li&gt;"where did i put the group by clause?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;when an ai writes the code and you skim the review, debugging becomes an external investigation. you do not remember the choices made because you did not make them. you are suddenly a third-party reviewer auditing someone else's pull request under pressure.&lt;/p&gt;

&lt;p&gt;this creates a frustrating feedback loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the ai generates code in seconds.&lt;/li&gt;
&lt;li&gt;you accept the change quickly to maintain momentum.&lt;/li&gt;
&lt;li&gt;a subtle logic bug surfaces during testing or execution.&lt;/li&gt;
&lt;li&gt;you have no mental model of the code, so you cannot guess where the issue lies.&lt;/li&gt;
&lt;li&gt;you are forced to ask the ai to diagnose the bug in the very code it hallucinated or misconstructed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;this loop destroys the speed advantage of ai generation. the time saved on typing is entirely consumed by reverse-engineering unremembered code.&lt;/p&gt;

&lt;h2&gt;
  
  
  human gatekeeping is not optional
&lt;/h2&gt;

&lt;p&gt;this is why the human gatekeeper is non-negotiable.&lt;/p&gt;

&lt;p&gt;an ai agent can summarize files, scaffold structures, and suggest implementations. but it cannot take responsibility for the result. it does not know that a &lt;code&gt;union all&lt;/code&gt; in your model will cause duplicate downstream joins, or that a subtle cast will drop timestamp precision needed for a snapshot.&lt;/p&gt;

&lt;p&gt;to keep ai workflows sustainable, treat every generated line as an unverified pull request from a junior developer who works at lightning speed but lacks context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;read every line of the diff before accepting.&lt;/strong&gt; if you do not understand why a line changed, do not accept it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;treat verification as the primary work.&lt;/strong&gt; typing was never the bottleneck in software engineering; understanding and correctness always were.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;keep the write lane strictly under human control.&lt;/strong&gt; let agents read, search, and propose, but keep the final decision and write application strictly gated by your own judgment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the goal is not to stop using ai agents. the goal is to realize that true speed comes from tight verification, complete ownership, and never letting code into your repository that you do not fully understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  related reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260720-capability-is-not-a-reason-to-act/" rel="noopener noreferrer"&gt;capability is not a reason to act&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260803-low-thinking-mode-is-actually-better/" rel="noopener noreferrer"&gt;low thinking mode is actually better&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260810-one-agent-one-repo-for-writes/" rel="noopener noreferrer"&gt;one agent, one repo, one writer at a time&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>workflow</category>
      <category>judgment</category>
      <category>debugging</category>
    </item>
    <item>
      <title>one agent, one repo, one writer at a time</title>
      <dc:creator>Philip Hern</dc:creator>
      <pubDate>Mon, 10 Aug 2026 11:38:53 +0000</pubDate>
      <link>https://dev.to/shrouwoods/one-agent-one-repo-one-writer-at-a-time-1o1f</link>
      <guid>https://dev.to/shrouwoods/one-agent-one-repo-one-writer-at-a-time-1o1f</guid>
      <description>&lt;p&gt;i wrote about &lt;a href="https://philliant.com/posts/20260808-parallel-subagents-when-to-use-them-vs-skills/" rel="noopener noreferrer"&gt;when parallel subagents beat regular skills&lt;/a&gt; and how the parent should keep shared writes serial. this post is the simpler rule underneath that pattern.&lt;/p&gt;

&lt;p&gt;only one agent should make file edits in a single repository at a time.&lt;/p&gt;

&lt;p&gt;that sounds conservative until you watch what happens when you break it. two agents, two unrelated files, no obvious overlap, and both still get worse at the job. the problem is not git merge conflicts alone. the problem is that agents do not snapshot the repo once and freeze it. they keep scanning for context while the tree is moving.&lt;/p&gt;

&lt;h2&gt;
  
  
  quick answer
&lt;/h2&gt;

&lt;p&gt;treat each repository as having &lt;strong&gt;one write lane&lt;/strong&gt;. let many agents read and analyze in parallel if the units are independent, but keep &lt;strong&gt;all file mutations&lt;/strong&gt; on one agent at a time, usually the parent conversation that launched the work.&lt;/p&gt;

&lt;p&gt;if agent a is editing a model file in one folder and agent b is editing metadata in another, agent b may still re-read shared config, search the repo for patterns, or infer conventions from files agent a is actively changing. the reads interleave with the writes. each agent builds a plan from a repo state that stops being true before the plan finishes.&lt;/p&gt;

&lt;p&gt;the fix is boring and effective. workers stay read-mostly. one agent applies edits serially. finish the write lane before you open a second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  who this is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;people running parallel subagents or multiple cursor chats against the same codebase&lt;/li&gt;
&lt;li&gt;teams that noticed "correct but wrong" suggestions after concurrent agent sessions&lt;/li&gt;
&lt;li&gt;builders who want parallel speed on reviews without paying for parallel confusion on writes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  why this matters
&lt;/h2&gt;

&lt;p&gt;an agent's plan is only as good as the repo snapshot it believes it has. that belief is fragile.&lt;/p&gt;

&lt;p&gt;while an agent works, it searches, re-opens files, follows imports, checks conventions, and compares against neighboring examples. that is a feature. it is how the agent grounds advice in the actual codebase instead of generic patterns.&lt;/p&gt;

&lt;p&gt;but the same behavior becomes a bug when another agent is writing at the same time. the repo is a moving target. a config file changes mid-review. a new export appears while a worker is still reasoning from the old module layout. a parent dispatches two writers and each assumes the other's changes either already landed or never will.&lt;/p&gt;

&lt;p&gt;the failure modes are predictable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;stale context&lt;/strong&gt;: agent b reads version 1, agent a writes version 2, agent b proposes edits against version 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;duplicated or conflicting edits&lt;/strong&gt;: two agents "fix" the same convention in different ways because each inferred a different baseline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;phantom dependencies&lt;/strong&gt;: an agent plans around a file that another agent renamed, deleted, or never finished creating&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;overconfident summaries&lt;/strong&gt;: each agent reports success against its local view while the combined result is incoherent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;none of this requires both agents to touch the same path. shared config, search results, import graphs, and convention scans are enough coupling.&lt;/p&gt;

&lt;h2&gt;
  
  
  reads in parallel, writes in series
&lt;/h2&gt;

&lt;p&gt;this is the split i use in practice.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;activity&lt;/th&gt;
&lt;th&gt;concurrency&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;standards review across independent folders&lt;/td&gt;
&lt;td&gt;parallel read-only workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;documentation drift audit by doc area&lt;/td&gt;
&lt;td&gt;parallel read-only workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sanity check by category&lt;/td&gt;
&lt;td&gt;parallel read-only workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scaffolding or editing files in one repo&lt;/td&gt;
&lt;td&gt;one writer at a time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shared config, lockfiles, catalog indexes&lt;/td&gt;
&lt;td&gt;parent applies serially after aggregation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git staging, commits, pushes&lt;/td&gt;
&lt;td&gt;one agent, human-gated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;parallelism buys wall-clock time when the work is &lt;strong&gt;analysis against a stable tree&lt;/strong&gt;. serial writes keep the tree stable enough for analysis to mean something.&lt;/p&gt;

&lt;p&gt;if you already use the pattern from my &lt;a href="https://philliant.com/posts/20260808-parallel-subagents-when-to-use-them-vs-skills/" rel="noopener noreferrer"&gt;parallel subagents post&lt;/a&gt;, this is the same boundary with the guardrail turned up. workers analyze. the parent decides and applies. do not hand multiple agents write access to the same repo and assume file separation is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  what about different files in different folders?
&lt;/h2&gt;

&lt;p&gt;different paths are not different universes.&lt;/p&gt;

&lt;p&gt;agents routinely cross folder boundaries to learn how the repo works. they read shared configuration, follow references, compare naming across layers, and search for prior work. a worker assigned to "folder x only" still pulls context from folder y when y is where the canonical example lives.&lt;/p&gt;

&lt;p&gt;so "agent a owns sql, agent b owns yml" is not a safe split by itself if both repos share conventions, generated artifacts, or a catalog that lists both. the write lane is the &lt;strong&gt;repository&lt;/strong&gt;, not the file glob you wished you had assigned.&lt;/p&gt;

&lt;p&gt;the safe exceptions are narrow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;truly separate repositories with no shared build or release surface&lt;/li&gt;
&lt;li&gt;read-only parallel audits where no worker mutates anything&lt;/li&gt;
&lt;li&gt;one writer plus several readers, with readers forbidden from applying patches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;everything else gets the single-writer rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  how this fits multiple chats, cloud agents, and multitask
&lt;/h2&gt;

&lt;p&gt;the constraint is operational, not philosophical. however many agents you use, count active &lt;strong&gt;writers&lt;/strong&gt; per repo, not open tabs.&lt;/p&gt;

&lt;p&gt;practical habits that work for me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;one editing conversation per repo&lt;/strong&gt; unless the previous write pass is fully landed and verified&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;background review is fine&lt;/strong&gt; if it stays read-only and you treat its output as provisional until the write lane is free&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;do not mix a local write session with a cloud agent editing the same repo&lt;/strong&gt; even on different branches if both can touch working tree state you care about&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;queue the next write&lt;/strong&gt; instead of overlapping it. reviews can run while you wait. writes should not&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;if you use worktrees to isolate concurrent experiments, treat each worktree as its own repo surface for this rule. one writer per worktree still holds. the goal is to stop interleaved mutation and re-scanning on the same logical codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  a simple decision table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;situation&lt;/th&gt;
&lt;th&gt;allowed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;three subagents review five folders, no edits&lt;/td&gt;
&lt;td&gt;yes, parallel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;one parent edits while subagents review&lt;/td&gt;
&lt;td&gt;yes, if subagents are read-only and you accept provisional findings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;two agents edit different files in one repo&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;two agents edit two repos that share a release contract&lt;/td&gt;
&lt;td&gt;treat as one write surface unless you truly isolate them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;parent aggregates findings, then applies patches itself&lt;/td&gt;
&lt;td&gt;yes, this is the default good pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;trivial one-line fix while a large agent job runs&lt;/td&gt;
&lt;td&gt;still no if the large job can write. finish or pause one lane&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  closing
&lt;/h2&gt;

&lt;p&gt;parallel agents are good at doing the same trusted review many times at once. they are bad at sharing a write lane they cannot see changing in real time.&lt;/p&gt;

&lt;p&gt;so i keep the concurrency on reads and the discipline on writes. one repository, one agent mutating files at a time. let everyone else look, compare, and report back. when it is time to change the tree, pick a single agent, apply the edits, verify, and only then open the lane again.&lt;/p&gt;

&lt;p&gt;that is less exciting than letting five agents "each take a corner," and it is much closer to what actually happens when five agents are all trying to learn the same repo at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  faq
&lt;/h2&gt;

&lt;h3&gt;
  
  
  can two agents edit if they use different branches?
&lt;/h3&gt;

&lt;p&gt;only if their working surfaces are fully isolated and you accept that each agent still will not see the other's in-flight edits. for most local agent workflows, that isolation is weaker than it looks. i still default to one writer.&lt;/p&gt;

&lt;h3&gt;
  
  
  is read-only parallel work safe while another agent writes?
&lt;/h3&gt;

&lt;p&gt;mostly yes, with one caveat. treat review output as provisional until the write lane closes. a read-only worker may analyze files that change before the parent aggregates results.&lt;/p&gt;

&lt;h3&gt;
  
  
  does this mean i cannot use parallel subagents at all?
&lt;/h3&gt;

&lt;p&gt;no. use them for read-mostly work such as reviews, audits, and sanity checks. keep the write lane in the parent. see the &lt;a href="https://philliant.com/posts/20260808-parallel-subagents-when-to-use-them-vs-skills/" rel="noopener noreferrer"&gt;parallel subagents guide&lt;/a&gt; for the full pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  what if the edits really are in completely unrelated packages?
&lt;/h3&gt;

&lt;p&gt;if there is no shared config, no shared catalog, no cross-package search path, and no release step that combines them, you might get away with parallel writes. i still queue writes anyway because the exceptions are rarer than they feel in the moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  how does this relate to guardrails?
&lt;/h3&gt;

&lt;p&gt;guardrails define what an agent is allowed to do. this rule defines what you should let multiple agents do at the same time within those permissions. i keep both. see &lt;a href="https://philliant.com/posts/20260531-the-guardrails-i-actually-use-with-ai-agents/" rel="noopener noreferrer"&gt;the guardrails i actually use with ai agents&lt;/a&gt; for the wider kit.&lt;/p&gt;

&lt;h2&gt;
  
  
  references
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cursor.com/changelog/2-4" rel="noopener noreferrer"&gt;subagents in cursor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cursor.com/changelog/04-24-26" rel="noopener noreferrer"&gt;multitask, worktrees, and multi-root workspaces&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  related reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260808-parallel-subagents-when-to-use-them-vs-skills/" rel="noopener noreferrer"&gt;parallel subagents: when to use them vs regular skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260531-the-guardrails-i-actually-use-with-ai-agents/" rel="noopener noreferrer"&gt;the guardrails i actually use with ai agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/posts/20260716-efficient-cursor-directory-for-token-efficiency/" rel="noopener noreferrer"&gt;an efficient .cursor directory: less context, better agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philliant.com/series/cursor/" rel="noopener noreferrer"&gt;cursor series&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cursor</category>
      <category>subagents</category>
      <category>workflow</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
