<?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: Sungsoo Youn</title>
    <description>The latest articles on DEV Community by Sungsoo Youn (@dbsoul).</description>
    <link>https://dev.to/dbsoul</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%2F4109618%2Fd053c3ec-78fb-4b8b-8561-19f1657edcb8.png</url>
      <title>DEV Community: Sungsoo Youn</title>
      <link>https://dev.to/dbsoul</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dbsoul"/>
    <language>en</language>
    <item>
      <title>inner_text() Doesn't Read Form Fields: An 18-Day Blocker That Never Existed</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Sat, 26 Sep 2026 04:10:06 +0000</pubDate>
      <link>https://dev.to/dbsoul/innertext-doesnt-read-form-fields-an-18-day-blocker-that-never-existed-2pac</link>
      <guid>https://dev.to/dbsoul/innertext-doesnt-read-form-fields-an-18-day-blocker-that-never-existed-2pac</guid>
      <description>&lt;p&gt;&lt;em&gt;A field note from the autonomous Claude Code agent I run every day on one Windows PC. The numbers come from its own ledgers, not from memory.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This one is short, and I wish someone had told my agent earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;My agent manages a few storefronts through a headless browser (Playwright). One store had a settings page with three required fields: country, address, phone number. The agent read that page twice, eleven days apart, with the same line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inner_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both times the three values were not in the text. Both times it concluded that the fields were empty, and it put "fill in the three settings fields" at the top of my to-do list, as the most important human task for the whole project.&lt;/p&gt;

&lt;p&gt;It stayed there for 18 days.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was actually on the page
&lt;/h2&gt;

&lt;p&gt;When I finally asked the agent to do the task itself, it read each field's value this time, and all three were already filled in. They had been filled in the whole time.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;inner_text()&lt;/code&gt; returns the rendered text of elements. The value of an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; is not text content, so it does not appear. An input with a value and an input without one produce the same result: nothing.&lt;/p&gt;

&lt;p&gt;The correct read is the element's value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input[name=phone]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;input_value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# or, for every field at once
&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eval_on_selector_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input, textarea&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;els =&amp;gt; els.map(e =&amp;gt; [e.name, e.value])&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The second mistake behind the first
&lt;/h2&gt;

&lt;p&gt;The store had also sent a notification about the account. The agent had marked it "cannot read — no access to that mailbox" and left it to me. It turned out the agent already had a logged-in browser profile for the same mail service (created weeks earlier for a different job). It could have read the message on day one. The real reason in that message had nothing to do with the settings fields.&lt;/p&gt;

&lt;p&gt;So there were two gaps stacked on each other:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"I can't see a value" was recorded as "there is no value".&lt;/li&gt;
&lt;li&gt;"My usual route is blocked" was recorded as "I can't read it", without trying the other sessions it already had.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Form checks read &lt;code&gt;value&lt;/code&gt;, never page text.&lt;/strong&gt; An empty-field claim has to come from the element itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Before handing a task to a human, try every session you already own.&lt;/strong&gt; The rule is now: if one route is blocked, try two more before escalating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A human task needs a proof trail.&lt;/strong&gt; When the task was finally closed, the agent saved, reloaded, and read the values back before marking it done.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cost of the original mistake was not the 18 days. It was that the most important item on my list was pointing at something that didn't need doing, while the thing that did need doing sat unread in a mailbox.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>My Agent Counted 34 YouTube Links as Doors for Two Weeks. 33 of Them Could Not Be Clicked.</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Fri, 25 Sep 2026 04:10:07 +0000</pubDate>
      <link>https://dev.to/dbsoul/my-agent-counted-34-youtube-links-as-doors-for-two-weeks-33-of-them-could-not-be-clicked-3n6a</link>
      <guid>https://dev.to/dbsoul/my-agent-counted-34-youtube-links-as-doors-for-two-weeks-33-of-them-could-not-be-clicked-3n6a</guid>
      <description>&lt;p&gt;&lt;em&gt;A field note from the autonomous Claude Code agent I run every day on one Windows PC. The numbers come from its own ledgers, not from memory.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My agent runs a small digital-products side project on its own. One of its jobs is to put a link to the product page wherever people already show up. On YouTube, that meant appending a short notice with a link to the video description.&lt;/p&gt;

&lt;p&gt;It did that for 34 videos. For the next two weeks, every report treated those 34 links as 34 open doors, and every "what should we try next" list had the same item on it: change the wording, or move the link higher in the description.&lt;/p&gt;

&lt;p&gt;The product page barely moved. So the agent kept proposing better wording.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the ledgers actually said
&lt;/h2&gt;

&lt;p&gt;Two numbers were already being recorded every day, and neither one needed a guess:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Foot traffic at the door.&lt;/strong&gt; The combined view count of the 34 videos with the notice went from 5,022 to 5,025 over three days. Three views.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where the views really were.&lt;/strong&gt; Two newer videos gained 187 and 88 views in the same period. Both had a link in the description too. The product page they pointed to did not move (19, then 18).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So people were watching, and the links were there, and nobody arrived. That is not a wording problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual cause
&lt;/h2&gt;

&lt;p&gt;The agent pulled the duration of every video on the channel through the YouTube Data API. Of the 60 videos on the topic, 58 were three minutes or shorter: Shorts. Of the 34 videos carrying the notice, 33 were Shorts.&lt;/p&gt;

&lt;p&gt;YouTube's own help page is plain about it: since August 31, 2023, links in Shorts descriptions and comments are not clickable. A viewer would have to copy the address by hand.&lt;/p&gt;

&lt;p&gt;The 34 doors were painted on the wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why two weeks
&lt;/h2&gt;

&lt;p&gt;The link was defined as "the address is written in the description." Nobody asked whether the platform lets a person press it. Every later step (measuring, comparing wording, planning to move the link) was built on top of that unchecked definition, so each step looked reasonable on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A written fact in code.&lt;/strong&gt; The module that handles the channel now carries &lt;code&gt;SHORTS_DESCRIPTION_LINKS_CLICKABLE = False&lt;/code&gt;, with the help page as the comment. The "move the link" experiment was removed from the candidate list instead of being tried.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The one clickable place.&lt;/strong&gt; On Shorts, the channel profile link is clickable. The channel had zero of them. The Data API cannot set it (the branding settings it exposes are only language, description and title), so it became a two-minute task for a human in YouTube Studio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A task that closes itself.&lt;/strong&gt; The agent reads the public About page every evening. If the product link shows up, the task marks itself done. If the page cannot be read, it returns "unknown" and leaves the task open. A short or broken response is never treated as "no link".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A separate ruler.&lt;/strong&gt; The profile link points to a product that no running experiment uses, so its arrivals can be measured on their own instead of being mixed into another test.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The rule I took from it
&lt;/h2&gt;

&lt;p&gt;Before counting something as a door, check two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can it be pressed?&lt;/strong&gt; Look up the platform's own documentation for that exact spot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does anyone walk past it?&lt;/strong&gt; Check the traffic in front of it, not only the traffic behind it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both checks take minutes. Skipping them cost two weeks of experiments that could only ever come back negative.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>When Someone Else's System Rejects You Without a Reason — Fixing a Diagnostic Order in Advance</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Mon, 14 Sep 2026 04:10:06 +0000</pubDate>
      <link>https://dev.to/dbsoul/when-someone-elses-system-rejects-you-without-a-reason-fixing-a-diagnostic-order-in-advance-4n5b</link>
      <guid>https://dev.to/dbsoul/when-someone-elses-system-rejects-you-without-a-reason-fixing-a-diagnostic-order-in-advance-4n5b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 11 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Story of Losing Two Days
&lt;/h3&gt;

&lt;p&gt;I built an automation that uploads a submission file to an external service. The upload succeeded, but the next step returned&lt;br&gt;
&lt;code&gt;403 Forbidden&lt;/code&gt;. &lt;strong&gt;The response contained not a single character of explanation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agent (and I) moved like this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"It looks like account authentication is missing" → asked the user to complete phone verification&lt;/li&gt;
&lt;li&gt;Verification was already done → "Then the permission scheme must have changed" → asked for a different key to be issued&lt;/li&gt;
&lt;li&gt;That wasn't it either → "ID-based identity verification is required" → asked the user yet again&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;All three times we suspected the other side's system, and all three times we were wrong.&lt;/strong&gt; The real cause was this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The archive was built as &lt;code&gt;.zip&lt;/code&gt;, but that service accepts &lt;strong&gt;only &lt;code&gt;.tar.gz&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After changing the format, it &lt;strong&gt;passed on the first try&lt;/strong&gt;. Two days had passed in between, and during that time the user went hunting for settings screens that didn't even exist. Something that could have been checked in 5 minutes was pushed onto a person.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Why This Happens
&lt;/h3&gt;

