<?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: pikuto1125-pixel</title>
    <description>The latest articles on DEV Community by pikuto1125-pixel (@pikuto1125pixel).</description>
    <link>https://dev.to/pikuto1125pixel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3927247%2F750e8e32-2f15-4fd3-bdcb-fcea8a0960ec.png</url>
      <title>DEV Community: pikuto1125-pixel</title>
      <link>https://dev.to/pikuto1125pixel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pikuto1125pixel"/>
    <language>en</language>
    <item>
      <title>Lessons from 9 months of solo AI automation: 10 patterns I'd give my past self</title>
      <dc:creator>pikuto1125-pixel</dc:creator>
      <pubDate>Tue, 12 May 2026 13:19:05 +0000</pubDate>
      <link>https://dev.to/pikuto1125pixel/lessons-from-9-months-of-solo-ai-automation-10-patterns-id-give-my-past-self-4j7n</link>
      <guid>https://dev.to/pikuto1125pixel/lessons-from-9-months-of-solo-ai-automation-10-patterns-id-give-my-past-self-4j7n</guid>
      <description>&lt;p&gt;canonical_url: &lt;a href="https://ai-hack-lab.com/insights/arena-blueprint-launch-eve/" rel="noopener noreferrer"&gt;https://ai-hack-lab.com/insights/arena-blueprint-launch-eve/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt; — I'm shipping &lt;em&gt;Arena Blueprint&lt;/em&gt; on May 13, 2026 (JST). I'm a new HN account, so my Show HN hit a submission limit and didn't reach the front page — figured I'd post the technical write-up here first instead. This is the post I wanted to read 9 months ago, before I burned a quarter on dead ends.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I'm a 20-year-old undergrad in Japan. Started writing code 9 months ago by talking to Claude Code.&lt;/li&gt;
&lt;li&gt;Built and ran an automation system in production: B2B proposal pipeline (Lancers/CrowdWorks), customer reply, content distribution, self-evolution loop.&lt;/li&gt;
&lt;li&gt;4 customer-facing failures along the way (duplicate sends, silent skips, dead schedulers, dedup race) — each became a transferable pattern.&lt;/li&gt;
&lt;li&gt;Packaged as a Notion blueprint + MIT-licensed Skills bundle on GitHub.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post is &lt;strong&gt;what I'd give my past self on day 1&lt;/strong&gt;. Free. Long. Code-included.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 10 patterns (one-line each)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;What it solves&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Inbox Pattern&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dedup sends without a database — file-based, atomic, crash-safe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10-layer Validator&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cheap regex first, LLM judge last — 10x cost reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Atomic State Writer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Race-free shared-state writes (rename trick)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Polling Watcher&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lock + dual triggers — daemons that don't quietly die&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Sender Pattern Audit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Static analysis as a CI gate, not a vibe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Generator + Validator Split&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mandatory post-check layer on every output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Reflection Loop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-collect failures → inject into next prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Devil's Advocate Council&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Institutionalized dissent before unrecoverable decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Time-to-Detect Log&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Measure how long until anomalies are noticed (and shrink it)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Predictions Registry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Force the agent to commit predictions you can verify later&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Below I dig into patterns 1 and 2 with code. The other 8 are in the Blueprint with their own failure logs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pattern 1: Inbox Pattern
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The failure that birthed it
&lt;/h3&gt;

&lt;p&gt;April 2026. The auto-send script for one client fired four times in a row. Same proposal. Same person. I noticed when the customer complained.&lt;/p&gt;

&lt;p&gt;The cause: my "dedup" was an in-memory &lt;code&gt;Set&lt;/code&gt; that reset every time the watcher restarted. The retry loop did exactly what it was told to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;Move the dedup state to disk. Append-only JSONL. Two ops:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// inbox.js — minimal core&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;INBOX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&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="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.state/inbox.jsonl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;hashKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parts&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;|&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;slice&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="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hashKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;INBOX&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;INBOX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;meta&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hashKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;INBOX&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;INBOX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;has&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hashKey&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The rule
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before any side-effect that touches a customer&lt;/strong&gt;, call &lt;code&gt;inbox.has(parts)&lt;/code&gt;. If true, exit. Otherwise call your sender, then &lt;code&gt;inbox.commit(parts)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;proposal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skip — already sent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendProposal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;proposal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lancers&lt;/span&gt;&lt;span class="dl"&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's it. No DB. No Redis. Append-only file you can also &lt;code&gt;cat&lt;/code&gt; to debug.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I learned
&lt;/h3&gt;

&lt;p&gt;The cheap version of dedup is a JSON file. Reach for the database when you've outgrown a JSONL file, not because you're afraid you'll outgrow one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pattern 2: 10-layer Validator
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The failure that birthed it
&lt;/h3&gt;