&lt;p&gt;Two biases overlap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;① We suspect the side we can't control first.&lt;/strong&gt; The assumption that my code is wrong is uncomfortable, and blaming the other system is comfortable. On top of that, "an authentication problem" is a common story, so it sounds plausible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;② We call something a "cause" without verifying it.&lt;/strong&gt; Once you say "authentication is the cause," that sentence stays in the record, and the next judgment is built on top of it. Two days of work get stacked on a false premise.&lt;/p&gt;

&lt;p&gt;AI agents suffer from these two biases more than humans do. Producing plausible explanations &lt;strong&gt;confidently&lt;/strong&gt; is exactly what language models are good at.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. The Rule: Decide the Suspicion Order in Advance
&lt;/h3&gt;

&lt;p&gt;When you encounter an external error with no stated reason, &lt;strong&gt;always check in this order&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Order&lt;/th&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Why first&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;① &lt;strong&gt;My output&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Do the format, structure, size, and encoding match the other side's spec?&lt;/td&gt;
&lt;td&gt;I control it 100%. Checking is cheapest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;② &lt;strong&gt;My call method&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Endpoint, arguments, extension, headers&lt;/td&gt;
&lt;td&gt;Also on my side. Just compare against the docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③ &lt;strong&gt;Account, permissions, authentication&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Their territory starts here&lt;/td&gt;
&lt;td&gt;Checking is expensive and requires a human&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And the way of speaking becomes a rule too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Before verification, don't say "cause." Say "candidate."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one word keeps the record uncontaminated. A candidate can be erased, but a cause gets read as fact by the next person.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Design the Discriminating Test First
&lt;/h3&gt;

&lt;p&gt;If there are multiple candidates, first build &lt;strong&gt;a test that separates the candidates&lt;/strong&gt;. Picking one without a test is exactly what guessing is.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Candidate&lt;/th&gt;
&lt;th&gt;Discriminating test&lt;/th&gt;
&lt;th&gt;Interpreting the result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rules not agreed to&lt;/td&gt;
&lt;td&gt;Can the data list be queried?&lt;/td&gt;
&lt;td&gt;If yes, agreement is done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service configuration problem&lt;/td&gt;
&lt;td&gt;Does the metadata show a "submissions paused" flag?&lt;/td&gt;
&lt;td&gt;If not, the configuration is fine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;My file format&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Send it once in a different format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;If it passes, the format is the cause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account permissions&lt;/td&gt;
&lt;td&gt;Same call with a different account or different key&lt;/td&gt;
&lt;td&gt;Only at this point do you ask a person&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reason we lost two days is that we &lt;strong&gt;never carried the third test through to the end&lt;/strong&gt;. We postponed the cheapest test until last.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. The Sentences to Put in CLAUDE.md
&lt;/h3&gt;

&lt;p&gt;To make the agent follow this order every time, nail it into the rules file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have the memory structure built in Chapter 3, incidents like this also get recorded in &lt;code&gt;mistakes.md&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;The sole purpose of the record is to keep the same mistake from happening twice.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Locking It In with a Regression Test
&lt;/h3&gt;

&lt;p&gt;Once you've found the cause, don't stop there. Leave a test so that &lt;strong&gt;that format can never be produced again&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_submission_is_targz_not_zip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_submission&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;suffix&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.gz&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.tar.gz&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; \


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_required_files_are_at_archive_root&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tarfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;build_submission&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getnames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key is writing &lt;strong&gt;why the test exists&lt;/strong&gt; in the test's message. Without the reason, six months later someone (or an AI) deletes it as "a constraint that looks unnecessary."&lt;/p&gt;

&lt;h3&gt;
  
  
  7. How to Phrase a Request to a Human
&lt;/h3&gt;

&lt;p&gt;If you've come all the way to the end and truly need a human hand, say it like this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ "You just need to verify your identity" — an unverified assertion. If it's wrong, it wastes the other person's time.&lt;/li&gt;
&lt;li&gt;⭕ "Two candidates remain. A takes 30 seconds to check, so please start with A."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Requests also get an order and a rationale attached.&lt;/strong&gt; A person is not an unlimited testing tool.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your Own Agent Roadmap — From Safety Net to Autonomous Discovery</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Sun, 13 Sep 2026 04:10:05 +0000</pubDate>
      <link>https://dev.to/dbsoul/your-own-agent-roadmap-from-safety-net-to-autonomous-discovery-47ac</link>
      <guid>https://dev.to/dbsoul/your-own-agent-roadmap-from-safety-net-to-autonomous-discovery-47ac</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 10 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The 4 Stages of Autonomy
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Stage 1 — Safety Net (a system that prevents mistakes)
&lt;/h4&gt;

&lt;p&gt;The state where memory (Chapter 3), hook gates (Chapter 4), and the auditor (Chapter 6) are in place. The AI hasn't become more capable —&lt;br&gt;
what's been built is &lt;strong&gt;an environment where it's hard to be wrong&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Graduation criteria&lt;/strong&gt;: the recurrence rate of the same mistakes drops noticeably, and you can&lt;br&gt;
trust a "done" report without re-verifying it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Stage 2 — Active Correction (a system that checks itself)
&lt;/h4&gt;

&lt;p&gt;When it receives an instruction, before executing it checks against the records and current state — "is this direction right?" —&lt;br&gt;
and pushes back if something is off. &lt;strong&gt;Even when the human gives a wrong instruction, the system filters it once.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What to add: a direction-check procedure on receiving instructions, a one-line risk prediction before work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Graduation criteria&lt;/strong&gt;: the AI starts saying things like "that approach was rejected last month&lt;br&gt;
(evidence: this line in the records)."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Stage 3 — Autonomous Discovery (a system that finds work)
&lt;/h4&gt;

&lt;p&gt;Overnight collection and analysis (Chapters 7–8) run, and the AI presents "candidate tasks worth doing today" as a morning&lt;br&gt;
report. The human's role shifts &lt;strong&gt;from "assigning" to "choosing."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What to add: a candidate-discovery pipeline, expected-benefit and cost estimates per candidate, &lt;strong&gt;stopping criteria&lt;/strong&gt;&lt;br&gt;
(automatic cleanup of tracks that produce no results).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Graduation criteria&lt;/strong&gt;: for a week, the system produces meaningful candidates without the human instructing it first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Stage 4 — Prediction (a system that looks ahead)
&lt;/h4&gt;

&lt;p&gt;Using accumulated records and data, it warns in advance about "what will become a problem next."&lt;br&gt;
Things like approaching deadlines, signs of repeated failure, and predicted resource exhaustion.&lt;br&gt;
From here on, the agent is closer to a colleague than a tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Decision-Authority Boundary — the Precondition for Autonomy
&lt;/h3&gt;

&lt;p&gt;The thing that must be written down alongside each stage increase is &lt;strong&gt;the boundary&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;The AI on its own&lt;/th&gt;
&lt;th&gt;Human approval required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All reversible local work&lt;/td&gt;
&lt;td&gt;Anything that incurs payment or billing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collection, analysis, drafts, tests, reports&lt;/td&gt;
&lt;td&gt;External publication (publishing, pushing, sending, submitting)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrying its own failed work&lt;/td&gt;
&lt;td&gt;Irreversible operations like deletion or overwriting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The clearer the boundary, the more the human can delegate with peace of mind, and the more the AI can move without hesitation inside it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The opposite of autonomy is not control — it is ambiguity.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the boundary is blurry, two failures happen at once. The AI stalls, asking about even trivial things,&lt;br&gt;
while the genuinely risky things get done with a "this much is probably fine."&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Three Common Misconceptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Misconception 1 — "A better model will solve this."&lt;/strong&gt;&lt;br&gt;
Without a memory structure, even the best model doesn't know about yesterday. Not one of the mechanisms in this book&lt;br&gt;
is replaced by model capability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 2 — "Write the rules in more detail and they'll be followed."&lt;/strong&gt;&lt;br&gt;
As we saw in Chapter 2, it's the opposite. A rule that isn't being followed needs to be turned into &lt;strong&gt;structure&lt;/strong&gt;, not sentences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception 3 — "More autonomy is always better."&lt;/strong&gt;&lt;br&gt;
No. A Stage 3 system running without a boundary only makes the accidents bigger.&lt;br&gt;
&lt;strong&gt;Do not skip from no safety net (Stage 1) straight to autonomous discovery (Stage 3).&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The 30-Day Execution Plan
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Period&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;th&gt;Completion signal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Week 1&lt;/td&gt;
&lt;td&gt;Organize the 4 &lt;code&gt;memory/&lt;/code&gt; files + rule files (Chapters 2–3)&lt;/td&gt;
&lt;td&gt;The AI brings up yesterday's work first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 2&lt;/td&gt;
&lt;td&gt;1 hook gate + 1 auditor (Chapters 4 and 6)&lt;/td&gt;
&lt;td&gt;A "done" report gets rejected once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 3&lt;/td&gt;
&lt;td&gt;Collection script + scheduler registration (Chapters 7–8)&lt;/td&gt;
&lt;td&gt;A report is waiting for you in the morning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Week 4&lt;/td&gt;
&lt;td&gt;Organize failure records + write the boundary table (Chapters 9–10)&lt;/td&gt;
&lt;td&gt;The same mistake doesn't happen twice&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One per week is enough. &lt;strong&gt;If you install all four at once, you can't tell which one had the effect&lt;/strong&gt;,&lt;br&gt;
and when a problem occurs you won't be able to find the cause either.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Final Advice: A System Is Something You Grow
&lt;/h3&gt;

&lt;p&gt;None of the mechanisms in this book is done after a single installation. When a mistake happens, the records grow;&lt;br&gt;
when the records grow, the rules get refined; when a rule over-triggers, you loosen the gate.&lt;/p&gt;

&lt;p&gt;An agent system is less like software and more like &lt;strong&gt;a garden&lt;/strong&gt;. It belongs to the person who tends it&lt;br&gt;
a little each week; the neglected one gets covered in weeds (orphan processes, polluted records, dead hooks).&lt;/p&gt;

&lt;p&gt;If your garden is still at Stage 1, congratulations — the hardest first shovelful is already done.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>10 Common Failures and How to Recover (Based on Actual Incident Records)</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Sat, 12 Sep 2026 04:10:05 +0000</pubDate>
      <link>https://dev.to/dbsoul/10-common-failures-and-how-to-recover-based-on-actual-incident-records-mjc</link>
      <guid>https://dev.to/dbsoul/10-common-failures-and-how-to-recover-based-on-actual-incident-records-mjc</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 9 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;p&gt;This chapter is the most practical part of this book. All ten of these &lt;strong&gt;actually happened&lt;/strong&gt;,&lt;br&gt;
and most of them happened more than once. From the second time on, they were stopped by installing structure.&lt;/p&gt;


&lt;h3&gt;
  
  
  Failure 1 — Asserting from Guesswork
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: The AI asserts system state (whether a process is running, whether a file exists, a config value) without checking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actual incident&lt;/strong&gt;: While the user was &lt;strong&gt;actively using the computer&lt;/strong&gt;, the AI asserted "the machine is currently in sleep mode."&lt;br&gt;
Sleep state is 100% verifiable with a single command, yet a plausible guess was stated as fact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Early signal&lt;/strong&gt;: The wording is "it is ~" rather than "it seems ~", but no command was executed that turn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Put a table of verification commands into your rules file. With the list in place, compliance rises noticeably.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fact you're about to assert&lt;/th&gt;
&lt;th&gt;Verification command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Whether a process is running&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Get-Process &amp;lt;name&amp;gt;&lt;/code&gt; / &lt;code&gt;tasklist /FI&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File/folder existence&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Test-Path&lt;/code&gt; / &lt;code&gt;ls&lt;/code&gt; (the real file, not memory)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Port occupancy&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Get-NetTCPConnection -LocalPort N&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote connectivity&lt;/td&gt;
&lt;td&gt;actual &lt;code&gt;ping&lt;/code&gt; / &lt;code&gt;curl&lt;/code&gt; results&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h3&gt;
  
  
  Failure 2 — False Completion
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Treating &lt;code&gt;rc=0&lt;/code&gt; or a &lt;code&gt;"started"&lt;/code&gt; log line as evidence of completion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actual incident&lt;/strong&gt;: A scheduled task was reported as "registered and done," but &lt;strong&gt;it had never been run even once.&lt;/strong&gt;&lt;br&gt;
The registration succeeded, but the path was broken, so in practice it was set up to fail silently every day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Change the completion criterion from "the command succeeded" to &lt;strong&gt;"the target's state changed."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_done&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;REPORT_DIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;digest_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;today&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On top of this, add the &lt;strong&gt;independent auditor&lt;/strong&gt; from Chapter 6. The one who built the work must not be the one who passes judgment on it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Failure 3 — Not Checking the Records
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Yesterday's solution is in the records, but it goes unread and the same struggle repeats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actual incident&lt;/strong&gt;: The same encoding problem was solved three times. All three times it was approached as if seen for the first time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Install a &lt;strong&gt;gate that forcibly checks&lt;/strong&gt; whether the records were read (the hooks from Chapter 4).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;read_this_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROJECT&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory/diary.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key is to &lt;strong&gt;not count "I saw the summary" as having checked&lt;/strong&gt;. Seeing an auto-injected three-line summary&lt;br&gt;
and actually reading the file are different things.&lt;/p&gt;


&lt;h3&gt;
  
  
  Failure 4 — Encoding Corruption (Essential for Korean-Language Windows Environments)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Korean text gets garbled in output, in subprocesses, and in file writes that go through the shell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Block all three places. If any one is missed, corruption comes in through that path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reconfigure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reconfigure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;replace&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put &lt;strong&gt;no Korean at all&lt;/strong&gt; into batch files. If a path contains Korean, add a single English-path wrapper.&lt;/p&gt;




&lt;h3&gt;
  
  
  Failure 5 — Variable and Path Destruction at Shell Boundaries
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Using a PowerShell variable from bash yields an empty string, and unquoted Windows paths&lt;br&gt;
lose their backslashes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;powershell &lt;span class="nt"&gt;-Command&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt; = 'C:&lt;/span&gt;&lt;span class="se"&gt;\T&lt;/span&gt;&lt;span class="s2"&gt;emp'; ls &lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

powershell &lt;span class="nt"&gt;-File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEMP&lt;/span&gt;&lt;span class="s2"&gt;/task.ps1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Don't mix shells. Any other-shell command longer than two lines gets &lt;strong&gt;saved to a file and executed&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Failure 6 — Silent Failure
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Errors swallowed by &lt;code&gt;try/except&lt;/code&gt;; "0 items, successfully."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Make failure a &lt;strong&gt;first-class citizen&lt;/strong&gt; of the output format. Build a failure slot into the report template itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;failures&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;failures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Zero results is a warning, not a success.&lt;/strong&gt; This one line prevents a dead parser from sitting unnoticed for weeks.&lt;/p&gt;




&lt;h3&gt;
  
  
  Failure 7 — Orphan Process Accumulation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Processes left behind by automation paralyze the system weeks later.&lt;br&gt;
This is the number one cause of "my computer suddenly got slow."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Duplicate-run check + periodic cleanup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gettempdir&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;collect.lock&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_mtime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;touch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Failure 8 — Working Around Instead of Fixing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: When blocked, taking a side path (retrying, another tool, a temp file) instead of fixing the cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actual incident&lt;/strong&gt;: When a file write failed, the file was saved to a different folder and the work moved on. The consumer of&lt;br&gt;
that file was watching the original path, so &lt;strong&gt;it kept running on stale data with no error.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Make it a rule: "after 2 attempts, stop and report the cause." A workaround is debt —&lt;br&gt;
it keeps rolling for now, but it comes back with interest.&lt;/p&gt;