&lt;p&gt;I had a single Claude prompt asking "is this proposal text OK?" before each send. Around 80 sends per week. Cost: about $40/week just on validation. And it still let a typo-laden draft through because the model felt generous that day.&lt;/p&gt;

&lt;h3&gt;
  
  
  The structure
&lt;/h3&gt;

&lt;p&gt;Order layers by &lt;strong&gt;cost&lt;/strong&gt;. Cheap regex first, expensive judge last. If any layer rejects, stop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Layer 0:  Typography     — full-width / half-width consistency
Layer 1:  Mine fields    — banned phrases (legal, brand)
Layer 2:  Placeholders   — unfilled {{client_name}} etc.
Layer 3:  Duplicate send — calls inbox.has()
Layer 4:  Brand guard    — required disclosure strings
Layer 5:  Sanity         — length, link count, encoding
Layer 6:  Reflection     — known-failure patterns from past incidents
Layer 7:  Platform rules — site-specific limits (Lancers 20-char title, etc.)
Layer 8:  Secrets leak   — emails / phone / API key shapes
Layer 9:  Sender audit   — static analysis of the caller (CI-time, not runtime)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Layer 9 is the one I'd skip explaining if I had to pick one. It runs at code-merge: any new sender must &lt;code&gt;await inbox.has(...)&lt;/code&gt; before the side-effect. If it doesn't, the audit fails the build.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this beats "ask Claude"
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;9 of 10 problems are caught by cheap deterministic rules&lt;/li&gt;
&lt;li&gt;The Claude judge runs on ~10% of cases&lt;/li&gt;
&lt;li&gt;Validation cost went from $40/week to ~$4&lt;/li&gt;
&lt;li&gt;The rejection reasons are &lt;em&gt;legible&lt;/em&gt; — I can read "Layer 4: missing disclosure" and fix it, vs. "the model said no, somehow"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I learned
&lt;/h3&gt;

&lt;p&gt;Validators get worse when they're a vibe. They get better when each layer has one job and a name.&lt;/p&gt;




&lt;h2&gt;
  
  
  The pattern behind the patterns
&lt;/h2&gt;

&lt;p&gt;The thing I keep noticing: &lt;strong&gt;most "AI agent" failures are not AI failures&lt;/strong&gt;. They're plain systems failures with an AI in the loop. The four I shipped in production were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dedup race (Pattern 1)&lt;/li&gt;
&lt;li&gt;PowerShell encoding error swallowed by silent-skip (now Pattern 7's Reflection Loop catches the pattern signature)&lt;/li&gt;
&lt;li&gt;Schedulers dying for weeks without me noticing (Pattern 4's dual-trigger lock)&lt;/li&gt;
&lt;li&gt;Make.com Iterator output shape mismatch eating 30 minutes of my evening (Pattern 9's Time-to-Detect Log shrank this kind of incident from days to minutes)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of these needed a smarter model. They needed a file that remembers things, a layered check, and a watcher that doesn't trust itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's in the Blueprint, what's free
&lt;/h2&gt;

&lt;p&gt;The Blueprint (Notion) and the Skills Bundle (GitHub, MIT) are separate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skills Bundle on GitHub — free, MIT-licensed.&lt;/strong&gt; This is the implementation: ~12 skills covering all 10 patterns, ready to drop into a Claude Code session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blueprint on Notion — paid.&lt;/strong&gt; This is the writing: deep dives on each pattern, the 4 failure logs in full, the trade-offs I'd flag if you asked me in person.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both work independently. The Skills bundle is genuinely useful without the Blueprint. The Blueprint is genuinely useful without the Skills bundle — it's a manual, not a wrapper around the code.&lt;/p&gt;

&lt;p&gt;Three tiers: $39 Blueprint only, $99 Blueprint + Skills, $199 Blueprint + Skills + a 30-minute call where I look at your stack and tell you which 3 modules to start with.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I'm publishing this
&lt;/h2&gt;

&lt;p&gt;I'm 20, a junior in college in Japan, and I want to graduate having shipped a real thing instead of having a clean GPA. This is part of that. The rest is at &lt;a href="https://ai-hack-lab.com/products/arena-blueprint?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;ai-hack-lab.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If any of the patterns above are useful to you and you build something — please tell me. I'm pikuto on most places. I read every reply.&lt;/p&gt;




&lt;h2&gt;
  
  
  Appendix: The Show HN
&lt;/h2&gt;

&lt;p&gt;I posted this to Show HN on May 12: [link]. The comment thread there has a tighter version of the brief above, plus answers to a handful of stack and pricing questions.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>indiehackers</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