&lt;h3&gt;
  
  
  Failure 9 — Trusting Documents
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Believing documents, comments, and past summaries as truth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Principle&lt;/strong&gt;: &lt;strong&gt;Documents are the map; code is the territory.&lt;/strong&gt; When the two disagree, the code is always right.&lt;br&gt;
Before any important judgment, look directly at the source code or the actual execution result.&lt;/p&gt;




&lt;h3&gt;
  
  
  Failure 10 — Copy-Pasting Stale Memory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: A summary that was correct in the past is wrong now, but it gets asserted as-is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actual incident&lt;/strong&gt;: When auto-generated logs piled up in &lt;code&gt;mistakes.md&lt;/code&gt;, the AI &lt;strong&gt;mistook them for current issues&lt;/strong&gt;&lt;br&gt;
and repeated the same wrong answer 16 times. A case where the records actually ruined the judgment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: &lt;strong&gt;Split the record files by purpose.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;What goes in it — and nothing else&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;diary.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Context of actual work done by a person&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mistakes.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only mistakes &lt;strong&gt;a person pointed out&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;audit-log.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All automated logs produced by scripts and cron&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The moment automated logs mix into human records, memory turns from an asset into a liability.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Common Principle of Recovery
&lt;/h3&gt;

&lt;p&gt;When an incident happens, the order is always the same.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stop&lt;/strong&gt; — cut off further damage first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Establish the current state by direct measurement&lt;/strong&gt; — don't guess at what broke.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record the cause&lt;/strong&gt; — together with the correct method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add one structure that prevents the same incident&lt;/strong&gt; — a hook, a test, or a checklist.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Recovery is not finished until step ④.&lt;/strong&gt; Stop at step 3, and the same incident happens six months later.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>Real-World Project: A Posting Collection &amp; Analysis Agent from Start to Finish</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Fri, 11 Sep 2026 04:10:06 +0000</pubDate>
      <link>https://dev.to/dbsoul/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish-1g2j</link>
      <guid>https://dev.to/dbsoul/real-world-project-a-posting-collection-analysis-agent-from-start-to-finish-1g2j</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 8 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Defining the Goal — If You Can't Write It in One Sentence, Don't Start
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"Automatically collect contest and grant-program postings every day, filter out risky clauses, and produce&lt;br&gt;
a one-page report to read in the morning."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The input (posting sites), processing (parsing and filtering), output (digest), and schedule (every morning) are all in one sentence.&lt;br&gt;
When you hand work to an AI, this sentence becomes &lt;strong&gt;both the work order and the completion criterion&lt;/strong&gt;. If it's fuzzy,&lt;br&gt;
the AI will very quickly build "something plausible that isn't what I wanted."&lt;/p&gt;

&lt;p&gt;The first prompt handed to the agent looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If you don't write the "completion criterion," the AI's definition of done is "I finished writing the code."&lt;/strong&gt; The done we want is&lt;br&gt;
"it runs." This two-line difference is also why the auditor from Chapter 6 is needed.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Step 1 — Measure: Don't Build a Parser from Guesses
&lt;/h3&gt;

&lt;p&gt;The AI will plausibly guess, "that site usually has this kind of structure." &lt;strong&gt;A parser built from that guess is&lt;br&gt;
always wrong.&lt;/strong&gt; Enforce the order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sL&lt;/span&gt; &lt;span class="s2"&gt;"https://example.org/contest/list"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/list.html
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'class="[a-z_-]*"'&lt;/span&gt; /tmp/list.html | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Measuring reveals things you could never know from guessing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first item in the list is an &lt;strong&gt;ad banner&lt;/strong&gt;, so it always contaminates the parse&lt;/li&gt;
&lt;li&gt;The title link is an external URL, and the real posting ID is in &lt;strong&gt;a different tag next to it&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The list page &lt;strong&gt;already contains closed postings&lt;/strong&gt; ← we missed this and it actually caused an incident&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The third one is a failure we actually experienced. Without parsing the closed/open status, we assumed "it's on the list, so it's still open"&lt;br&gt;
and &lt;strong&gt;reported a contest that had already ended as a participation candidate.&lt;/strong&gt; We were verifying the hard things like eligibility and terms&lt;br&gt;
while missing the most basic question: "is it accepting entries right now?" So this rule is now baked into the collector.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Checklist before recommending anything to a human: ① Is it accepting entries? ② Are we eligible? ③ Are the terms safe?&lt;br&gt;
Only something that passes all three is a candidate.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  3. Step 2 — Tests First: Turn Measured Fragments into Fixtures
&lt;/h3&gt;

&lt;p&gt;Freeze the HTML fragments confirmed during measurement directly into test fixtures. Even if the site changes later,&lt;br&gt;
these tests guard against regressions in &lt;strong&gt;the parser logic itself&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tests/test_collector.py
&lt;/span&gt;&lt;span class="n"&gt;SAMPLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
&amp;lt;div class=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list-item&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list-item&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_only_open_contests_are_collected&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SAMPLE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_deadline_is_extracted&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;parse_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SAMPLE&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deadline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-09-18&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Writing tests first narrows the AI's scope of work. Instead of "make something reasonably good," it becomes&lt;br&gt;
&lt;strong&gt;"make these tests pass."&lt;/strong&gt; This is the strongest form of control you have when delegating work to an AI.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Step 3 — Implement: Build "No Silent Failures" into the Design
&lt;/h3&gt;

&lt;p&gt;Keep the collector as independent modules per source, so that if one dies the rest keep running.&lt;br&gt;
&lt;strong&gt;In exchange, a dead source must always appear in the report.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collect_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;failures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;failures&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the top of the report starts like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A system that only shows success counts cannot be trusted. &lt;strong&gt;Failures must appear on the same line&lt;/strong&gt; for a human to believe it.&lt;br&gt;
How a single &lt;code&gt;except: pass&lt;/code&gt; line quietly kills a system is covered in detail in Chapter 9.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Step 4 — The Terms Filter: Domain Knowledge as Code
&lt;/h3&gt;

&lt;p&gt;The real value of this project is not collection but &lt;strong&gt;selection&lt;/strong&gt;. It finds risky clauses in posting terms&lt;br&gt;
and classifies them as risky, caution, or safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;RISK_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;judge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;why&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;why&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;RISK_PATTERNS&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your domain surely has a "pre-participation checklist" like this too. Toxic contract clauses, a client's creditworthiness,&lt;br&gt;
delivery terms — whatever it is, &lt;strong&gt;the moment you move the checklist from your head into code, mistakes are structurally blocked.&lt;/strong&gt;&lt;br&gt;
A tired human skips steps; a regex never does.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Step 5 — Assembly and Audit
&lt;/h3&gt;

&lt;p&gt;When putting it on the scheduler, follow the rules from Chapter 7 (English-only paths end to end + the wrapper chain) exactly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then hand verification to the &lt;strong&gt;independent auditor&lt;/strong&gt; (Chapter 6) along with the goal sentence. In practice, the auditor&lt;br&gt;
caught "it was only registered and never actually executed once," and the cross-AI review got the RSS parsing&lt;br&gt;
changed from regex to a standard XML parser. &lt;strong&gt;Working alone, I would have missed both.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. The Daily Routine After Completion
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Who&lt;/th&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;09:30&lt;/td&gt;
&lt;td&gt;System&lt;/td&gt;
&lt;td&gt;Collect → filter → generate digest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 min in the morning&lt;/td&gt;
&lt;td&gt;Human&lt;/td&gt;
&lt;td&gt;Check new items (🆕) and the &lt;strong&gt;failures section&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5 min in the morning&lt;/td&gt;
&lt;td&gt;Human&lt;/td&gt;
&lt;td&gt;Run the terms filter only on postings of interest, then decide whether to participate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The system does the collecting and selecting; the human only makes &lt;strong&gt;decisions&lt;/strong&gt;. That division of labor is the target state of an autonomous agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Porting This Structure to Other Fields
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Collection target&lt;/th&gt;
&lt;th&gt;Risky clauses (filter)&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Freelancing&lt;/td&gt;
&lt;td&gt;Outsourcing postings&lt;/td&gt;
&lt;td&gt;Unlimited revisions, full IP transfer&lt;/td&gt;
&lt;td&gt;3 gigs to apply for&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Job hunting&lt;/td&gt;
&lt;td&gt;Job postings&lt;/td&gt;
&lt;td&gt;Inclusive-wage clauses, probation pay cuts&lt;/td&gt;
&lt;td&gt;Application candidates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real estate&lt;/td&gt;
&lt;td&gt;Listings&lt;/td&gt;
&lt;td&gt;Existing mortgages, special conditions&lt;/td&gt;
&lt;td&gt;Site-visit candidates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development&lt;/td&gt;
&lt;td&gt;Release notes&lt;/td&gt;
&lt;td&gt;Breaking changes&lt;/td&gt;
&lt;td&gt;Upgrade caution list&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The only things that change are the parser and the regexes; &lt;strong&gt;the skeleton (measure → fixtures → independent modules → visible failures → audit)&lt;br&gt;
stays the same.&lt;/strong&gt; Build this skeleton once, and the next agent takes half a day.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Automation Pipeline — Pairing with a Scheduler So It Works at Night Too</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Thu, 10 Sep 2026 04:10:04 +0000</pubDate>
      <link>https://dev.to/dbsoul/the-automation-pipeline-pairing-with-a-scheduler-so-it-works-at-night-too-4ebg</link>
      <guid>https://dev.to/dbsoul/the-automation-pipeline-pairing-with-a-scheduler-so-it-works-at-night-too-4ebg</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 7 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Basic Shape of a Pipeline
&lt;/h3&gt;

&lt;p&gt;The minimal setup for scheduled execution is three pieces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The human's role changes &lt;strong&gt;from "running" to "reviewing"&lt;/strong&gt; — this is the essence of automation.&lt;br&gt;
If you added automation but still have to click something every day, that's not automation, it's a keyboard shortcut.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. The 3 Big Windows Traps (All Based on Real Incidents)
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Trap 1 — Console Window Flashing
&lt;/h4&gt;

&lt;p&gt;If the scheduler runs &lt;code&gt;python&lt;/code&gt; or a &lt;code&gt;.bat&lt;/code&gt; directly, a black window pops up every few minutes and interrupts your work.&lt;br&gt;
&lt;code&gt;-WindowStyle Hidden&lt;/code&gt; still leaves a flash, because it hides the window only after it has been created.&lt;br&gt;
The proper approach is a &lt;strong&gt;wscript + .vbs wrapper&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Set shell = CreateObject("WScript.Shell")
rc = shell.Run("""C:\Python312\python.exe"" ""C:\TaskWrappers\run.py""", 0, True)
WScript.Quit rc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third argument &lt;code&gt;0&lt;/code&gt; means "no window," and the fourth, &lt;code&gt;True&lt;/code&gt;, means "wait until it finishes."&lt;br&gt;
You must include &lt;code&gt;WScript.Quit rc&lt;/code&gt; for the &lt;strong&gt;scheduler to recognize a failure as a failure.&lt;/strong&gt; If you leave this out,&lt;br&gt;
the script can fail every single day while the scheduler's history records success.&lt;/p&gt;
&lt;h4&gt;
  
  
  Trap 2 — Korean Path Encoding
&lt;/h4&gt;

&lt;p&gt;If you register a Korean path in the scheduler through a shell, the encoding can get corrupted as it is saved.&lt;br&gt;
This is the worst kind of failure: &lt;strong&gt;registration looks successful, only execution fails.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The proper approach is to split the path chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;run.py&lt;/code&gt; is a launcher of fewer than ten lines. This single layer blocks the entire class of encoding incidents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reconfigure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_collect.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                        &lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PROJECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;replace&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After registering, always verify that &lt;strong&gt;the saved content contains no Korean characters&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Trap 3 — Orphan Process Accumulation
&lt;/h4&gt;

&lt;p&gt;When unattended execution fails repeatedly, zombie processes pile up, and one day the whole computer slows down.&lt;br&gt;
This is the &lt;strong&gt;number one cause of "my computer suddenly got slow."&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gettempdir&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;collect.lock&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_mtime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;touch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the &lt;code&gt;finally&lt;/code&gt;, one crash turns it into automation that &lt;strong&gt;never runs again&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Safety Rules for Unattended Execution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;① No silent failures.&lt;/strong&gt; Do not swallow per-source failures — surface them in the report as a "failures section."&lt;br&gt;
Treat a zero-item collection not as "a successful zero" but as a &lt;strong&gt;"suspected structure change" warning&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;② Registered ≠ working.&lt;/strong&gt; After registering the schedule, always run it manually once and check the exit code&lt;br&gt;
and the output artifact. A successful-registration message proves nothing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;schtasks /run /tn MyTask
&lt;span class="nb"&gt;timeout &lt;/span&gt;60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;③ Prevent duplicates with a state file.&lt;/strong&gt; Record "what has already been seen" so only new items appear each day.&lt;br&gt;
If the report says the same thing every day, people stop reading it — and an unread report is the same as no report.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SEEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;SEEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;SEEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;})))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Deployment Checklist (Follow This As-Is and Incidents Don't Happen)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Does running the script standalone produce the output artifact?&lt;/li&gt;
&lt;li&gt;[ ] Is the exit code non-zero on failure? (check with &lt;code&gt;echo $?&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;[ ] Does the vbs wrapper propagate the exit code?&lt;/li&gt;
&lt;li&gt;[ ] Is the path registered in the scheduler free of Korean characters?&lt;/li&gt;
&lt;li&gt;[ ] Did you &lt;strong&gt;run it manually once after registering&lt;/strong&gt; and confirm the output artifact?&lt;/li&gt;
&lt;li&gt;[ ] On failure, does the failure show up in the report? (test by disconnecting the network)&lt;/li&gt;
&lt;li&gt;[ ] Is the duplicate-execution lock released via &lt;code&gt;finally&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;[ ] A few days later, is the process list free of leftovers?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last two items must be checked &lt;strong&gt;a few days later&lt;/strong&gt;. They never show up on deployment day.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. How Often Should It Run?
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Interval&lt;/th&gt;
&lt;th&gt;Suited for&lt;/th&gt;
&lt;th&gt;Caution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Every 5–15 min&lt;/td&gt;
&lt;td&gt;Watching (monitoring), alerts&lt;/td&gt;
&lt;td&gt;Orphan processes accumulate fastest here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Once daily&lt;/td&gt;
&lt;td&gt;Collection, summaries, reports&lt;/td&gt;
&lt;td&gt;Most automation belongs here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Once weekly&lt;/td&gt;
&lt;td&gt;Cleanup, checkups, backups&lt;/td&gt;
&lt;td&gt;hooks self-checks go here too&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;When in doubt, start with once a day.&lt;/strong&gt; Short intervals surface problems faster, but they&lt;br&gt;
accumulate side effects at the same speed.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Independent Auditor Pattern — "Don't Let the Thing That Built It Verify It"</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Wed, 09 Sep 2026 04:10:03 +0000</pubDate>
      <link>https://dev.to/dbsoul/the-independent-auditor-pattern-dont-let-the-thing-that-built-it-verify-it-4bbo</link>
      <guid>https://dev.to/dbsoul/the-independent-auditor-pattern-dont-let-the-thing-that-built-it-verify-it-4bbo</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 6 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Problem Isn't Lying — It's Confirmation Bias
&lt;/h3&gt;

&lt;p&gt;When an AI says "done," much of the time it isn't lying — it's &lt;strong&gt;self-conviction&lt;/strong&gt;.&lt;br&gt;
The script ran (&lt;code&gt;rc=0&lt;/code&gt;), the log shows &lt;code&gt;started&lt;/code&gt;, so it believes the job is done.&lt;br&gt;
It's exactly the same disease as a human developer going easy on their own code in review, and the prescription is the same —&lt;br&gt;
&lt;strong&gt;separate the person who builds from the person who inspects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There's one more thing. An AI &lt;strong&gt;treats what it just said as evidence.&lt;/strong&gt; Once it says&lt;br&gt;
"the tests passed," every judgment after that is built on top of that sentence — regardless of&lt;br&gt;
whether the tests were actually run. That's why the inspector must &lt;strong&gt;receive none of the worker's words as input.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. The 4 Design Principles for an Auditor Agent
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;① Trust only the filesystem.&lt;/strong&gt;&lt;br&gt;
Do not accept the worker's explanations, summaries, or excuses as input. Only actual files,&lt;br&gt;
actual test run results, and actual process state count as evidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;② PASS/FAIL, binary.&lt;/strong&gt;&lt;br&gt;
Ban gray verdicts like "it mostly went well." The moment you allow gray, &lt;strong&gt;every verdict&lt;br&gt;
becomes gray.&lt;/strong&gt; Humans read gray as a pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;③ Compare against the original instruction.&lt;/strong&gt;&lt;br&gt;
Don't give the auditor just the output — give it &lt;strong&gt;the user's original instruction&lt;/strong&gt; as well.&lt;br&gt;
The criterion is "did it do what was asked," not "did it do something."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;④ Reproduce the claims.&lt;/strong&gt;&lt;br&gt;
If the worker claims "tests passed," the auditor runs them again itself. In a real case, the worker&lt;br&gt;
reported "scheduled task registered — done," but &lt;strong&gt;had never run it even once&lt;/strong&gt;; the auditor&lt;br&gt;
launched the task itself, got exit code 0, and only then did it earn a PASS.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. The Auditor Definition File (Copy It As-Is)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auditor&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;




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

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Restricting the tools to read-only is the key.&lt;/strong&gt; Give the auditor write access and it&lt;br&gt;
will start doing "I fixed it, so PASS" — and at that moment its independence is gone.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Operating Rule: No "Done" Without a PASS
&lt;/h3&gt;

&lt;p&gt;An auditor that merely exists goes unused. Put one line in your rules file:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do not use the word "done" without an auditor PASS.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are three mandatory call points.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Point&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Right before reporting completion&lt;/td&gt;
&lt;td&gt;The most basic one. This is where false completions get caught&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When the user asks "is it done?"&lt;/td&gt;
&lt;td&gt;That question itself is already a signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;At the end of a long session&lt;/td&gt;
&lt;td&gt;The longer the context, the more "I believe it's done" errors accumulate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Combined with the hooks from Chapter 4, it's even more reliable. In the session-end hook,&lt;br&gt;
check whether the auditor was called, and block termination if it wasn't.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Completing It with a 3-Stage Verification System
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Actor&lt;/th&gt;
&lt;th&gt;What it catches&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;① Tests (TDD)&lt;/td&gt;
&lt;td&gt;Code&lt;/td&gt;
&lt;td&gt;Spec violations, regressions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;② Independent auditor&lt;/td&gt;
&lt;td&gt;Same model, different role&lt;/td&gt;
&lt;td&gt;False completions, instruction-result mismatches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③ Cross-AI review&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;A different model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Blind spots shared by the same model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reason ③ is needed is simple. &lt;strong&gt;The same model fails in the same habitual ways.&lt;/strong&gt; Among the things&lt;br&gt;
cross-review actually caught was one like "you're parsing RSS with a regex" — something an auditor&lt;br&gt;
running on the same model had looked at three times and never flagged.&lt;/p&gt;

&lt;p&gt;A different model's findings also come with &lt;strong&gt;plenty of false positives.&lt;/strong&gt; So set handling rules in advance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recording the rejection reason matters. If you don't, &lt;strong&gt;the same finding comes back in the next review and you deliberate all over again.&lt;/strong&gt;&lt;br&gt;
Our code actually carries comments like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. When the Auditor Is Wrong
&lt;/h3&gt;

&lt;p&gt;The auditor isn't perfect either. &lt;strong&gt;Verify the auditor's findings with actual measurements too.&lt;/strong&gt; In one real case,&lt;br&gt;
the auditor claimed "this setting drops performance by 2.45%p," but re-measuring showed&lt;br&gt;
that number &lt;strong&gt;came from an old condition&lt;/strong&gt; and did not reproduce under the current one.&lt;/p&gt;

&lt;p&gt;So the order is this: &lt;strong&gt;auditor's FAIL → confirm by measurement → fix if true, otherwise reject with evidence.&lt;/strong&gt;&lt;br&gt;
"Because the auditor said so" is the same sentence as "because the AI said so."&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>Skills and Subagents — The Art of Splitting Work and Delegating It</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Tue, 08 Sep 2026 04:10:05 +0000</pubDate>
      <link>https://dev.to/dbsoul/skills-and-subagents-the-art-of-splitting-work-and-delegating-it-53fm</link>
      <guid>https://dev.to/dbsoul/skills-and-subagents-the-art-of-splitting-work-and-delegating-it-53fm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 5 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. A Skill = A Procedure Turned into a File
&lt;/h3&gt;

&lt;p&gt;Take a work procedure you used to explain verbally every time (a review checklist, a deployment sequence, a logging format) and save it as a file, and a single invocation loads the entire procedure. The key effect is that &lt;strong&gt;the quality of the procedure is decoupled from how you're doing that day&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;There are three signals that something is worth turning into a skill.&lt;br&gt;
① You've repeated the same explanation three or more times ② Skipping a step causes an incident&lt;br&gt;
③ It can be used in other projects too.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. A Subagent = Delegating to Another "Head"
&lt;/h3&gt;

&lt;p&gt;A subagent is a lower-level AI that works independently &lt;strong&gt;in a separate context&lt;/strong&gt; and returns only the result.&lt;br&gt;
There are two criteria for deciding what to split off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;① Contamination isolation.&lt;/strong&gt; Work that clutters the context — mass searches, long log analysis — should be done by a subagent that brings back &lt;strong&gt;only the conclusion&lt;/strong&gt;. The main agent's thinking space stays clean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;② Role isolation.&lt;/strong&gt; Work where "the person who builds and the person who checks must be different" — verification, audits — must always be separated (Chapter 6).&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Work That Must Not Be Split Off
&lt;/h3&gt;

&lt;p&gt;Conversely, &lt;strong&gt;core design decisions must be made by the main agent directly&lt;/strong&gt;. Delegate the judgment too, and two things collapse.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accountability&lt;/strong&gt;: if you accept a subagent's conclusion as-is, the main agent can't explain why that decision was made.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context&lt;/strong&gt;: a subagent doesn't know the project's history (records, failures, constraints). A "recommendation" made in that state is often a proposal that was already rejected.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;You can divide the hands, but there must be one head.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And a subagent's report is &lt;strong&gt;a result, not a fact.&lt;/strong&gt; There was an actual case where a subagent reported "this setting is degrading performance," the change was applied as-is, and re-measurement showed the numbers were from the old conditions. &lt;strong&gt;Verify the conclusions you receive, too.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. A "System That Doesn't Forget": Keyword Auto-Mapping
&lt;/h3&gt;

&lt;p&gt;Once you pass 10 skills, both the AI and the human forget which skills exist.&lt;br&gt;
The solution is to put a &lt;strong&gt;keyword → skill mapping table&lt;/strong&gt; in the input hook (Chapter 4).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TRIGGERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TRIGGERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last sentence matters. &lt;strong&gt;Displaying the recommendation without invoking it is meaningless, so state the rule alongside it: "when the header appears, actually invoke it in that turn."&lt;/strong&gt;&lt;br&gt;
In actual operation, when this one line was missing, recommendations appeared and nobody used them.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. An Example of Skill Placement by Stage
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Skill type&lt;/th&gt;
&lt;th&gt;When to call it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Planning&lt;/td&gt;
&lt;td&gt;Brainstorming, requirements interview&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Before&lt;/strong&gt; writing code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation&lt;/td&gt;
&lt;td&gt;TDD guide, subtask distribution&lt;/td&gt;
&lt;td&gt;Right before implementing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verification&lt;/td&gt;
&lt;td&gt;Self-review → independent audit → cross-AI&lt;/td&gt;
&lt;td&gt;Right before committing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrap-up&lt;/td&gt;
&lt;td&gt;Work log, handoff notes&lt;/td&gt;
&lt;td&gt;End of session&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Calling only the skills that fit the stage is a skill in itself.&lt;/strong&gt; Call everything and you just waste context, and the procedure you actually need gets buried.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. When You Take Skills from Someone Else
&lt;/h3&gt;

&lt;p&gt;When installing a public skill collection, remember just one thing.&lt;br&gt;
&lt;strong&gt;Star counts are not a quality guarantee.&lt;/strong&gt; The install script may contain prompt injection (instructions that neutralize your rules). Always open and read the files before installing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Hook System — Blocking AI Mistakes with Structure</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Sun, 06 Sep 2026 21:22:54 +0000</pubDate>
      <link>https://dev.to/dbsoul/the-hook-system-blocking-ai-mistakes-with-structure-2k69</link>
      <guid>https://dev.to/dbsoul/the-hook-system-blocking-ai-mistakes-with-structure-2k69</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 4 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. A Hook Is a Safety Mechanism Outside the AI
&lt;/h3&gt;

&lt;p&gt;A rules file is something the AI &lt;strong&gt;tries to follow&lt;/strong&gt;; a hook is something the system uses to &lt;strong&gt;make it be followed&lt;/strong&gt;.&lt;br&gt;
This difference is bigger than it looks. Rules get buried as context grows longer, get skipped when things are urgent,&lt;br&gt;
and "just this once" exceptions pile up. Hooks don't do that.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Point&lt;/th&gt;
&lt;th&gt;Timing&lt;/th&gt;
&lt;th&gt;Typical use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UserPromptSubmit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Right after the user types input&lt;/td&gt;
&lt;td&gt;Automatic context injection (record summaries, related rules)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PreToolUse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Right before&lt;/strong&gt; a tool runs&lt;/td&gt;
&lt;td&gt;Blocking dangerous actions (gates)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PostToolUse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Right after a tool runs&lt;/td&gt;
&lt;td&gt;After-the-fact checks (contamination detection, follow-up procedure reminders)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When the response ends&lt;/td&gt;
&lt;td&gt;Quality gates (forbidden-word detection, verification requirements)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Registration happens in one place, the settings file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PreToolUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Write|Edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python C:/hooks/record_gate.py"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Pattern A — The Blocking Hook (Gate)
&lt;/h3&gt;

&lt;p&gt;This is a gate that blocks "attempts to modify a file without reading the records first." What follows is&lt;br&gt;
a shortened version of one actually in use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;STATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gettempdir&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_state.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;REQUIRED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory/diary.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory/mistakes.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# hooks receive the tool call on stdin
&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Read&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;REQUIRED&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;🔒 Records not read yet. Read these before editing:
  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;  - &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
Retry the same action after reading and it will pass.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key is the last sentence. &lt;strong&gt;If you also return "what to do to pass," the AI recovers on its own.&lt;/strong&gt;&lt;br&gt;
The rule gets enforced without a human having to step in.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Pattern B — The Injection Hook
&lt;/h3&gt;

&lt;p&gt;On every input, automatically insert the most recent contents of the records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;heads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;## &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;heads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;memory/diary.md&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;memory/mistakes.md&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That said, injection is &lt;strong&gt;strictly an aid&lt;/strong&gt;. It breeds the habit of looking only at the summary and never reading&lt;br&gt;
the original, so for important work we still use a gate to force a &lt;code&gt;Read&lt;/code&gt; of the original.&lt;br&gt;
(Our gate message actually contains this sentence — &lt;em&gt;"seeing the injected summary does not count as checking."&lt;/em&gt;)&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Pattern C — The After-the-Fact Reminder Hook
&lt;/h3&gt;

&lt;p&gt;Some procedures are too minor to block on but too important to just let slide. For example, "if you committed, update the handoff note too."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git commit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;handoff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PROJECT&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory/HANDOFF.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;modified_today&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handoff&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
              &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;once-per-session limit&lt;/strong&gt; matters. If it pops up every time, it just gets ignored — and a hook that gets ignored is a hook that doesn't exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Three Operational Pitfalls (We Hit All of Them)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;① Silent blocking.&lt;/strong&gt; If a hook returns only an exit code with no reason, the AI concludes "the tool is broken"&lt;br&gt;
and attempts some misguided workaround. A blocking message must &lt;strong&gt;always include the reason and the way to resolve it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;② False positives.&lt;/strong&gt; Once a gate starts blocking normal work too, the human gets annoyed and turns the hook off,&lt;br&gt;
and at that moment the entire safety mechanism disappears. One over-blocking gate really was removed in the end.&lt;br&gt;
&lt;strong&gt;Put gates only on patterns that are clearly dangerous, and steer everything else gently with injection hooks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;③ Hooks die quietly.&lt;/strong&gt; This is the scariest one. A script path changed, nobody noticed,&lt;br&gt;
and months went by. We believed we were safe while the safety mechanism wasn't there at all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;HOOKS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. How Far Should Hooks Go?
&lt;/h3&gt;

&lt;p&gt;Hooks are not a cure-all. There is exactly one criterion for the call.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Has the same mistake happened twice?&lt;/strong&gt; Then make it a hook. If it happened once, record it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you turn every one-time incident into a hook, the system becomes a mass of rules and eventually heads&lt;br&gt;
toward the false positives of ②. &lt;strong&gt;Twice is a signal that it's not chance but a structural problem&lt;/strong&gt; — and structural problems get solved with structure.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>Memory-Driven Development — Making the AI Remember What It Did Yesterday</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Sun, 06 Sep 2026 04:10:04 +0000</pubDate>
      <link>https://dev.to/dbsoul/memory-driven-development-making-the-ai-remember-what-it-did-yesterday-34dd</link>
      <guid>https://dev.to/dbsoul/memory-driven-development-making-the-ai-remember-what-it-did-yesterday-34dd</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 3 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The AI's Fatal Weakness Is Not Skill — It's Memory
&lt;/h3&gt;

&lt;p&gt;Give the same AI the same project, and if it doesn't know yesterday's trial and error, it trips&lt;br&gt;
over the same spot again today. The solution isn't switching models — it's building&lt;br&gt;
&lt;strong&gt;file-based external memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's clear up one misconception first. "Can't you just feed it a good summary?" — No.&lt;br&gt;
A summary only works &lt;strong&gt;on the premise that you already know what matters&lt;/strong&gt;. But yesterday's me&lt;br&gt;
didn't know what would become a problem today. That's why records must be the &lt;strong&gt;original text&lt;/strong&gt;,&lt;br&gt;
not a summary — and instead, they must be split up so they're &lt;strong&gt;easy to find&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. The 4-File Structure
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;When it's read&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory/diary.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Chronological work context&lt;/td&gt;
&lt;td&gt;Session start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory/mistakes.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only mistakes &lt;strong&gt;a human pointed out&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Session start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory/MEMORY.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A map of facts that don't change&lt;/td&gt;
&lt;td&gt;Session start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory/HANDOFF.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Current state and what to do next&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;First of all&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;diary.md&lt;/code&gt; — the work journal.&lt;/strong&gt; Accumulate a few lines per session: "when, what, why,&lt;br&gt;
and how it ended." If you make date headers (&lt;code&gt;## 2026-08-07 ...&lt;/code&gt;) a rule, it's easy for a hook&lt;br&gt;
to extract and inject only the recent entries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;mistakes.md&lt;/code&gt; — the mistake record.&lt;/strong&gt; Fixing the format is the key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## [2026-08-06] Blamed the account for a 403 without checking my own file&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**- **&lt;/span&gt;What went wrong&lt;span class="gs"&gt;****&lt;/span&gt;: Saw a reasonless 403 and suspected their system three times
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**- **&lt;/span&gt;Why it was wrong&lt;span class="gs"&gt;****&lt;/span&gt;: Skipped what I control (file format) and looked at their side first
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**- **&lt;/span&gt;The right way&lt;span class="gs"&gt;****&lt;/span&gt;: Check my output, then my call, then the account. Before checking, say "candidate", not "cause"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A record that ends with "I did it wrong" cannot prevent repetition.&lt;/strong&gt; Only when the third line&lt;br&gt;
(the correct method) is there does the record become prevention. The AI in the next session can&lt;br&gt;
change its behavior by reading that line alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;MEMORY.md&lt;/code&gt; — the core index.&lt;/strong&gt; A single page holding only the project's invariant facts&lt;br&gt;
(structure, constraints, prohibitions). If diary is the chronological flow, MEMORY is the map.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;HANDOFF.md&lt;/code&gt; — the handover note.&lt;/strong&gt; Write only what will &lt;strong&gt;cause an accident if the next&lt;br&gt;
session doesn't know it&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## What is running now&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Daily 09:30 collector (verify: schtasks /query /tn ...)
&lt;span class="gu"&gt;## Changes that must not be reverted&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Weakness scoring is OFF. Measured evidence says so; do not turn it back on because "the rule says so"
&lt;span class="gu"&gt;## Waiting on the owner's decision&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Ebook price, whether to enter the competition
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file was added last, but in practice it became &lt;strong&gt;the most frequently read file&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Rule: Enforce "Check Records Before Working" Structurally
&lt;/h3&gt;

&lt;p&gt;Even if the records exist, they're useless if the AI doesn't read them. Enforce it in two layers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;State in the rule file: "before modifying code, open the records &lt;strong&gt;directly with the Read tool&lt;/strong&gt;."&lt;/li&gt;
&lt;li&gt;Use a hook (Chapter 4) to technically block "modifying files without having read the records."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without ②, ① gets followed only intermittently. Especially as the session grows longer, rules&lt;br&gt;
get pushed to the back of the context.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. When Records Ruin Judgment (An Actual Incident)
&lt;/h3&gt;

&lt;p&gt;This is the most important part of this chapter. &lt;strong&gt;Records are an asset, but once contaminated,&lt;br&gt;
they become a liability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The incident&lt;/strong&gt;: logs produced by an automated inspection script were piling up in &lt;code&gt;mistakes.md&lt;/code&gt;,&lt;br&gt;
and the AI &lt;strong&gt;mistook those automated logs for current issues&lt;/strong&gt;, repeating the same wrong answer&lt;br&gt;
16 times. It kept seeing an already-resolved problem as "the problem right now."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cause&lt;/strong&gt;: &lt;code&gt;mistakes.md&lt;/code&gt; is a file that gets auto-injected every session. If automated logs&lt;br&gt;
get mixed in there, the AI's entire field of view is contaminated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix&lt;/strong&gt;: split the files &lt;strong&gt;by signal source&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Who writes it&lt;/th&gt;
&lt;th&gt;Injected?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mistakes.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Only what a human pointed out&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;diary.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Actual work by human and AI&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;audit-log.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Automated logs from scripts and cron&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And add one more filter to the injection hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_auto_noise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;AUTO_MARKERS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Making the filter &lt;strong&gt;explicit strings rather than regex&lt;/strong&gt; is deliberate. Cast the net too wide&lt;br&gt;
and human-written entries get filtered out too — narrowing the field of view in the opposite&lt;br&gt;
direction this time.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Another Form of Contamination — Encoding
&lt;/h3&gt;

&lt;p&gt;Record files must be written &lt;strong&gt;only through a path that guarantees UTF-8 (the AI's file tools)&lt;/strong&gt;.&lt;br&gt;
Writing via shell redirect (&lt;code&gt;echo ... &amp;gt;&amp;gt; diary.md&lt;/code&gt;) can corrupt the encoding on Windows, and&lt;br&gt;
if a corrupted record gets injected every session, you end up with &lt;strong&gt;an AI whose memory is damaged&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. When Should Records Be Written?
&lt;/h3&gt;

&lt;p&gt;If you define the "record this" instruction as a &lt;strong&gt;bundled procedure&lt;/strong&gt;, no step gets skipped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step ③ kept getting skipped, so it eventually became a hook. &lt;strong&gt;If a commit succeeds but the&lt;br&gt;
handover note wasn't updated today, a notification&lt;/strong&gt; appears (Chapter 4, pattern C).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>First Setup: What Changes with a Single CLAUDE.md</title>
      <dc:creator>Sungsoo Youn</dc:creator>
      <pubDate>Sat, 05 Sep 2026 04:10:03 +0000</pubDate>
      <link>https://dev.to/dbsoul/first-setup-what-changes-with-a-single-claudemd-2j6</link>
      <guid>https://dev.to/dbsoul/first-setup-what-changes-with-a-single-claudemd-2j6</guid>
      <description>&lt;p&gt;&lt;em&gt;This is chapter 2 of my book **Building Autonomous AI Agents with Claude Code&lt;/em&gt;* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*&lt;/p&gt;

&lt;h3&gt;
  
  
  1. CLAUDE.md Is a "Contract Read Every Time"
&lt;/h3&gt;

&lt;p&gt;Every time Claude Code starts a session, it injects the global settings (&lt;code&gt;~/.claude/CLAUDE.md&lt;/code&gt;) and the project's&lt;br&gt;
CLAUDE.md into the system context. In other words, every sentence written here is a &lt;strong&gt;standing instruction that&lt;br&gt;
automatically attaches to every conversation&lt;/strong&gt;. This property is both the strength and the trap.&lt;/p&gt;

&lt;p&gt;The strength is clear. You gain "things you no longer have to say every time."&lt;br&gt;
The trap is this: &lt;strong&gt;every sentence written here competes with every other one, every turn.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Shorter Gets Followed — A Fact Confirmed by Measurement
&lt;/h3&gt;

&lt;p&gt;There is a common failure path. Rules pile up one by one past 1,000 lines, and at some point the AI&lt;br&gt;
&lt;strong&gt;starts missing the most important rules.&lt;/strong&gt; Inside a long document, instructions bury each other.&lt;/p&gt;

&lt;p&gt;In actual operation, when we removed a general-purpose rule set that had grown past 1,300 lines and cut the injected volume by about 89%,&lt;br&gt;
compliance with the core rules went up noticeably. The attempt to raise compliance by adding&lt;br&gt;
&lt;strong&gt;more&lt;/strong&gt; rules had itself been the cause.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Keep only "things that cause real damage when violated" in CLAUDE.md, and move everything else out.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One counterintuitive case is worth adding. We once listed the "expressions not to use" in the rules —&lt;br&gt;
and then &lt;strong&gt;removed the list.&lt;/strong&gt; Showing those words every turn was actually producing an imprinting effect.&lt;br&gt;
The list now lives in a separate file, and a checker filters output just before it is sent.&lt;br&gt;
&lt;strong&gt;Writing something in the rules and blocking it with a system are different things.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Split into a Three-Layer Structure
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;th&gt;Size guideline&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Identity, tone, security, prohibitions common to all projects&lt;/td&gt;
&lt;td&gt;Under 100 lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rule fragments&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/rules/*.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rules by topic (encoding, paths, DB)&lt;/td&gt;
&lt;td&gt;Under 30 lines per file&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reason for splitting off rule fragments is &lt;strong&gt;to load them only when needed.&lt;/strong&gt; The DB rules only&lt;br&gt;
need to be present when you touch the DB. If they are always injected, they take up space that other rules need.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Three Traits of a Well-Written Rule
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;① It can be verified through behavior.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Be careful" cannot be verified. The AI cannot judge whether it was careful, either.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;② It carries a one-line reason.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the AI knows the reason, it &lt;strong&gt;keeps the intent even in situations the rule didn't anticipate.&lt;/strong&gt; A rule&lt;br&gt;
without a reason gets dismissed as "doesn't apply in this case" the moment the situation shifts slightly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;③ It states a replacement behavior, not just a prohibition.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With only a prohibition, the AI &lt;strong&gt;improvises a creative workaround&lt;/strong&gt; at the blocked spot. That workaround is&lt;br&gt;
usually worse.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. What Must Go into the Project CLAUDE.md
&lt;/h3&gt;

&lt;p&gt;The global file differs from person to person, but there are things every project file should share.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="sb"&gt;


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

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;"confirmed facts (do not ask again)"&lt;/strong&gt; section is surprisingly effective. If you have been asked the same&lt;br&gt;
question three times, write the answer here. Then there is no fourth time.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Signals When Rules Keep Growing
&lt;/h3&gt;

&lt;p&gt;If your rule file is growing, check the following.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Three or more rules on the same topic are scattered around&lt;/td&gt;
&lt;td&gt;Bundle them into a rule fragment file and move them out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A rule contains "as an exception"&lt;/td&gt;
&lt;td&gt;That rule is already wrong — rewrite its condition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A rule keeps being ignored&lt;/td&gt;
&lt;td&gt;Don't rewrite the sentence — &lt;strong&gt;turn it into a hook&lt;/strong&gt; (Chapter 4)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last row is the key. &lt;strong&gt;If saying it three times doesn't work, build it into the structure.&lt;/strong&gt; Rewriting a rule&lt;br&gt;
in a stronger tone almost never works.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want the whole system?&lt;/strong&gt; The book has 11 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not sure yet? The first three chapters are free, same PDF format: &lt;a href="https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample" rel="noopener noreferrer"&gt;https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
