<?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: Jeremy Longshore</title>
    <description>The latest articles on DEV Community by Jeremy Longshore (@jeremy_longshore).</description>
    <link>https://dev.to/jeremy_longshore</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%2F3842419%2Ff5d02b54-daf0-4520-9aef-118fbd0c24ac.jpeg</url>
      <title>DEV Community: Jeremy Longshore</title>
      <link>https://dev.to/jeremy_longshore</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeremy_longshore"/>
    <language>en</language>
    <item>
      <title>Every Fix Failed in the Shape of the Bug It Fixed</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Thu, 13 Aug 2026 11:30:14 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/every-fix-failed-in-the-shape-of-the-bug-it-fixed-28d6</link>
      <guid>https://dev.to/jeremy_longshore/every-fix-failed-in-the-shape-of-the-bug-it-fixed-28d6</guid>
      <description>&lt;p&gt;The restore drill was right to fail and wrong about why.&lt;/p&gt;

&lt;p&gt;It was newly added by &lt;code&gt;decision-log/050&lt;/code&gt;, and the first snapshot it touched came back bad. It aborted with the loudest explanation it had: the seal has locked us out. The seal was fine. From a sample of one, a brand new verifier reached for the scariest failure mode in its vocabulary and published it as a finding.&lt;/p&gt;

&lt;p&gt;That set the pattern for the whole day. Every fix I shipped after it failed in the shape of the bug it was fixing. A shorter timeout that more than tripled the timeouts. A correction that turned a right count into a wrong one. A verifier that manufactured the exact failure it existed to rule out. Each of those got repaired on its own terms, by measurement, not by architecture. What actually changed by the end of the day was where I was willing to put an invariant: not in a check sitting next to the thing, but in a schema that refuses to hold the false claim.&lt;/p&gt;

&lt;p&gt;Seven commits and roughly 860 insertions in the intent-os backup fabric between 02:00 and 04:00. Most of what follows is me correcting me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate that passed every one of them
&lt;/h2&gt;

&lt;p&gt;Off-estate snapshot custody had 43 retained snapshots. 17 of them could not be restored. The nightly health gate had passed every one of them.&lt;/p&gt;

&lt;p&gt;Two commands, same snapshot, opposite answers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# what the nightly gate ran, every night, and logged as "snapshot OK"&lt;/span&gt;
borg check &lt;span class="nt"&gt;--repository-only&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# -&amp;gt; exit 0&lt;/span&gt;

&lt;span class="c"&gt;# what a restore actually needs&lt;/span&gt;
borg list &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# -&amp;gt; exit 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;borg check --repository-only&lt;/code&gt; validates the contents of the segments it finds. It never verifies that the transaction id recorded in the index has a segment sitting behind it. A repo missing its newest segments is internally consistent and completely unrestorable, and the gate reads that as healthy.&lt;/p&gt;

&lt;p&gt;The second failure was an interlock that did not exist. Three scripts, three locks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vps-borg-pull.sh        -&amp;gt; flock A
devbox-replica-pull.sh  -&amp;gt; flock B
repo-snapshot.sh        -&amp;gt; flock C   (unrelated to either)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each one guarded against a second copy of itself and nothing else. So the snapshot job rsync'd a replica that a pull was actively rewriting, which is how you get a torn snapshot that opens cleanly enough to fool a content check.&lt;/p&gt;

&lt;p&gt;Per repo, measured: VPS 20 of 24 restorable, dev box 6 of 19 restorable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first fix would have skipped the leg entirely
&lt;/h2&gt;

&lt;p&gt;To stop the race I made the snapshot wait for the pull's lock:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exec &lt;/span&gt;7&amp;gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PULL_LOCK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; flock &lt;span class="nt"&gt;-w&lt;/span&gt; 1800 7&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log &lt;span class="s2"&gt;"pull in progress, giving up"&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;10
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thirty minutes. That number came from an "8 to 12 minute" pull figure that the same pull request had already corrected as wrong. Against measured reality, a snapshot job starting at 07:00 and giving up at 07:30 never gets the lock. Not sometimes. Any day.&lt;/p&gt;

&lt;p&gt;I had traded torn snapshots for no snapshots, which is the worse of the two, because a torn snapshot at least exists to be caught.&lt;/p&gt;

&lt;h2&gt;
  
  
  The correction that turned a right number into a wrong one
&lt;/h2&gt;

&lt;p&gt;The first measurement said 17 of 43 unrestorable. That was correct. A later three-predicate scan returned 14 dev-box REJECTs, I read REJECT as "unrestorable," and published 18 of 43 as a correction. Then I edited the in-script comment away from the right value to match the wrong one.&lt;/p&gt;

&lt;p&gt;The gate refuses on three grounds and only one of them is unreadability. Dev-box snapshot &lt;code&gt;2026-08-05T0704&lt;/code&gt; carries rsync transfer debris and opens perfectly well in borg. Two measures of similar magnitude, conflated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 total   borg-list UNREADABLE   has-debris
vps                 24                      4            4
devbox              19                     13           14

17 of 43 UNRESTORABLE   (the damage)
18 of 43 REFUSED        (by the new gate, strictly larger, correctly so)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Debris proves the source was not quiescent even when the repo still opens, so refusing more than 17 is the right behavior. It is just a different number with a different meaning, and I published it under the first one's name.&lt;/p&gt;

&lt;p&gt;The cleanup after that was a sweep of every "N of 43", "N of 19" and "all N" claim across &lt;code&gt;repo-snapshot.sh&lt;/code&gt;, &lt;code&gt;home-server-custody-check.sh&lt;/code&gt;, the home-server README, &lt;code&gt;000-docs/154&lt;/code&gt;, the index and the CHANGELOG. &lt;code&gt;pnpm check&lt;/code&gt; clean over 532 markdown files, shellcheck clean at warning level.&lt;/p&gt;

&lt;p&gt;The part that stings: the entire thesis of that pull request is that adjacent checks lie to each other. It shipped with a second source of truth sitting next to the code, disagreeing with the record.&lt;/p&gt;

&lt;h2&gt;
  
  
  The verifier that manufactured its own failure
&lt;/h2&gt;

&lt;p&gt;The same class of bug was still sitting in ACCEPTANCE 2 of &lt;code&gt;bootstrap-root-custody.sh&lt;/code&gt;, which is the worst possible place for it. That walk iterates snapshots newest-first looking for one that lists.&lt;/p&gt;

&lt;p&gt;Every snapshot in a root carries the same borg repo id. With one shared cache, the newest iteration poisons every later one with "Cache is newer than repository." Measured over the 8 newest snapshots:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHARED cache, newest-first   -&amp;gt;  1 listable,  7 failed
FRESH cache per call         -&amp;gt;  4 listable,  4 failed   &amp;lt;- the true state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Half the failures were the walk's own cache. Had it run out of listable candidates, the drill would have reported that no sealed snapshot could be listed, aborted the bootstrap, and blamed the seal. That is precisely the misdiagnosis this walk was rewritten to prevent, in the one test whose entire job is telling a seal problem apart from a torn snapshot.&lt;/p&gt;

&lt;p&gt;A verifier that manufactures the failure it is checking for is worse than no verifier, because its output looks like a finding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The measurement with no receipt
&lt;/h2&gt;

&lt;p&gt;The whole scheduling redesign rested on one number, and that number had no evidence file behind it. Evidence 00 was titled "pull duration vs the gap before the snapshot" and captured &lt;code&gt;tail -4&lt;/code&gt; of the log, so it showed nothing but short pulls. That is exactly how the original "8 to 12 minute" figure got made in the first place.&lt;/p&gt;

&lt;p&gt;Evidence 06 pairs every start with its finish across the full log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-08-06  06:47:01 -&amp;gt; 11:14:31   4h27m   snapshot ran mid-pull  -&amp;gt; torn
2026-08-07  06:47:01 -&amp;gt; 08:17:43   1h30m   snapshot ran mid-pull  -&amp;gt; torn
2026-08-08  06:47:01 -&amp;gt; FAILED        --   snapshot copied debris -&amp;gt; torn

dev box: 88 starts / 76 ok / 12 FAILED
VPS:    118 starts / 108 ok / 10 FAILED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pull duration runs from about 3 minutes to about 4.5 hours and grows with the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not the obvious fix
&lt;/h2&gt;

&lt;p&gt;Three decisions on this day went against the first thing that came to mind. The reasoning is worth more than the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Opportunistic retry, not a longer timeout.&lt;/strong&gt; The obvious repair for &lt;code&gt;flock -w 1800&lt;/code&gt; is &lt;code&gt;flock -w 5400&lt;/code&gt;. I did not do that, because a longer timeout is the same guess with a bigger number. A fixed start time plus a fixed timeout is unwinnable when the thing you are waiting on spans two orders of magnitude and grows. Any constant chosen today is a guess with an expiry date, and the 07:00 cron was exactly that guess, made when the repo was smaller. The lock is now non-blocking, a held lock returns 0 and skips, and the timer fires every 2 hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fresh cache per call, not walking oldest-first.&lt;/strong&gt; Oldest-first also dodges the poisoning, and it was tempting because it is a one-word change. It hides the hazard rather than removing it, and it tests the least interesting snapshots.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pairing start to finish, not quoting a log tail.&lt;/strong&gt; The tail is what lied twice already. It is biased toward whatever ran most recently, and the recent pulls happen to be fast. Pairing every start with its outcome makes the distribution visible instead of the last sample.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same shape, a different repo
&lt;/h2&gt;

&lt;p&gt;Afternoon, &lt;code&gt;scorecardecho.com&lt;/code&gt;, the MLB GUMBO poller. Yesterday's known-issues entry had it at 11,319 failed polls in 24 hours behind a green health check.&lt;/p&gt;

&lt;p&gt;I shipped a fix, then had to fix the fix. A timing-out poll was overlapping the next tick, so I cut the poll ceiling from 5000ms to 4000ms. The overlap was a real bug. Shortening the timeout was the wrong repair for it, and it regressed the failure mode it was meant to help. Production, steady state, cold start excluded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5000ms ceiling : ~0.75 timeouts/min   (1,080 in 24h)
4000ms ceiling : ~2.6  timeouts/min   (13 in 5 min)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Direct latency sampling of the real GUMBO call through the residential proxy explains it exactly: median 1.69s, p90 4.91s, max 7.49s, with 25% of samples over 4 seconds. I had set the ceiling below the p90 of the call I was calling. The ceiling is now 8s, with 0 of 20 samples over.&lt;/p&gt;

&lt;p&gt;Four compounding defects total. 8,002 stale-socket errors and 186 breaker trips a day, both now 0.&lt;/p&gt;

&lt;p&gt;What is not proven: the poller latches onto a game at first pitch, so everything above was verified in Pre-Game and by direct sampling. The first in-game window is the remaining proof. I nearly reported "0 failures in 5 minutes" as success when it was 0 polls, because the poller was idle. Two items stay open: &lt;code&gt;sportstalk_atl&lt;/code&gt; 403s, and a cold-start burst that trips the breaker once per deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  None of these corrections were self-generated
&lt;/h2&gt;

&lt;p&gt;This is the part a git log cannot show. I did not catch most of this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both MiniMax reviewer lanes flagged the superseded counts in the in-script comment.&lt;/li&gt;
&lt;li&gt;The MiniMax defect lane caught the &lt;code&gt;flock -w 1800&lt;/code&gt; bug, which was worse than the one being fixed.&lt;/li&gt;
&lt;li&gt;The adversarial lane did the arithmetic on a gap I had written down as 13 minutes: 06:47 to a 07:06 snapshot is 19.&lt;/li&gt;
&lt;li&gt;The defect lane pointed out that the load-bearing 4h27m measurement had no receipt.&lt;/li&gt;
&lt;li&gt;On the intent-os side, a round-2 adversarial review caught a miscount in the capability matrix, which reported five sourceless capabilities where there were six.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reviewers produce noise too, and pretending otherwise would be its own kind of lying. One review run flagged a torn-snapshot block that an earlier commit had already fixed. That part was stale, not a live defect. The line next to it was live. You still have to read every finding.&lt;/p&gt;

&lt;p&gt;The day ran on Claude Opus 5 for most of the work, with Claude Fable 5, Claude Opus 4.8 and Claude Sonnet 5 in smaller sessions, plus 57 subagent transcripts (one intent-os session spawned nine or more).&lt;/p&gt;

&lt;h2&gt;
  
  
  The turn: put the invariant in the schema
&lt;/h2&gt;

&lt;p&gt;The same day shipped three vertical slices in intent-os where the invariant does not live in a check next to the data. It lives in a versioned JSON Schema contract that will not validate a document making the false claim.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;deployment-state.v0&lt;/code&gt;&lt;/strong&gt; (#453). A failed deploy workflow paired with a non-failure repo state is a schema rejection. The choice on the record: schema-encoding the never-stale-green rule over renderer-only enforcement, because the proof's teeth then show that a doctored collector cannot even write the lie.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;health-projection.v0&lt;/code&gt;&lt;/strong&gt; (#458). A conditional rejects any document where a non-running container claims healthy. The alarm-to-service mapping is a stated heuristic carried in every projection's &lt;code&gt;provenance.mapping_basis&lt;/code&gt;, reported rather than silently assumed. The run proof statically asserts that no query-API path exists in the collector.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;estate-capability-matrix.v0&lt;/code&gt;&lt;/strong&gt; (#462). The D167 truth table as a slice, with 1 valid and 4 invalid fixtures. It composes the settled projections and collects nothing itself (statically asserted: no network or ssh in &lt;code&gt;compose.py&lt;/code&gt;). Health is capability health, never data greenness, and sourceless live rows render unknown loudly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each slice carries its seeded drill as a schema rejection, invalid fixtures, and a run proof. That is the structural answer to a day of adjacent checks lying to each other: the check can be blinded, the renderer can be doctored, the comment can drift, but the document either validates or it does not.&lt;/p&gt;

&lt;p&gt;I want to be careful about how far that claim reaches. Those three slices are clean execution and nothing in them broke. They are not vindicated yet. One approach is being tried against a problem the other approach kept losing to, and that is all today proves.&lt;/p&gt;

&lt;p&gt;The audit that closed the matrix slice is a fair warning about how much ceremony this costs. &lt;code&gt;mc-evidence-auditor&lt;/code&gt; refused it because the round that caught the five-versus-six miscount was missing from the "every round disposed" log, and the count fix had landed in the CHANGELOG but not in the pull request body or the bead note. A fix that lands in one copy of a claim while other copies keep the wrong number is the exact failure the audit exists to catch, and it was the second instance of that pattern in one day. Note where that one happened: in the prose describing the schema slice, not in the schema itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do differently
&lt;/h2&gt;

&lt;p&gt;Not "test more." Every one of these had a test. The gate ran nightly, the drill was purpose-built, the timeout was chosen from a measurement, the correction was made from a scan.&lt;/p&gt;

&lt;p&gt;The transferable rule is narrower: a check that sits next to the thing it checks shares its blind spots and its state. The nightly gate shared borg's idea of consistency. The drill shared a cache with the thing it was measuring. The in-script comment shared a file with the code and drifted from the record.&lt;/p&gt;

&lt;p&gt;The timeout belongs to a neighboring category worth naming separately, because it is the one I keep miscategorizing. It shared no state with anything. It inherited a number from a measurement the same change had already retracted, which is how a constant outlives the evidence that produced it.&lt;/p&gt;

&lt;p&gt;When the invariant moves into an artifact that has to validate independently, none of that sharing is available to it. The document either validates or it does not, and no adjacent comment gets a vote.&lt;/p&gt;

&lt;p&gt;That is not a claim that schemas are self-correcting. I did not catch most of the corrections above, a reviewer did, and the one drift that did land on the schema side landed in prose that a reviewer still had to read. A contract has to be written correctly by someone first. What it removes is the option of the code and the record quietly disagreeing about what is true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also shipped
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Extended the Carter gate to &lt;code&gt;/downloads/&lt;/code&gt; after it served a file anonymously, and corrected a stale username in the same config.&lt;/li&gt;
&lt;li&gt;Added a CLAUDE.md to partner-portals recording the same ingress trap that published an ungated file.&lt;/li&gt;
&lt;li&gt;Repaired the wrapped updater lane, which had never been able to run on either host.&lt;/li&gt;
&lt;li&gt;Repaired six stale claims found by an &lt;code&gt;/init&lt;/code&gt; audit, spanning hosted CI, the grown gate suite, and undocumented directories.&lt;/li&gt;
&lt;li&gt;Restored chronological order in a log after a rebase put an 08-09 entry above an 08-11 one.&lt;/li&gt;
&lt;li&gt;Forwarded &lt;code&gt;learn.&lt;/code&gt; access requests to the owner's inbox, because the Slack ping had been silently dead.&lt;/li&gt;
&lt;li&gt;diagnostic-pro backlog from 14 open to 5, after checking each one against reality rather than closing on vibes.&lt;/li&gt;
&lt;li&gt;claude-code-plugins untracked 42M of archived inventory snapshots while preserving five cited governance records that had never been tracked.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-drills-passed-reality-did-not/"&gt;The Drills Passed. Reality Did Not.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/nothing-read-it-so-nothing-failed/"&gt;Nothing Read It, So Nothing Failed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/a-dead-socket-is-not-a-dead-host/"&gt;A Dead Socket Is Not a Dead Host&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;{&lt;br&gt;
  "&lt;a class="mentioned-user" href="https://dev.to/context"&gt;@context&lt;/a&gt;": "&lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;",&lt;br&gt;
  "@type": "BlogPosting",&lt;br&gt;
  "headline": "Every Fix Failed in the Shape of the Bug It Fixed",&lt;br&gt;
  "description": "An invariant guarded by adjacent checks is only as honest as the checks. Seven commits of corrections, then it moved into a schema that refuses the claim.",&lt;br&gt;
  "author": { "@type": "Person", "name": "Jeremy Longshore" },&lt;br&gt;
  "publisher": { "@type": "Organization", "name": "Start AI Tools", "url": "&lt;a href="https://startaitools.com/" rel="noopener noreferrer"&gt;https://startaitools.com/&lt;/a&gt;" },&lt;br&gt;
  "datePublished": "2026-08-11T10:00:00-06:00",&lt;br&gt;
  "mainEntityOfPage": { "@type": "WebPage", "&lt;a class="mentioned-user" href="https://dev.to/id"&gt;@id&lt;/a&gt;": "&lt;a href="https://startaitools.com/posts/every-fix-failed-in-the-shape-of-the-bug/" rel="noopener noreferrer"&gt;https://startaitools.com/posts/every-fix-failed-in-the-shape-of-the-bug/&lt;/a&gt;" },&lt;br&gt;
  "url": "&lt;a href="https://startaitools.com/posts/every-fix-failed-in-the-shape-of-the-bug/" rel="noopener noreferrer"&gt;https://startaitools.com/posts/every-fix-failed-in-the-shape-of-the-bug/&lt;/a&gt;",&lt;br&gt;
  "articleSection": "Technical Deep-Dive",&lt;br&gt;
  "keywords": "borg check, borg list, torn snapshot, backup verification, flock, restore drill, JSON Schema contract, timeout tuning, devops, debugging"&lt;br&gt;
}&lt;/p&gt;

</description>
      <category>devops</category>
      <category>debugging</category>
      <category>architecture</category>
      <category>testing</category>
    </item>
    <item>
      <title>A Dead Socket Is Not a Dead Host</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Wed, 12 Aug 2026 10:27:05 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/a-dead-socket-is-not-a-dead-host-3ald</link>
      <guid>https://dev.to/jeremy_longshore/a-dead-socket-is-not-a-dead-host-3ald</guid>
      <description>&lt;h2&gt;
  
  
  The measurement
&lt;/h2&gt;

&lt;p&gt;Over 24 hours on the Braves production backend, the GUMBO poller failed 11,319 times. That is roughly 8 failures per minute, continuous, for a full day. It tripped the circuit breaker 186 times. The health endpoint reported &lt;code&gt;status: ok&lt;/code&gt; the entire time, so nothing reached a human and the uptime monitor stayed green.&lt;/p&gt;

&lt;p&gt;The poller runs every 5 seconds and requests timed out after 5 seconds. The three largest failure buckets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terminated, other side closed: 8,002&lt;/li&gt;
&lt;li&gt;Circuit-open, which is a consequence rather than a cause: 2,232&lt;/li&gt;
&lt;li&gt;Timeout: 1,080&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The defect was not a single thing. It was four things compounding, each one plausible in isolation, each one invisible when stacked. And the strangest part of the debugging was that the codebase had already diagnosed two of them: one in a comment predicting the exact race, one in a branch two lines from the bug making the exact distinction the bug failed to make. The answers were in the file. What follows is the order in which they turned up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defect 1: A socket is not a host
&lt;/h2&gt;

&lt;p&gt;Keep-alive connection pools race their peer by construction. You can pick a socket in the instant between the peer closing it and you noticing. When undici tries to reuse such a socket it reports &lt;code&gt;UND_ERR_SOCKET / "other side closed"&lt;/code&gt;. That means the socket is dead, not the host, and the next request on a fresh connection succeeds.&lt;/p&gt;

&lt;p&gt;Nothing retried. Worse, it counted toward the circuit breaker, and five stale sockets were enough to open the circuit for 60 seconds. So a benign race manufactured 2,232 additional real failures per day on top of the 8,002 it caused directly. Roughly a fifth of the day's failure count was the breaker reacting to a race that never needed to be a failure at all.&lt;/p&gt;

&lt;p&gt;The fix is narrow: retry once on a fresh connection, exclude the race from the breaker, and stop.&lt;/p&gt;

&lt;p&gt;The part worth sitting with is that the code already knew this distinction. The 4xx branch, two lines away, carries a comment saying "the host is up, the query is rejected". That is the same separation, already reasoned through, already written down. It was never extended one layer down to the socket. The category error was not an oversight in principle, it was an oversight in scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Excerpted from the poll error handler in http-client.ts, illustrative shape.&lt;/span&gt;

&lt;span class="c1"&gt;// Before: every socket death counted toward the breaker&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handlePollErrorBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PollError&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UND_ERR_SOCKET&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;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recordFailure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 8,002 times in 24h&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// After: a dead socket and a dead host are different facts&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handlePollError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PollError&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UND_ERR_SOCKET&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="c1"&gt;// The socket raced the peer. Try once on a fresh connection.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;retried&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;pollOnFreshConnection&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="nx"&gt;retried&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&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;retried&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Only a failure on a FRESH connection says anything about the host.&lt;/span&gt;
    &lt;span class="nx"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recordFailure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;is5xx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Upstream is struggling. Never retry these. Record and move on.&lt;/span&gt;
    &lt;span class="nx"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recordFailure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why not retry on timeout or 5xx? Because re-issuing those is exactly what produced the 2026-07-17 storm. A timeout and a 5xx both say the upstream is already struggling, and the correct response to a struggling upstream is fewer requests, not more. A stale socket says something different: nothing is wrong upstream, our own pool handed us a corpse. Only the third case earns a retry, so only the third case gets one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defect 2: The pool was tuned to maximize the race
&lt;/h2&gt;

&lt;p&gt;ProxyAgent was constructed with no options, so undici's default &lt;code&gt;keepAliveTimeout&lt;/code&gt; sat at 4 seconds, just under the 5-second poll interval. Every poll reused a socket that was idle right at the edge of expiry. We could have held sockets longer. Instead, we chose to close our side first.&lt;/p&gt;

&lt;p&gt;We set &lt;code&gt;keepAliveTimeout&lt;/code&gt; to 2 seconds, well below the poll interval. On paper that costs one CONNECT per poll. In practice the proxy log showed that CONNECT was already happening on nearly every poll, because the sockets were expiring anyway. So the tradeoff was cheap: we formalized a cost we were already paying, and in exchange correctness stopped depending on the peer's idle timeout, which we do not control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defect 3: The poll could overlap itself
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;setInterval&lt;/code&gt; does not wait for the previous tick to finish, and the request timeout was 5000ms against a 5000ms interval. Any slow poll ran concurrently with its successor: two in-flight requests to the same upstream, each making the other likelier to time out. The old code had already called this shot. A comment in the file warned about the request timeout becoming "a 5s timeout that races the next poll tick". It sat there, correct and unactioned, while the race it described ran 8 times a minute.&lt;/p&gt;

&lt;p&gt;We added a single-flight guard and dropped the timeout to 4000ms to give each poll headroom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// strictly below the 5000ms interval&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currentPoll&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GameState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pollWithSingleFlight&lt;/span&gt;&lt;span class="p"&gt;()&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="nx"&gt;currentPoll&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="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// a poll is already in flight; skip this tick&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="nx"&gt;currentPoll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchGameState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;POLL_TIMEOUT_MS&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;currentPoll&lt;/span&gt;&lt;span class="p"&gt;;&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;span class="nx"&gt;currentPoll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&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;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pollWithSingleFlight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A skipped tick costs nothing here. The next poll arrives in at most 5 seconds, and GUMBO state does not change meaningfully inside one interval. Two concurrent polls, each degrading the other, cost plenty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defect 4: Health could not report any of it
&lt;/h2&gt;

&lt;p&gt;The health endpoint exposed a single boolean: &lt;code&gt;isStuck&lt;/code&gt;, which only fires when &lt;code&gt;gameStatus === "In Progress"&lt;/code&gt;. Between games, the poller could fail every single poll and health would still report ok. The signal was so under-specified that it could not represent the truth even in principle.&lt;/p&gt;

&lt;p&gt;We rewired health to expose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;consecutivePollFailures&lt;/code&gt; (number)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lastPollError&lt;/code&gt; (string or null)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;healthy&lt;/code&gt; (boolean)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;status&lt;/code&gt; field now becomes &lt;code&gt;"degraded"&lt;/code&gt; after 3 consecutive failures (roughly 15 seconds of darkness) or when stuck. A stopped poller between games is idle, not unhealthy, so &lt;code&gt;status&lt;/code&gt; stays &lt;code&gt;"ok"&lt;/code&gt; when gameStatus is not "In Progress".&lt;/p&gt;

&lt;p&gt;Note what that last clause protects. A stopped poller is idle, not unhealthy. If the definition of degraded had been "the poller is not returning data", every night between games would page someone, and a monitor that cries wolf nightly gets muted inside a week. The enum has to distinguish not running from running badly, or the fix reintroduces the original problem from the other direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  The deploy contract changed, and that is the risky part
&lt;/h3&gt;

&lt;p&gt;This is the piece worth flagging before copying any of it. &lt;code&gt;deploy.yml&lt;/code&gt; runs a smoke validation of &lt;code&gt;.status == "ok"&lt;/code&gt; after each deploy, and until now that assertion was decorative. It passed over 11,319 failed polls, because &lt;code&gt;status&lt;/code&gt; was a constant. Making &lt;code&gt;status&lt;/code&gt; honest silently gave that smoke test teeth it never had.&lt;/p&gt;

&lt;p&gt;A deploy whose live feed cannot reach MLB will now fail smoke and roll back. That is intended, and it fails closed, which is the right direction: rollback restores the prior image. But it means a change to a health endpoint quietly altered deploy behavior, and an upstream outage at MLB can now block shipping unrelated frontend work. Off-hours deploys are unaffected, since an idle poller reports ok. I made that dependency on purpose and wrote it into the commit as a contract change, because the alternative was finding out during an incident that the smoke gate had grown a third-party dependency nobody chose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same error in four more costumes
&lt;/h2&gt;

&lt;p&gt;Defects 2 and 3 are ordinary tuning and concurrency bugs. They amplified the damage but they are not the interesting part. Defects 1 and 4 are, because neither is a monitoring gap. Nothing was missing. A value existed, it was being read, and it was under-specified: two genuinely different facts had been assigned the same representation, so the signal could not express the truth even in principle. Add another dashboard and you get the same wrong answer on a second screen.&lt;/p&gt;

&lt;p&gt;The rest of the day, over on intent-os, was the same mistake in other places.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observed zero is not failed observation.&lt;/strong&gt; B4.1 is a per-repo CI and release status projection over 145 active repos. The bead asked, literally, for a repo with no CI to render as &lt;code&gt;unknown&lt;/code&gt;. That is wrong, and shipping it as written would have poisoned the page. "I asked GitHub and it has run zero workflows" is a positive observation. "I asked GitHub and the call failed" is the absence of an observation. Both mean never green, which is the requirement's real substance, but they are not the same fact. The closed enum keeps &lt;code&gt;none&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt; apart, and &lt;code&gt;unknown&lt;/code&gt; always carries a reason. The live sweep came back 63/17/1/62/2: seventeen genuinely red repos rendering red, two genuinely unobservable ones rendering unknown with a reason attached.&lt;/p&gt;

&lt;p&gt;The shape it produces is small. The enforcement lives in the &lt;code&gt;ci-release-status.v0&lt;/code&gt; contract (a closed verdict enum, with &lt;code&gt;reason&lt;/code&gt; required on &lt;code&gt;unknown&lt;/code&gt;), and the point of it is that "we do not know" can never be written down as cheaply as "there is nothing here":&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;"repo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"intent-solutions-io/intent-os"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ci"&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;"verdict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"passing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"observed_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-08-10T05:40:12Z"&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;"//"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no CI runs exist. positively observed. never green, but not a failure to look."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ci_none_example"&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;"verdict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"observed_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-08-10T05:40:12Z"&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;"//2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the observation itself failed. a reason is structurally required here."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ci_unknown_example"&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;"verdict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gh api timeout after 20s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"observed_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-08-10T05:40:12Z"&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;p&gt;That &lt;code&gt;observed_at&lt;/code&gt; is per class, not per document. Registry fields carry the registry's clock and the CI fields carry their own, because a fresh registry read tells you nothing about how stale the CI observation beside it is. Anything older than 48 hours is flagged loudly.&lt;/p&gt;

&lt;p&gt;The renderer also refuses to emit a projection whose counts disagree with its own rows, so a doctored summary cannot quietly hide a red repo. A projection is never a source of truth, and the fastest way to forget that is to let it round off its own inconsistencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A matching name is not a shared identity.&lt;/strong&gt; B4.2 joins the repo registry against the service inventory to produce blast-radius edges. The join is a name-match heuristic, and the entire design question is what to do with that fact. The answer was to report it rather than launder it: exact case-insensitive match only, ambiguity excluded and listed rather than resolved by guess, gaps counted on both sides, no fabricated identity written anywhere. First live run produced 26 edges, 68 bindings, and 5 real orphans (the vendored twenty stack). The orphan class had production examples on day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A schema-valid document does not prove its endpoints exist.&lt;/strong&gt; This was the sharp finding out of four on that PR, and it is the one worth stealing. Every edge validated against &lt;code&gt;catalog-relationship.v0&lt;/code&gt;. Every edge was also potentially pointing at nothing, because schema conformance says a field is well-formed, not that the thing it names is real. A slug-convention divergence between producer and catalog would have made the entire blast radius fictional, and no amount of schema validation could have noticed. The proof now asserts that every live edge endpoint actually resolves in the materialized catalog, same inventory, same run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A recorded rehearsal is not a re-executable one.&lt;/strong&gt; The settlement audit on B4.1 pulled the rollback receipt out of the shipped evidence bundle and found its caption mislabeled the executed command and cited the wrong base commit. Re-run as written, it did not work. The underlying claim was true, the rollback genuinely worked, and the artifact still failed to prove it. That is the category error applied to evidence itself: "I did this" and "here is something you can run to confirm I did this" had been collapsed into one document. It was regenerated verbatim against the real parent commit, captured output and all.&lt;/p&gt;

&lt;p&gt;Every fix is the same move. Find the two facts sharing one value, name them separately, and make the system structurally incapable of rendering them as one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The collaboration beat
&lt;/h2&gt;

&lt;p&gt;The intent-os work spanned three sessions, 178 turns, 560 tool calls, and 1003 minutes across Claude Fable 5 and Claude Opus 5. It opened with &lt;code&gt;/init&lt;/code&gt; on an already-strong CLAUDE.md. Instead of rewriting, the model did a drift-repair audit. It checked every checkable claim and fixed six false ones. The most dangerous was a CI section still claiming a self-hosted dev-box runner when all four GitHub Actions jobs had run on ubuntu-latest since 2026-07-27. An agent following that text would reason about runner serialization and systemctl commands that no longer exist.&lt;/p&gt;

&lt;p&gt;Then came a blunt voice-dictated steer, mid-session. The command was rough (voice-to-text had roughed it up), the instruction was not: finish the B3 synchronization spine before touching B4. Non-negotiable architecture: reconciliation is truth. Events are acceleration signals. A dropped, duplicated, delayed, or reordered event must never permanently make Mission Control wrong.&lt;/p&gt;

&lt;p&gt;The model entered plan mode, dispatched three Explore agents and one Plan agent, wrote the plan, then executed it. The 26 errors along the way included Exit code 8, Exit code 128, a Traceback, a failed string replacement, and a harness block on a 45-second sleep (the instruction was to use Monitor with an until-loop instead). Each one was recovered in place.&lt;/p&gt;

&lt;p&gt;On the Braves side, the useful moment was two poller tests going red after the single-flight guard landed. The tests were wrong, not the code. In &lt;code&gt;gumbo-poller.ts&lt;/code&gt;, the poller's &lt;code&gt;start()&lt;/code&gt; fires an unawaited poll immediately, so the hand-driven polls those tests injected were correctly skipped by the new guard. That is the failure mode you want from a guard, arriving disguised as a regression. The tests gained a &lt;code&gt;drain()&lt;/code&gt; helper that waits for the in-flight poll before asserting, and went green.&lt;/p&gt;

&lt;p&gt;The last check was the one easiest to skip. ProxyAgent's object form was verified live, constructed for real with a request through the home-server proxy returning 200, rather than trusted because &lt;code&gt;tsc&lt;/code&gt; was clean. Typechecking proves a shape, not a behavior, which is the same distinction this entire post is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also shipped
&lt;/h2&gt;

&lt;p&gt;Verified: 359 tests pass across 58 files. No TypeScript or ESLint errors. Refs #114, #115, #116, #118.&lt;/p&gt;

&lt;p&gt;On intent-os: B3.5 (conflict/drift queue) and B3.6 (replay/dedup/missed-event recovery proof with drills for missing/delayed/reordered events) shipped the same day. Also: a fix for treating malformed prior snapshot as absent. A corrupted state file must never become a daily-sweep denial-of-service.&lt;/p&gt;

&lt;p&gt;17 beads closed 2026-08-10. Notable: the estate-graph projection fallback was claiming verified health without ever querying the database, which is this post's thesis restated as a bug title. The Kilo review bot had been dead on every intent-os PR for 10 snapshots (its configured model no longer exists). The github_pat_intentsolutions_vps token in production SOPS returned 401 Bad credentials. An ungated download shipped to the partner portal because Caddy's PATH allow-list had not been updated for the new prefix. Each one a gap between "we checked this" and "this is actually true".&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/the-check-that-only-confirmed-a-name/"&gt;The Check That Only Confirmed a Name&lt;/a&gt;. A gate that validated the label instead of the thing behind it. The F2 finding here is the same shape.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/nothing-read-it-so-nothing-failed/"&gt;Nothing Read It, So Nothing Failed&lt;/a&gt;. What it costs when absence and success are indistinguishable to the consumer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/the-ghost-in-the-catalog/"&gt;The Ghost in the Catalog&lt;/a&gt;. A record asserting work that never happened, then read downstream as truth. The same collapse, applied to provenance.&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "&lt;a class="mentioned-user" href="https://dev.to/context"&gt;@context&lt;/a&gt;": "&lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;",&lt;br&gt;
  "@type": "BlogPosting",&lt;br&gt;
  "headline": "A Dead Socket Is Not a Dead Host",&lt;br&gt;
  "datePublished": "2026-08-10T08:00:00-05:00",&lt;br&gt;
  "author": {&lt;br&gt;
    "@type": "Person",&lt;br&gt;
    "name": "Jeremy Longshore"&lt;br&gt;
  },&lt;br&gt;
  "url": "&lt;a href="https://startaitools.com/posts/a-dead-socket-is-not-a-dead-host/" rel="noopener noreferrer"&gt;https://startaitools.com/posts/a-dead-socket-is-not-a-dead-host/&lt;/a&gt;"&lt;br&gt;
}&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>debugging</category>
      <category>cicd</category>
      <category>releaseengineering</category>
    </item>
    <item>
      <title>The Agent's Mistakes Were the Fast Ones</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Tue, 11 Aug 2026 10:24:19 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/the-agents-mistakes-were-the-fast-ones-1dfe</link>
      <guid>https://dev.to/jeremy_longshore/the-agents-mistakes-were-the-fast-ones-1dfe</guid>
      <description>&lt;p&gt;Intent Solutions runs a chat relay it owns. The software is Buzz, and the property we are building&lt;br&gt;
toward is that humans and AI agents are co-members of the same room, each holding their own key,&lt;br&gt;
every message landing on an audit trail that belongs to us instead of to a vendor. Owning the&lt;br&gt;
record is the entire reason the project exists.&lt;/p&gt;

&lt;p&gt;We adopted it knowing exactly what it is. Upstream says out loud that this is preview software. The&lt;br&gt;
bundled object store is labeled evaluation-only. Rate limiting is defined in configuration and not&lt;br&gt;
enforced in code. Several workflow features are stubs. That honesty is what makes adoption a scoped&lt;br&gt;
hardening job rather than an act of faith. When a project tells you where its edges are, you can put&lt;br&gt;
your own gates at those edges instead of discovering them in production.&lt;/p&gt;

&lt;p&gt;The team it is for is a founding group of a few dozen people who currently live in a consumer group&lt;br&gt;
chat. The migration is not done. A handful of identities are on the relay so far, and the all-in&lt;br&gt;
onboarding is still open work. I am saying that here rather than saving it for a tidy ending,&lt;br&gt;
because everything below is substrate work for a room most of the team has not walked into yet.&lt;/p&gt;

&lt;p&gt;The part that actually matters, and the reason for all of it: agents as members rather than&lt;br&gt;
integrations. Not a bot posting into a channel through someone else's API token. A member with a&lt;br&gt;
key.&lt;/p&gt;

&lt;p&gt;Over about two weeks, agents doing that substrate work broke things. Six times, specifically. I&lt;br&gt;
logged all six. Then I went back through them looking for a pattern in the agents, and found a&lt;br&gt;
different pattern instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The agent's mistakes were the fast ones. Mine were slow, invisible, and upstream of nearly every&lt;br&gt;
one of them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Five of the six trace back to a decision I made to write a rule down and call it done. The agent&lt;br&gt;
violated a contract that lived in prose. It reported green from a probe that authenticated as the&lt;br&gt;
wrong identity, because nobody had ever made it prove otherwise. It built machinery the contract&lt;br&gt;
said was unnecessary, because the contract was not in front of it. The sixth is an arithmetic slip&lt;br&gt;
in an audit, and I am not going to stretch it into an indictment of me to make the pattern come out&lt;br&gt;
clean. Five is the number, and five is enough.&lt;/p&gt;

&lt;p&gt;Those are real failures and they stay on the record below. But an agent that breaks a rule nothing&lt;br&gt;
enforces is not the interesting story. The interesting story is that I wrote the rule, felt&lt;br&gt;
finished, and did not notice for weeks that nothing was checking it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the agent messed up
&lt;/h2&gt;

&lt;p&gt;An agent solved a real bug, and solved it well. Invited members were not being joined to the&lt;br&gt;
canonical general channel. The fix was CI-proven, reviewer-hardened, and reproduction-tested. Then&lt;br&gt;
it landed on our fork's main branch instead of going upstream through the contribution lane, and it&lt;br&gt;
dragged fourteen upstream-owned paths along with it: two files of relay source, six of desktop&lt;br&gt;
source, all four of upstream's own CI workflows, and both dependency lockfiles. The code was good.&lt;br&gt;
The lane was wrong.&lt;br&gt;
It came out as a single revert, no history rewrite, which is the one mercy of catching it before&lt;br&gt;
anything built on top of it.&lt;/p&gt;

&lt;p&gt;The same working session built our own relay images, then went and fought a container registry&lt;br&gt;
credential wall to push them. The fork contract says we deploy upstream's published images and&lt;br&gt;
carry zero patches of our own. None of that apparatus was needed at all. Nobody had to debug it,&lt;br&gt;
because it should never have existed. Work done well against a requirement that does not exist is&lt;br&gt;
still work that gets thrown away.&lt;/p&gt;

&lt;p&gt;The audit written about the branch breach documented, correctly, that two lists disagreed: the&lt;br&gt;
enforcement script's allowlist was missing two hash-pin files that the fork contract's must-survive&lt;br&gt;
table names. In the same document, it reported the must-survive check passing at ten of ten,&lt;br&gt;
against a table that names twelve paths. An audit about a counting problem that miscounted the&lt;br&gt;
count.&lt;/p&gt;

&lt;p&gt;A functional membership probe reported green while authenticating as the relay owner. The owner is&lt;br&gt;
the most privileged identity on the system and is always allowed. The probe proved that the door&lt;br&gt;
opens for the person who owns the door. It was rewritten to authenticate as a throwaway member&lt;br&gt;
identity, publish a message, read that message back, and clean up after itself, with a separate&lt;br&gt;
assertion that an un-invited key gets refused.&lt;/p&gt;

&lt;p&gt;Nine sessions running in parallel on one machine, sharing nothing but a filesystem. One of them&lt;br&gt;
retired a shared library that another was still calling. The failure surfaced as an ordinary&lt;br&gt;
missing file, which is the worst possible disguise a coordination problem can wear, because you&lt;br&gt;
will spend your first ten minutes looking for a typo.&lt;/p&gt;

&lt;p&gt;An agent wrote into the canonical naming record that upstream had independently fixed one half of a&lt;br&gt;
problem we were tracking. The upstream fix was open, not merged. Because that document is the&lt;br&gt;
canonical record, every document that defers to it inherited the overstatement. One overclaim in&lt;br&gt;
the right file propagates for free, and nothing downstream has any way to notice, because deferring&lt;br&gt;
to the canonical record is the correct behavior. The document was doing its job. It was just wrong.&lt;/p&gt;

&lt;p&gt;None of those six took long to fix once seen. The revert was one command. The probe rewrite was an&lt;br&gt;
afternoon. The miscount was a text edit. Speed of repair is not the measure that matters here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I messed up
&lt;/h2&gt;

&lt;p&gt;I wrote the fork contract in prose and enforced it with a local pre-push hook, then trusted it. An&lt;br&gt;
agent working through tooling that pushes without that hook, or working from a fresh clone, never&lt;br&gt;
runs it. The repository's required checks were upstream's own, and upstream's checks know nothing&lt;br&gt;
about our contract. The rule existed. The enforcement did not. In one line: the contract lived in&lt;br&gt;
prose and a local hook, not in a required check. Every minute the agent spent on the wrong branch&lt;br&gt;
was a minute I had already paid for weeks earlier.&lt;/p&gt;

&lt;p&gt;The difference between a rule and a gate is who has to remember. A rule delegates the remembering&lt;br&gt;
to whoever shows up next, and a fresh clone remembers nothing. A gate remembers on their behalf and&lt;br&gt;
does not get tired. I knew that. I have said it about deploy pipelines for years. I did not apply&lt;br&gt;
it to the one contract I cared most about, because I was the one who wrote it, and writing it felt&lt;br&gt;
like the work.&lt;/p&gt;

&lt;p&gt;The nine parallel sessions were my decision too. An agent does not choose to be one of nine. I&lt;br&gt;
fanned that wide because it is faster, and the coordination mechanism I gave them for the one&lt;br&gt;
surface they share is a journal file each session is asked to append to, plus a convention that&lt;br&gt;
says commit early or work in an isolated tree. Both of those are rules. Neither is a gate. A&lt;br&gt;
session that never read the convention is indistinguishable from one that read it and was in a&lt;br&gt;
hurry, and the retired library proves which one I actually shipped: that refactor was complete and&lt;br&gt;
correct and was never committed, so the next session found a tree missing a file and a guard that&lt;br&gt;
refused to run on a dirty one. I have the exact diagnosis written down one paragraph up, and I did&lt;br&gt;
not apply it to the surface I was running nine things on.&lt;/p&gt;

&lt;p&gt;I put two repository names into the canonical record for repositories that were never created. One&lt;br&gt;
of them got the same string as a real production host. When that collision started causing&lt;br&gt;
confusion, I wrote a rule saying that a bare use of the name is a defect to fix on sight. Read that&lt;br&gt;
again. A name that needs a footnote every time it appears is itself the defect. Killing the phantom&lt;br&gt;
removed the collision at the source, so the rule got deleted rather than policed, and deleting it&lt;br&gt;
cost nothing and broke nothing. That is the tell. I had built a permanent maintenance burden, and&lt;br&gt;
enforced it on every mention for weeks, to manage a problem whose entire existence was a line I&lt;br&gt;
wrote.&lt;/p&gt;

&lt;p&gt;I wrote the documentation for myself, so nothing ever executed it. There is one reader and the&lt;br&gt;
reader is the author, which means the runbook and my head agree, and the agreement is never tested.&lt;br&gt;
Wrong documentation can sit there indefinitely at zero cost, because the only person consuming it&lt;br&gt;
already knows the answer. Handing it to a new lead priced it immediately. The access list grew from&lt;br&gt;
six grants to nine while it was still being written. Two grants that looked exactly like access&lt;br&gt;
were not access at all: one invitation could never be delivered, because the mail path was never&lt;br&gt;
configured, and one was a data row with no invitation behind it. A ghost that looks like a grant.&lt;/p&gt;

&lt;p&gt;Key custody was never decided, only deferred. Five separate open items were each waiting on the&lt;br&gt;
same missing choice, and the inventory that would have surfaced that was itself open and had never&lt;br&gt;
been run. The forcing function was a handover, not an audit. I was about to hand someone a&lt;br&gt;
production system whose master decryption key existed in exactly one place on one disk, with no&lt;br&gt;
export, and only then did the deferral start to look like a decision I had actually made. Two&lt;br&gt;
things the audit had not caught: the backup repository's key was stored inside the repository it&lt;br&gt;
protects, and its passphrase was a single-copy file on that same host. Escrowing the key alone&lt;br&gt;
would have closed a high-priority item while leaving the actual failure completely intact. That is&lt;br&gt;
the worst outcome available, because it retires the ticket that would have made someone look again.&lt;/p&gt;

&lt;p&gt;I shipped a coverage manifest whose vocabulary could not express "someone looked and there is&lt;br&gt;
none." It could say nobody has looked. It could say protected. It had no word for a confirmed&lt;br&gt;
absence. So the production system with no off-site copy at all was simply left out of the list, and&lt;br&gt;
a sixteen-row manifest read as complete. An absence you can name is an absence you can page on. An&lt;br&gt;
absence you cannot name is indistinguishable from a thing nobody has checked yet, which is to say&lt;br&gt;
it is invisible in exactly the way that matters.&lt;/p&gt;

&lt;p&gt;I never watched a control fail on purpose, so I did not know whether I had one. A document asserted&lt;br&gt;
that a compromise of one machine could not reach the backup history. Both facts it cited were true.&lt;br&gt;
No authorized keys were installed. No SSH daemon was listening on the standard port. Neither of&lt;br&gt;
those was the actual access path, which ran through a different mechanism nobody had enumerated.&lt;br&gt;
It was reasoning from the wrong evidence, which is harder to catch than a lie, because every&lt;br&gt;
individual sentence in it survives review. An isolation claim justified by the absence of one&lt;br&gt;
mechanism is worthless unless every other mechanism has been enumerated. The acceptance test now is&lt;br&gt;
a delete that has to fail. I wrote that claim and then never once tried to falsify it, and for as&lt;br&gt;
long as it stood unfalsified it was not a claim at all. It was a preference with a paragraph built&lt;br&gt;
around it.&lt;/p&gt;

&lt;p&gt;Those seven did not get fixed in an afternoon. Two of them needed a personnel handover and a first&lt;br&gt;
login to a machine nobody had logged into, before anyone looked at all. Every one of them had been&lt;br&gt;
sitting in a file I wrote, in language I still agree with, the whole time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we accomplished
&lt;/h2&gt;

&lt;p&gt;Bounded, and all of it verified rather than asserted, which is the only reason it is worth listing&lt;br&gt;
after everything above.&lt;/p&gt;

&lt;p&gt;A relay we own, closed from first boot, on a dedicated host with its own ingress. A fast-moving&lt;br&gt;
pre-release stack does not share a kernel, a disk, or a memory ceiling with the workloads that pay&lt;br&gt;
the bills.&lt;/p&gt;

&lt;p&gt;Proof that it says no, not just proof that it is running. An un-invited key gets refused over HTTPS&lt;br&gt;
from off the network, plus six classes of unauthenticated request that all have to be rejected and&lt;br&gt;
all six are.&lt;/p&gt;

&lt;p&gt;Backups that restore. A named recovery point restored onto a different machine, with the exact&lt;br&gt;
production message physically present, membership intact, and the door still shut afterward.&lt;br&gt;
Recovery time of about three minutes, measured rather than estimated. A proven restore is not a&lt;br&gt;
second copy, which is the distinction the last section is about.&lt;/p&gt;

&lt;p&gt;Key custody written down as a register: live copy, escrowed copy, and the command that proves each&lt;br&gt;
one works. Proven by destroying a key inside a copy of the repository and recovering it from the&lt;br&gt;
escrow alone.&lt;/p&gt;

&lt;p&gt;Contract violations now fail at the gate instead of in review. The fork gates are a required check,&lt;br&gt;
and a deliberate canary that touches an upstream path goes red.&lt;/p&gt;

&lt;p&gt;The estate's own alerting moved onto the relay, so the system posts into the room the team will&lt;br&gt;
live in rather than into a mailbox nobody opens on a Saturday.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are trying to accomplish
&lt;/h2&gt;

&lt;p&gt;The goal is a surface where the agents doing the work are members rather than integrations. They&lt;br&gt;
hold their own keys. They post under their own identity. Their output is reviewable in the same&lt;br&gt;
room, by the same people it affects, at the time it happens. And the company owns the record&lt;br&gt;
instead of renting it. That is a different thing from a chat app with a bot in it, and the&lt;br&gt;
difference is exactly the substrate work above.&lt;/p&gt;

&lt;p&gt;The distance still to travel, stated plainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The team is not moved yet. A handful of identities on the relay is not a migration.&lt;/li&gt;
&lt;li&gt;Production still holds one copy of its data. The key is escrowed and restore-proven. The off-site
copy of the data itself does not exist.&lt;/li&gt;
&lt;li&gt;The most privileged human identity in the system lives on the least backed-up, least monitored
machine in the estate.&lt;/li&gt;
&lt;li&gt;The automatic updater is installed and deliberately not armed, because arming it means unattended
weekly deploys of pre-release software onto a live event store.&lt;/li&gt;
&lt;li&gt;One encryption recipient that can decrypt every production secret is documented nowhere. It is
recorded as an open question rather than removed, because a wrong removal locks out whatever
depends on it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The mistakes I could see got fixed the same week. The ones that cost the most were rules I had&lt;br&gt;
already written down, and having written them down is precisely what made them invisible. A rule on&lt;br&gt;
paper feels finished, and a finished thing does not get looked at again. Nothing in this estate was&lt;br&gt;
watching any of them, and I was the only person in a position to notice that, which is the part&lt;br&gt;
that took two weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/onboarding-one-person-audited-the-whole-estate/"&gt;Onboarding One Person Audited the Whole Estate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/three-copies-of-the-key-none-of-the-passphrase/"&gt;Three Copies of the Key, None of the Passphrase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-check-that-only-confirmed-a-name/"&gt;The Check That Only Confirmed a Name&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aiagents</category>
      <category>devops</category>
      <category>architecture</category>
      <category>automation</category>
    </item>
    <item>
      <title>Three Copies of the Key, None of the Passphrase</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Mon, 10 Aug 2026 11:30:13 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/three-copies-of-the-key-none-of-the-passphrase-4a5g</link>
      <guid>https://dev.to/jeremy_longshore/three-copies-of-the-key-none-of-the-passphrase-4a5g</guid>
      <description>&lt;p&gt;A new lead is taking over Buzz management. That is the whole reason this work happened, and it is worth being precise about why, because it is not an audit finding.&lt;/p&gt;

&lt;p&gt;You do not hand someone a production system whose master decryption key exists in exactly one place, on one disk, with no export. Before the handover, a key loss is a bad day for the person who built the thing and knows where every copy is. After the handover, the same event is unrecoverable, because the new owner has no context to recover from. Responsibility moving is what converts a deferred decision into a live one.&lt;/p&gt;

&lt;p&gt;Five items were already open on this. Three P0 beads (&lt;code&gt;spine-3fy&lt;/code&gt;, &lt;code&gt;spine-9yg&lt;/code&gt;, &lt;code&gt;spine-u1a.2.3&lt;/code&gt;), one P1 (&lt;code&gt;spine-u1a.12.4&lt;/code&gt;), and a set of home-server passphrases nobody had documented at all. Every one of them was blocked on the same missing choice: what is custody. The bead that would have surfaced this, &lt;code&gt;spine-u1a.12.1&lt;/code&gt;, the secret inventory, is still open and was never run. So the audit did not find this. A personnel change did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does replicating a borg repokey repository survive host loss?
&lt;/h2&gt;

&lt;p&gt;No. With &lt;code&gt;repokey&lt;/code&gt; encryption the key blob lives in the repository config, so replication carries the key to every copy. The repository passphrase does not travel with it, and &lt;code&gt;borg key export&lt;/code&gt; output is itself passphrase-encrypted. Replicate the data without the passphrase and you hold three unopenable copies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the failure
&lt;/h2&gt;

&lt;p&gt;The scoping document, &lt;code&gt;000-docs/151&lt;/code&gt;, said the P0 was about the borg &lt;strong&gt;key&lt;/strong&gt;. Export the repokey, escrow it, close the bead.&lt;/p&gt;

&lt;p&gt;That would have closed a P0 while leaving the failure completely intact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;buzz repo encryption:  repokey
  -&amp;gt; the key blob lives INSIDE the repository config
  -&amp;gt; `borg key export` produces a file that is ITSELF
     encrypted with the repository passphrase
  -&amp;gt; that passphrase: one 600-mode file, on the same host,
     no second copy anywhere

escrow the key alone  =&amp;gt;  an escrowed artifact nobody can open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worse than that. The passphrase file on the host turned out to be a &lt;strong&gt;different value&lt;/strong&gt; from the &lt;code&gt;borg_passphrase&lt;/code&gt; already sitting in &lt;code&gt;secrets.prod.sops.yaml&lt;/code&gt;. Verified by sha256 comparison, no values exposed. So there were two single points of failure on one disk, and the one that was already escrowed was the wrong one.&lt;/p&gt;

&lt;p&gt;That is the local finding. The estate finding is the reason this post exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  The redundancy is what hid it
&lt;/h2&gt;

&lt;p&gt;Executing the fix meant building a register, &lt;code&gt;ops/host/secrets/KEY-CUSTODY.md&lt;/code&gt;: 13 key classes, each row carrying its live copy, its escrowed copy, and the command that proves the escrowed copy works. References only, never values. Writing that register surfaced three things no document in the estate held.&lt;/p&gt;

&lt;p&gt;The first one is the thesis.&lt;/p&gt;

&lt;p&gt;The dev box (&lt;code&gt;team-server&lt;/code&gt;) runs its own borg repo. Also &lt;code&gt;repokey&lt;/code&gt;. 1.93 TB of source data deduplicated down to 84 GB of archives, replicated to the VPS and from the VPS onward to the home server. Three copies, three machines, two physical locations.&lt;/p&gt;

&lt;p&gt;Every one of those three copies carries the encryption key, because &lt;code&gt;repokey&lt;/code&gt; puts the key in the repo and replication copies the repo. The passphrase did not ride along. It was a single 600-mode file on the dev box, and as far as any document in the estate was concerned, that was the only copy in existence.&lt;/p&gt;

&lt;p&gt;Lose the dev box and you are holding three undecryptable copies of everything. The replication is exactly what made that look solved. A coverage table, a backup dashboard, a mental model of the estate, all of them read "backed up three ways", and all three were right about the bytes and wrong about the access. The insurance policy and the thing it insures failed together, because the value that opens the data was the one value that never got copied with it.&lt;/p&gt;

&lt;p&gt;That turned out to be almost true rather than exactly true, and the exception is worth holding until the end of this post. Building the register found a copy of the dev-box passphrase in a place no document named. Which does not rescue the point. An undocumented file, on the least-monitored box in the estate, which is currently offline, is not a recovery plan. It is a coin flip you did not know you were holding.&lt;/p&gt;

&lt;p&gt;Fixed by escrowing it as &lt;code&gt;devbox_borg_passphrase&lt;/code&gt;, and proven the only way that counts: open the VPS-side replica using only that escrowed value. It extracted &lt;code&gt;etc/hostname&lt;/code&gt; reading &lt;code&gt;team-server&lt;/code&gt;, sha256 &lt;code&gt;82c0970220c9b48b...&lt;/code&gt; identical to live, 17 archives listed.&lt;/p&gt;

&lt;p&gt;The write into &lt;code&gt;secrets.prod.sops.yaml&lt;/code&gt; was guarded, because a file holding 28 other production secrets is not a file you edit casually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# &amp;lt;hash-each-value&amp;gt; is a placeholder: whatever you use to emit one&lt;/span&gt;
&lt;span class="c"&gt;# "key -&amp;gt; sha256(value)" line per entry. The shape is the point.&lt;/span&gt;
sops &lt;span class="nt"&gt;-d&lt;/span&gt; secrets.prod.sops.yaml | &amp;lt;hash-each-value&amp;gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/shm/before.txt
&lt;span class="c"&gt;# ... add devbox_borg_passphrase ...&lt;/span&gt;
sops &lt;span class="nt"&gt;-d&lt;/span&gt; secrets.prod.sops.yaml | &amp;lt;hash-each-value&amp;gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/shm/after.txt
diff /dev/shm/before.txt /dev/shm/after.txt
&lt;span class="c"&gt;# expect: exactly one added line, zero changed lines, 3 recipients preserved&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;None of the 28 changed. One key added. Three age recipients preserved, one of which is a recipient nobody can identify. That comes back later, and it is the reason "nothing changed" is a weaker guarantee here than it sounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just put the key on another box?
&lt;/h2&gt;

&lt;p&gt;The obvious move is to copy the key material to a second machine and call it redundant. That is what "escrow" sounds like it means.&lt;/p&gt;

&lt;p&gt;It is wrong for a specific reason, and the reason earned its own decision number in &lt;code&gt;decision-log/049&lt;/code&gt; (D174 through D180). Three rules came out of it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An escrow is never encrypted to its own subject.&lt;/strong&gt; Recovery material that is only readable from the machine whose destruction it insures against is not escrow, it is a second copy of the problem. So the Buzz escrow at &lt;code&gt;ops/buzz/secrets/buzz.borg-escrow.sops.yaml&lt;/code&gt; is encrypted to the estate key and the shared VPS host key, and deliberately &lt;strong&gt;not&lt;/strong&gt; to the dedicated Buzz host key.&lt;/p&gt;

&lt;p&gt;That rule lives in &lt;code&gt;.sops.yaml&lt;/code&gt;, at the exact point where someone would make the mistake, not in a paragraph of a document nobody opens while running a &lt;code&gt;sops&lt;/code&gt; command. The real comment is longer; this is its shape, with the recipients redacted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;creation_rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# KEY ESCROW. Recipients are deliberately the estate key plus the&lt;/span&gt;
  &lt;span class="c1"&gt;# shared-VPS host key, and deliberately NOT the dedicated buzz host&lt;/span&gt;
  &lt;span class="c1"&gt;# key: encrypting a host's escrow to that same host is circular. It&lt;/span&gt;
  &lt;span class="c1"&gt;# would be readable only from the machine whose destruction it exists&lt;/span&gt;
  &lt;span class="c1"&gt;# to survive. See ops/host/secrets/KEY-CUSTODY.md and decision-log/049.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path_regex&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ops/buzz/secrets/buzz\.borg-escrow\.sops\.yaml$&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;&amp;lt;estate-key&amp;gt;,&lt;/span&gt;
      &lt;span class="s"&gt;&amp;lt;shared-vps-host-key&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The acceptance test is a backup verification drill: a restore using only the escrowed copy.&lt;/strong&gt; Never the existence of a file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The passphrase is escrowed with the key.&lt;/strong&gt; Which is the whole post.&lt;/p&gt;

&lt;h2&gt;
  
  
  The drill, and the negative test that is the point
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ops/buzz/scripts/escrow-restore-drill.sh&lt;/code&gt; runs on the host. The sequence matters more than any individual step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. baseline from the LIVE repo&lt;/span&gt;
borg extract ::&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ARCHIVE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; postgres.dump      &lt;span class="c"&gt;# 6,988,132 bytes, sha256 97021228c2...&lt;/span&gt;

&lt;span class="c"&gt;# 2. copy the repo, strip the repokey blob from the COPY, prove it is dead&lt;/span&gt;
borg list &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COPY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;                            &lt;span class="c"&gt;# MUST FAIL. if this passes, the drill is a lie.&lt;/span&gt;

&lt;span class="c"&gt;# 3. recover using ONLY escrowed key + escrowed passphrase&lt;/span&gt;
borg key import &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COPY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ESCROWED_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
borg list &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COPY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;                            &lt;span class="c"&gt;# 11 archives&lt;/span&gt;
borg extract ...  postgres.dump              &lt;span class="c"&gt;# byte-identical to step 1&lt;/span&gt;
pg_restore &lt;span class="nt"&gt;--list&lt;/span&gt; postgres.dump              &lt;span class="c"&gt;# 421 restorable objects&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2 is the one people skip and it is the one that makes the rest mean anything. Without proving the stripped copy actually fails, step 3 proves only that borg found a key somewhere, which it very much will if you leave one lying around.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pg_restore --list&lt;/code&gt; is there for the same reason. Byte-identical says the extract worked. 421 restorable objects says the artifact is usable. Those are different claims and only the second one is what a restore is for.&lt;/p&gt;

&lt;p&gt;One more detail that decides whether the drill tests anything: the escrowed material was re-derived from the &lt;strong&gt;committed&lt;/strong&gt; SOPS file before the drill and confirmed byte-identical to the host's live key export. A drill against a copy sitting in a scratch directory tests the scratch directory. The point is to test what is in git. That is the same distinction as &lt;a href="https://startaitools.com/posts/the-drills-passed-reality-did-not/" rel="noopener noreferrer"&gt;the drills that passed while reality did not&lt;/a&gt;, where a documented posture and the deployed copy had quietly stopped agreeing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The drill broke live backup access, and that is the second finding
&lt;/h2&gt;

&lt;p&gt;First run of the drill, live backup access broke. Nothing was lost. Future runs would simply have stopped.&lt;/p&gt;

&lt;p&gt;Borg records where a repository id was last seen. Working on a copy re-pinned that location, so the next access to the live repo hit a relocation prompt and aborted. Inside &lt;code&gt;buzz-backup.timer&lt;/code&gt;, with no TTY to prompt, that is not a visible failure. It is a &lt;strong&gt;silent&lt;/strong&gt; one. The timer fires, borg aborts, and the next thing that notices is a restore attempt weeks later.&lt;/p&gt;

&lt;p&gt;Caught and repaired the same session. Location re-pinned, then &lt;code&gt;borg info&lt;/code&gt; and &lt;code&gt;backup.sh --dry-run&lt;/code&gt; both verified clean with &lt;strong&gt;no override environment variable set&lt;/strong&gt;, exactly as the timer runs it. Verifying with an override in your shell verifies your shell.&lt;/p&gt;

&lt;p&gt;The script now forces its own state directories, with a comment saying why removing them is not an option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# NOT removable. Without these, operating on a repo COPY re-pins borg's&lt;/span&gt;
&lt;span class="c"&gt;# record of where the LIVE repo lives, and the next timer-driven backup&lt;/span&gt;
&lt;span class="c"&gt;# aborts on a relocation prompt with no TTY. Silent backup failure.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BORG_SECURITY_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DRILL_DIR&lt;/span&gt;&lt;span class="s2"&gt;/security"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BORG_CACHE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DRILL_DIR&lt;/span&gt;&lt;span class="s2"&gt;/cache"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the shape, because it is the same shape as the passphrase. Borg's location record is state that lives next to the data and gets stomped by touching a copy of it. The passphrase was state that lived next to the data and did not get copied with it. Both are the estate believing the repo carries everything the repo needs, and both fail quietly, which is why the drill has to run with no override set and why the guard is not optional.&lt;/p&gt;

&lt;p&gt;Second defect, recorded in the evidence summary rather than quietly fixed: a &lt;code&gt;sed&lt;/code&gt; redaction masked only the &lt;strong&gt;first&lt;/strong&gt; line of a multi-line key blob, so passphrase-encrypted continuation lines reached the session transcript. Partial, passphrase-encrypted, reached no file and no commit and no remote. The redaction method changed immediately. Both defects are in &lt;code&gt;evidence/2026-08-08-spine-3fy-buzz-key-escrow/&lt;/code&gt; because an evidence bundle that reports only wins is marketing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The host that looked most exposed held nothing unique
&lt;/h2&gt;

&lt;p&gt;Third finding from the register, and it went the other direction.&lt;/p&gt;

&lt;p&gt;The home server looks like the sharp end. Least monitored box in the estate, least backed up, currently offline. It holds two passphrase files. The expectation going in was a transfer job.&lt;/p&gt;

&lt;p&gt;It was not. Both files are the VPS repo passphrase and the dev-box repo passphrase. A value that opens repo X &lt;strong&gt;is&lt;/strong&gt; repo X's passphrase, and the scripts on that box &lt;code&gt;borg check&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, and &lt;code&gt;extract&lt;/code&gt; exactly those two repos. Both are now escrowed elsewhere, so that whole slice collapsed from a migration into a one-command confirmation. Recorded with its caveats: the box is offline right now, and six days in seven the pull runs &lt;code&gt;--repository-only&lt;/code&gt;, which needs no key at all.&lt;/p&gt;

&lt;p&gt;That is also the exception I promised earlier. The dev-box passphrase was not literally single-copy. There was a second one, sitting on the home server, because a script there needed it to check the replica. Nothing recorded that. It is not in a register, not in a runbook, not in the coverage table. So the estate's actual survival odds on a dev-box loss depended on an undocumented file, on an offline box, that nobody would have thought to look for while trying to open 84 GB of archives in an emergency.&lt;/p&gt;

&lt;p&gt;Both directions of that are the same finding. Replication moved the data and not the access. Documentation tracked neither. The register is what made both visible, and the most useful single thing it produced about the scariest host in the estate was proof that there was no gap there at all. An inventory that can only return findings is not an inventory. That is the neighboring failure to &lt;a href="https://startaitools.com/posts/nothing-read-it-so-nothing-failed/" rel="noopener noreferrer"&gt;an artifact with a producer and no consumer&lt;/a&gt;: here the artifact had a consumer and no record, so key custody was decided by whoever last wrote a script.&lt;/p&gt;

&lt;p&gt;Two more things it surfaced, both outside the redundancy story, both worth naming because the same register produced them.&lt;/p&gt;

&lt;p&gt;A third age recipient, &lt;code&gt;age197nar...&lt;/code&gt;, can decrypt every production secret and is documented nowhere (swept &lt;code&gt;000-docs/&lt;/code&gt;, the runbooks, and the &lt;code&gt;.sops.yaml&lt;/code&gt; comments, no match). It is one of the three recipients the earlier before-and-after check confirmed as unchanged, which is exactly why "nothing changed" is a weaker guarantee than it reads. Recorded as an open question for the owner and deliberately &lt;strong&gt;not removed&lt;/strong&gt;. Removing an unknown recipient locks out whatever depends on it, and you learn which service that was at the worst possible moment.&lt;/p&gt;

&lt;p&gt;And the identity fact (D179). The Buzz Desktop app runs on the home server, so the nostr identity &lt;code&gt;0ace65ad&lt;/code&gt; lives there. The repo could not answer this and actively contradicted itself: &lt;code&gt;000-docs/033&lt;/code&gt; defines "workstation" as the dev box, &lt;code&gt;000-docs/142&lt;/code&gt; says the desktop app is on the home server, and three separate docs say "client-side" without naming a machine. Look at the shape of that. Every prior statement in the repo about where a human key lives was a &lt;strong&gt;negative&lt;/strong&gt;: "client-side", "never touches our shells". Those tell you where the key is not. Blast radius needs a positive. That identity owns both the CCA private channel and welcome-everyone, so its exposure is a fact about the least-monitored box in the estate, and the docs could not say so because they had only ever ruled places out.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUNBOOK-key-incidents.md&lt;/code&gt; priced two keys, &lt;code&gt;RELAY_OWNER_PUBKEY&lt;/code&gt; and &lt;code&gt;BUZZ_RELAY_PRIVATE_KEY&lt;/code&gt;, both recoverable, and omitted the one that is not. Added as a fourth incident, honest that it is mostly a warning: an nsec cannot be reset, only a channel's owner can act on it, and the relay owner has no override. Loss permanently forfeits ownership with no administrative path back. It also records the mitigation considered and &lt;strong&gt;not&lt;/strong&gt; taken: co-owning channels with Buzz Admin would cost sole-delete rights over the CCA private channel, which is a deliberate confidentiality boundary, so the cheaper fix buys resilience by spending the thing the channel exists for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The docs are the handover artifact
&lt;/h2&gt;

&lt;p&gt;Executing &lt;code&gt;spine-3fy&lt;/code&gt; made several statements across the Buzz documentation set false. Not stale, false. &lt;code&gt;RUNBOOK-backup-restore.md&lt;/code&gt; carried a MUST-do warning that is now done, plus a correction block asserting it "was also never actioned". Both onboarding guides told the new lead the key had never been exported.&lt;/p&gt;

&lt;p&gt;So the set got re-read as a handover artifact instead of spot-checked, and the corrections landed as &lt;strong&gt;dated notes rather than rewrites&lt;/strong&gt;, original text retained inline. That is the repo's discipline: when two records disagree, running reality wins, then you fix the loser with a dated correction so the provenance survives. A clean rewrite would have erased the evidence that the estate ever believed the wrong thing, which is the part a new owner most needs to see.&lt;/p&gt;

&lt;p&gt;The re-read raised a new gap rather than leaving it silent. &lt;code&gt;buzz.borg-escrow.sops.yaml&lt;/code&gt; is a &lt;strong&gt;fourth&lt;/strong&gt; file in &lt;code&gt;ops/buzz/secrets/&lt;/code&gt; and the new lead's grant 4 covers three. As written, he would own Buzz operationally and be unable to decrypt Buzz's backup escrow. The lesson that went into his onboarding: executing a remediation is also a re-audit of the remediation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is not fixed
&lt;/h2&gt;

&lt;p&gt;Buzz production still has &lt;strong&gt;no off-site copy&lt;/strong&gt;, so the disaster recovery posture stays partial. &lt;code&gt;spine-9yg&lt;/code&gt;, P0, open. This work unblocks it, because an off-site copy of an undecryptable archive is not a backup, but it does not build the leg. The &lt;code&gt;coverage[]&lt;/code&gt; row still correctly reads &lt;code&gt;no_offsite_copy&lt;/code&gt;. Buzz production has exactly one copy of its data. That copy is now decryptable after host loss, which is a different and much smaller claim than being recoverable after host loss. Better than 2026-08-07. Still not a backup.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spine-u1a.2.3&lt;/code&gt; stays open on its second half: the restore-only age key does not exist. And the age private keys are the bootstrap exception. They cannot be age-escrowed, their out-of-band status is UNCONFIRMED, and losing the estate key makes every escrow described here unreadable. &lt;code&gt;0ace65ad&lt;/code&gt; is still unescrowed, because that one is an owner-only UI action.&lt;/p&gt;

&lt;p&gt;No key was rotated. None is proposed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The session that would not build the workaround
&lt;/h2&gt;

&lt;p&gt;Gates green: &lt;code&gt;pnpm check&lt;/code&gt; exit 0 (markdownlint over 525 files inside a chain of about thirty steps), disclosure gate clean, &lt;code&gt;gitleaks protect --staged&lt;/code&gt; clean, &lt;code&gt;ops/buzz/tests/key-runbook-commands-test.sh&lt;/code&gt; 7 of 7 with the new incident added. One real catch on the way through: &lt;code&gt;validate:buzz-skill-refs&lt;/code&gt; failed because &lt;code&gt;.claude/skills/buzz-ops/&lt;/code&gt; vendors a copy of the deployment reference that had drifted. Resynced, all three vendored references match canonical.&lt;/p&gt;

&lt;p&gt;Handling, since escrowing a key badly is worse than not escrowing it. Plaintext key material existed only in &lt;code&gt;/dev/shm&lt;/code&gt;, was &lt;code&gt;shred&lt;/code&gt;ed after encryption, and moved host to host in a single &lt;code&gt;tar | ssh&lt;/code&gt; stream into a &lt;code&gt;mktemp -d&lt;/code&gt; with &lt;code&gt;trap ... EXIT&lt;/code&gt; cleanup. Nothing hit disk on either box.&lt;/p&gt;

&lt;p&gt;That work ran with &lt;strong&gt;Claude Opus 5&lt;/strong&gt;, four sessions and about twenty hours of span, and one thing from earlier in the day belongs here because it is the same subject. The session opened on an unrelated task, deploying the already-built B3.2b receiver, and hit a wall: no route existed to get &lt;code&gt;origin/main&lt;/code&gt; onto the VPS. Four routes checked, four closed. The stale VPS checkout was 24 commits behind and carrying a marker file named &lt;code&gt;STALE-CHECKOUT-NOT-DEPLOY-SOURCE.txt&lt;/code&gt;. A read-only deploy key returned 422, deploy keys disabled org-wide. The VPS PAT in SOPS returned 401, expired. No CI deploy workflow exists.&lt;/p&gt;

&lt;p&gt;Every one of those is an invitation to invent a credential. Instead the key material already created got cleaned up rather than left stranded, the blocker was filed as a P0 bead (&lt;code&gt;spine-7br&lt;/code&gt;), and the conclusion was that this is an owner call and not more engineering. Refusing to route around a deliberately disabled credential with an ad-hoc one is the correct answer on any day. On a day whose entire subject is who can decrypt what, it is the only answer, and it is not the one that feels productive at 2 a.m.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also shipped
&lt;/h2&gt;

&lt;p&gt;Three other PRs landed the same day. Different systems, and one of them is the same mistake in a different register.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PR #405, the collector supersedes its own stale proposals.&lt;/strong&gt; Each proposal branch is named after its content digest, so a changed run opens a new branch, and &lt;code&gt;promotion.py&lt;/code&gt; had no close path at all. The sweep found four open at once, all rewriting the same ~100 generated files, so every extra one was a merge conflict waiting for whoever reviewed second. Close only if the branch carries the collector's prefix &lt;strong&gt;and&lt;/strong&gt; the title is the generated proposal title, because a cron job closing a human's PR is far worse than a stale proposal staying open. The guard was proven by planting the defect: remove the title check and exactly two scoping tests fail, one of them the human-PR case. It also retracted an earlier claim of mine with measured data. &lt;code&gt;rclone size&lt;/code&gt; reports 9.922 GiB current against 11.507 GiB with versions on an 11 GB source, about 1.16x, so "monotonic growth, raising the cap only defers it" was wrong. It is a cap set below the data. Raise it, roughly $0.07 a month, add an alert under it, leave Object Lock alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PR #396, the HQ checkpoint result.&lt;/strong&gt; HQ proposed two additions and a direction change. All three had been ratified two days earlier as &lt;code&gt;decision-log/047&lt;/code&gt;, same six columns, same verbatim framing. Leading with that correction beat burying it, because HQ spending a cycle closing a gap that is already closed is the expensive outcome. The report answers its own seven operational-readiness questions against the B3.2b receiver rather than assuming, and scores &lt;strong&gt;5 of 7&lt;/strong&gt;, so by its own rule that receiver is not operational and would not be even if it deployed today. It also records two things the session got wrong, including "byte-identical" asserted before it was proven.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PR #12 in partner-portals, a false sentence the live page was serving.&lt;/strong&gt; It claimed Plane has no SMTP configured. Plane keeps mail settings in &lt;code&gt;instance_configurations&lt;/code&gt;, not the container environment, so the check that produced the claim looked in the wrong place. Proved live by sending through Plane's own &lt;code&gt;get_email_configuration()&lt;/code&gt;. The invite genuinely never arrived, but for a different reason: the public v1 API writes the invitation row without enqueuing &lt;code&gt;workspace_invitation&lt;/code&gt;. And the new lead was never blocked at all, because &lt;code&gt;__check_signup&lt;/code&gt; treats an existing invite row as an explicit exemption. Same day, the welcome email went through a five-lens review (69 findings, six blockers) and shrank from about 2,400 words to 562, because it had become a mutable snapshot of the guides, which is the "v2 attached to an email" the portal exists to prevent. The skills bundle now ships as portal plus published hash instead of an attachment: a skill carries &lt;code&gt;allowed-tools&lt;/code&gt; and instructions an agent acts on, and an emailed zip teaches a new hire to trust the next emailed zip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://startaitools.com/posts/nothing-read-it-so-nothing-failed/" rel="noopener noreferrer"&gt;Nothing Read It, So Nothing Failed&lt;/a&gt; is the backup fabric this sits next to, five defects that all shared the shape of an artifact with a producer and no consumer.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://startaitools.com/posts/the-drills-passed-reality-did-not/" rel="noopener noreferrer"&gt;The Drills Passed. Reality Did Not.&lt;/a&gt; is the same gap seen from the other side, a documented posture versus what the deployed copy actually does.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://startaitools.com/posts/onboarding-one-person-audited-the-whole-estate/" rel="noopener noreferrer"&gt;Onboarding One Person Audited the Whole Estate&lt;/a&gt; is the day before this one, and the same handover that forced the custody decision.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>architecture</category>
      <category>automation</category>
    </item>
    <item>
      <title>Three Commits Between the Rule and the Violation</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Sat, 08 Aug 2026 10:36:11 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/three-commits-between-the-rule-and-the-violation-3je8</link>
      <guid>https://dev.to/jeremy_longshore/three-commits-between-the-rule-and-the-violation-3je8</guid>
      <description>&lt;p&gt;Understanding a failure mode does not inoculate you against shipping it. This blog has returned to vacuous checks repeatedly over the past two weeks, most recently 2026-08-05 and 2026-08-03. One admission is due: that frequency reads obsessive. But this instance earns publication for its specificity and for what it says about review.&lt;/p&gt;

&lt;p&gt;The rationale and the defect shipped in the same commit. Commit &lt;code&gt;25df411ad&lt;/code&gt; added &lt;code&gt;check-changelog-coverage.mjs&lt;/code&gt; carrying a header that explains why inert surfaces rot, and in the same diff wired it into a job where it could never run. Two AI reviewers read PR #1162. Greptile submitted a review with no findings. Kilo flagged CRITICAL. That is not an argument about AI reviewers being superior. It is an argument about which questions catch which defects: the author reads &lt;code&gt;check-changelog-coverage.mjs&lt;/code&gt; and sees the invariant he intended. A reader with no investment reads &lt;code&gt;fetch-depth: 2&lt;/code&gt; and asks whether tags are present. One reviewer checked the mechanism (what does a shallow clone at &lt;code&gt;fetch-depth: 2&lt;/code&gt; actually contain). The other checked the intent (is this the right invariant) and found nothing. That asymmetry is what a fresh reader can do that an invested one cannot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Changelog Frozen at March
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;claude-code-plugins&lt;/code&gt; shipped v4.33.0 on 2026-05-25. By 2026-08-06, the site advertised that version under a link labeled "what's new" pointing to release notes dated 2026-03-07. Seventeen tagged releases and 556 commits had shipped with no notes at all.&lt;/p&gt;

&lt;p&gt;Commit &lt;code&gt;fa454f5ae&lt;/code&gt; backfilled all 17 entries from &lt;code&gt;git log&lt;/code&gt; ranges, grouped by conventional-commit type, with real PR links. Where the three existing entries were hand-written prose explaining why each change mattered, reconstructing that voice for releases months old would mean inventing rationale. Each backfilled entry states plainly that it was reconstructed from the tag range. Accurate over readable.&lt;/p&gt;

&lt;p&gt;A second finding, deliberately not bundled into the docs backfill: as of that day, 336 commits had merged since v4.33.0 with no tag and no version bump.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gate, Written and Then Shipped Inert
&lt;/h2&gt;

&lt;p&gt;Commit &lt;code&gt;25df411ad&lt;/code&gt; added &lt;code&gt;scripts/check-changelog-coverage.mjs&lt;/code&gt;, wired into the validate job. Its invariant: for every &lt;code&gt;vX.Y.Z&lt;/code&gt; git tag, a matching changelog entry exists with that version in frontmatter. The file header articulates the rationale (paraphrase, dashes removed):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A changelog rots for the same reason the missing og:image survived five months: nothing in the build depends on it being right. This makes something depend on it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That og:image is not a hypothetical. It is &lt;a href="https://dev.to/blog/the-check-that-only-confirmed-a-name/"&gt;a real case from three days earlier&lt;/a&gt;: &lt;code&gt;BaseLayout&lt;/code&gt; advertised &lt;code&gt;/og-image.png&lt;/code&gt; on 3,830 published pages and the file had never been committed at all. So the header is not vague pattern-awareness. It names a specific worked example, in the same diff that shipped the same failure.&lt;/p&gt;

&lt;p&gt;Two design calls worth showing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The floor is a constant, pinned deliberately.&lt;/strong&gt; The first version computed the floor as the oldest documented entry. Deleting that entry would raise the floor silently, and the gate would report "0 missing" with one fewer release covered. Verified by removing v4.14.0's notes: floor moved to v4.15.0, exit 0. A ratchet a file deletion can loosen is not a ratchet. The constant came from that test. There is a coda: lines 29-32 of that same file still describe the design that was rejected, documenting a derived floor. Line 104 implements the pinned one. The code is correct; the header is stale. Nobody has re-read it. It is the same class sitting inside the exhibit.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FLOOR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4.14.0&lt;/span&gt;&lt;span class="dl"&gt;'&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;documented&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="nx"&gt;FLOOR&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`The pinned floor v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;FLOOR&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has no release notes. Either restore them, or\n`&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
      &lt;span class="s2"&gt;`lower FLOOR in this script deliberately, do not let it drift.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&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="nx"&gt;WARN_ONLY&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;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deliberately not gated:&lt;/strong&gt; entry quality and whether unreleased work has notes. Demanding prose nobody has written is how gates get disabled.&lt;/p&gt;

&lt;p&gt;Then PR #1162 went up. Kilo Code Review flagged CRITICAL. The finding: &lt;code&gt;actions/checkout&lt;/code&gt; does not fetch tags by default, and that job uses &lt;code&gt;fetch-depth: 2&lt;/code&gt;. So &lt;code&gt;git tag --list&lt;/code&gt; returns EMPTY in CI.&lt;/p&gt;

&lt;p&gt;Verified by cloning exactly what CI produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 2 &lt;span class="nt"&gt;--no-tags&lt;/span&gt; file:///path/to/repo cov-test
&lt;span class="nb"&gt;cd &lt;/span&gt;cov-test
git tag &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="s1"&gt;'v*'&lt;/span&gt;
&lt;span class="c"&gt;# (empty)&lt;/span&gt;
node scripts/check-changelog-coverage.mjs
&lt;span class="c"&gt;# no version tags visible - skipping&lt;/span&gt;
&lt;span class="c"&gt;# EXIT 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A PR could delete the entire changelog and this silent CI failure would report success. The gate passed because it never ran, not because it verified anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Full History
&lt;/h2&gt;

&lt;p&gt;The short version, for anyone who arrived here from a search box: &lt;code&gt;actions/checkout&lt;/code&gt; does not fetch tags by default. Under a shallow clone (&lt;code&gt;fetch-depth: 2&lt;/code&gt;), &lt;code&gt;git tag --list&lt;/code&gt; returns empty, so any gate that keys on tags skips itself and exits 0 without checking anything. Reach for &lt;code&gt;fetch-tags: true&lt;/code&gt; rather than &lt;code&gt;fetch-depth: 0&lt;/code&gt;, which exposes the tags without paying for full history on every run.&lt;/p&gt;

&lt;p&gt;The longer version is that &lt;code&gt;fetch-depth: 0&lt;/code&gt; would work, but two separate constraints make &lt;code&gt;fetch-tags: true&lt;/code&gt; the surgical choice. First, the catalog format guard in the same job needs the merge base, so the shallow clone has to stay at &lt;code&gt;fetch-depth: 2&lt;/code&gt;. Second, a full-history fetch on every PR is a real cost to buy one gate's benefit. &lt;code&gt;fetch-tags: true&lt;/code&gt; gets the tags without paying for the history.&lt;/p&gt;

&lt;p&gt;The fix, ordered so the explanation precedes the change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="c1"&gt;# fetch-tags is REQUIRED by check-changelog-coverage.mjs below.&lt;/span&gt;
  &lt;span class="c1"&gt;# actions/checkout does not fetch tags by default, so `git tag --list`&lt;/span&gt;
  &lt;span class="c1"&gt;# returned EMPTY and that gate silently exited 0. It never fired in&lt;/span&gt;
  &lt;span class="c1"&gt;# CI at all. Verified by cloning --depth 2 --no-tags and deleting every&lt;/span&gt;
  &lt;span class="c1"&gt;# release note: still exit 0. fetch-depth stays 2 (the catalog format&lt;/span&gt;
  &lt;span class="c1"&gt;# guard needs the merge base); fetch-tags is the surgical addition.&lt;/span&gt;
  &lt;span class="na"&gt;fetch-tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;persist-credentials&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kilo raised four other findings in the same review. &lt;code&gt;git tag --list&lt;/code&gt; takes a GLOB, not a regex, so &lt;code&gt;v[0-9]*.[0-9]*.[0-9]*&lt;/code&gt; has a literal dot and zero-or-more wildcards and admits shapes it looks like it excludes. It is now filtered in JS with &lt;code&gt;/^v\d+\.\d+\.\d+$/&lt;/code&gt;. The skip was silent instead of loud, and silence makes a no-op indistinguishable from a pass:&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;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Loud, not silent. A gate that quietly no-ops is indistinguishable from a&lt;/span&gt;
  &lt;span class="c1"&gt;// passing one, which is precisely how this script shipped inert.&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;::warning title=changelog-coverage::No version tags visible - the gate did NOT run. If this is CI, the checkout needs fetch-tags: true.&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;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;changelog-coverage: no version tags visible - SKIPPED (not a pass)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also: &lt;code&gt;readdirSync&lt;/code&gt; needed recursion so a future &lt;code&gt;blog/2026/…&lt;/code&gt; grouping cannot silently stop counting posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Shape, Twice More
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;intent-os&lt;/code&gt; on the same day hosted two related breaks. The first: &lt;code&gt;vps-liveness-sweep-test.sh&lt;/code&gt; had an assertion checking that a delivery path was not retired. It invoked &lt;code&gt;rg&lt;/code&gt;, which was not on a non-interactive script's PATH. Exit 127, else branch taken, assertion reported ok. An always-passing check that verified nothing, because the tool it depended on was never invoked. It passed because its tool was missing, not because the property held. Switched to &lt;code&gt;grep -E&lt;/code&gt; (POSIX-present).&lt;/p&gt;

&lt;p&gt;The second: &lt;code&gt;run-proof.sh&lt;/code&gt; checked that a database unit FILE existed, then claimed "the receiver unit's Requires= names a real target." Different statements. Rename the target and the file still exists, so the assertion stays green while systemd would refuse to start the receiver. Caught by MiniMax on PR #389 and then lost. The branch was reset to resolve a rebase conflict, and #389 merged without it. An uncommitted fix leaves no trace. The restored version additionally asserts the receiver is ordered &lt;code&gt;After=&lt;/code&gt; the datastore, not merely &lt;code&gt;Requires=&lt;/code&gt; it. Proof went from 51 to 52 assertions, 0 failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Work That Day
&lt;/h2&gt;

&lt;p&gt;Claude Opus 5 and Claude Sonnet 5 drove the analysis. The &lt;code&gt;intent-os&lt;/code&gt; work spanned 8 sessions: 276 turns, 492 tool calls, 25 errors hit, across 1,189 minutes. The &lt;code&gt;claude-code-plugins&lt;/code&gt; session was the opposite: 42 turns, 63 tool calls, 43 minutes.&lt;/p&gt;

&lt;p&gt;A build that normally took 50 seconds blew past 600. The cause: the model's own astro preview servers left running three days, load average 12. It could not see its own mess until something unrelated broke, which is the same asymmetry as the gate: an external symptom surfaces a blind spot the author cannot see from the inside. It found and killed its own 10 processes, which surfaced five orphaned polling loops from 30 to 35 days prior. One had a &lt;code&gt;pgrep -f&lt;/code&gt; matching its own subprocess: permanently self-satisfied, unable to ever exit. Each exit condition was verified unreachable before killing. Load went 12.05 to 6.60. A cross-session hazard also surfaced: another session was building the same tree while this one held 17 uncommitted files. It stashed the other session's artifacts, committed, and popped the stash back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also Shipped
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;intent-os PR #389: isolated postgres:17.10-alpine for the webhook receiver, pinned by DIGEST, published on 127.0.0.1:5439 so which database you are connected to is answerable from the port.&lt;/li&gt;
&lt;li&gt;PRs #385 and #387: wire channels renamed to &lt;code&gt;wire-&amp;lt;provider&amp;gt;&lt;/code&gt;, failing loud on unresolved names. The human course-corrected the naming mid-flight.&lt;/li&gt;
&lt;li&gt;Caddy detail: &lt;code&gt;sudo caddy validate&lt;/code&gt; does not parse only, it builds the config. A log directive creates its output file as the invoking user at mode 0600. Under sudo that is root-owned; the service runs as caddy. Next reload cannot open its log and Caddy rejects the WHOLE config. One sudo on one new vhost stalls a reload for every domain on the host. Verified on Caddy v2.10.2.&lt;/li&gt;
&lt;li&gt;intent-curriculum: 60-item CCAO-F practice exam bank added.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Freshness Is Not Enough
&lt;/h2&gt;

&lt;p&gt;The author is the worst reader of his own gate because he has a model of what the code was supposed to do. Reading &lt;code&gt;check-changelog-coverage.mjs&lt;/code&gt;, he sees the invariant he intended. When he reads &lt;code&gt;fetch-depth: 2&lt;/code&gt;, he does not see it as a question because he already answered it: he knows why he chose 2. That model, from the inside, is indistinguishable from a model of what the code actually does. Freshness alone does not fix that, because checking the intent (is this the right invariant) is exactly what the author was already doing and is exactly what cannot catch this.&lt;/p&gt;

&lt;p&gt;Greptile was equally fresh. It checked the intent and found no issues. Kilo checked the mechanism: does &lt;code&gt;actions/checkout&lt;/code&gt; fetch tags. Intent-checking is what the invested reader does; mechanism-checking is what the fresh reader can do differently. Both are needed.&lt;/p&gt;

&lt;p&gt;For any gate you write, the question that catches this class is not "is the logic right" but "under what conditions does this exit 0 without running?" That is a question about the environment, not the code, which is why it survives code review and lands in production. Understanding the pattern, as the author articulated it in that header comment, does not inoculate you. You still need someone to ask the question whose answer you already know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/nothing-read-it-so-nothing-failed/"&gt;Nothing Read It, So Nothing Failed&lt;/a&gt; covers the same failure class at Tier 3 and broader scale.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/the-check-that-only-confirmed-a-name/"&gt;The Check That Only Confirmed a Name&lt;/a&gt; and &lt;a href="https://dev.to/blog/the-ghost-in-the-catalog/"&gt;The Ghost in the Catalog&lt;/a&gt; are adjacent instances in this family.&lt;/p&gt;

</description>
      <category>ci</category>
      <category>codereview</category>
      <category>githubactions</category>
      <category>aicodereview</category>
    </item>
    <item>
      <title>Nothing Read It, So Nothing Failed</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Fri, 07 Aug 2026 11:30:13 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/nothing-read-it-so-nothing-failed-94n</link>
      <guid>https://dev.to/jeremy_longshore/nothing-read-it-so-nothing-failed-94n</guid>
      <description>&lt;p&gt;Five defects surfaced on 2026-08-05 across five substrates that share nothing with each other.&lt;/p&gt;

&lt;p&gt;A JSON config key, &lt;code&gt;source.verify_before_push&lt;/code&gt;, set to &lt;code&gt;true&lt;/code&gt;, mirrored in a JSON schema as a &lt;code&gt;const&lt;/code&gt;, mirrored&lt;br&gt;
again in a test fixture, and read by zero lines of code. A systemd deployment manifest with a writer and no&lt;br&gt;
reader. A Postgres grant held on a table because the word appeared in the design vocabulary, not because any&lt;br&gt;
code touched it. A Python alert callback bound as a method, so &lt;code&gt;self&lt;/code&gt; arrived as the first positional argument&lt;br&gt;
and every single call raised &lt;code&gt;TypeError&lt;/code&gt; straight into a broad &lt;code&gt;except&lt;/code&gt;. An rsync mirror check that verified the&lt;br&gt;
copy matched the source rather than that the source still existed.&lt;/p&gt;

&lt;p&gt;All five are the same shape. &lt;strong&gt;An artifact with a producer and no consumer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is precisely why none of them ever failed. They did not emit a false green. Nothing consumed what they&lt;br&gt;
produced, so nothing they produced was ever in a position to be wrong.&lt;/p&gt;

&lt;p&gt;Be blunt about the distinction, because this blog has already run the "the check was lying" thesis four separate&lt;br&gt;
times in two weeks, most recently in&lt;br&gt;
&lt;a href="https://startaitools.com/posts/the-check-that-only-confirmed-a-name/" rel="noopener noreferrer"&gt;The Check That Only Confirmed a Name&lt;/a&gt;,&lt;br&gt;
and this is not that. A check that reports OK while doing nothing is a wrong answer,&lt;br&gt;
and a wrong answer is at least an answer. You catch it by asking whether the green is plausible. Most of these&lt;br&gt;
produced no answer at all. The config key was never consulted, so it never approved anything. The manifest was&lt;br&gt;
never read, so it never verified anything. The alert dispatch raised before it reached its callback, so it never&lt;br&gt;
alerted. There is no green to distrust because there is no signal, and silent failure reads identically to quiet&lt;br&gt;
health.&lt;/p&gt;

&lt;p&gt;The five are not identical, and pretending they were would be its own decorative claim. Three of them are the&lt;br&gt;
pure form: an artifact declared and never consulted. The fourth is the same shape at the call boundary, where a&lt;br&gt;
consumer was configured and made unreachable by a one-word binding error. The fifth is the edge of the class,&lt;br&gt;
and it is the interesting edge, because it had a consumer and still told nobody anything useful. Taking them in&lt;br&gt;
that order is the argument.&lt;/p&gt;

&lt;p&gt;Then, hours later, on the other side of the estate and citing none of it, the day's governance work&lt;br&gt;
independently named the general form. Two of the seven questions a subsystem must now answer before it counts as&lt;br&gt;
operational are "can Mission Control consume it" and "can an agent consume it." The engineering found the bug&lt;br&gt;
class in the morning. The governance wrote its law in the evening. Neither knew about the other.&lt;/p&gt;
&lt;h2&gt;
  
  
  The day started with a full disk
&lt;/h2&gt;

&lt;p&gt;The report from the human was "transcript writes are failing." That is a symptom, and a small one.&lt;/p&gt;

&lt;p&gt;Root was at 100 percent: a 387G volume with &lt;strong&gt;100K free&lt;/strong&gt;. Claude Code writes each command's output and the&lt;br&gt;
session transcript into &lt;code&gt;/tmp&lt;/code&gt;, so those writes hit &lt;code&gt;ENOSPC&lt;/code&gt; and got dropped. Nothing corrupted. Output just&lt;br&gt;
vanished.&lt;/p&gt;

&lt;p&gt;Underneath that, three legs of the backup fabric were broken at once, and the estate's own docs described a&lt;br&gt;
system that had not existed since 2026-07-28:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The dev box's own borg backup had failed every run since 08-04 with &lt;code&gt;ENOSPC&lt;/code&gt;, and the killed
run left a stale lock, so the 02:00 retry died in five seconds trying to acquire it.&lt;/li&gt;
&lt;li&gt;The VPS to dev-box replica pull failed all three attempts on 08-05, leaving a torn repo.&lt;/li&gt;
&lt;li&gt;The Backblaze B2 offsite push had not succeeded in &lt;strong&gt;eight days&lt;/strong&gt; while writing nothing at all
to its log.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Legs 1 and 2 had an architectural root cause, not a capacity one. &lt;code&gt;backup-system.sh&lt;/code&gt; backed up &lt;code&gt;/home/jeremy&lt;/code&gt;&lt;br&gt;
with no exclude for &lt;code&gt;~/backups&lt;/code&gt;, so the roughly 10G VPS replica was being swallowed into the dev box's own borg&lt;br&gt;
repo and shipped back to the VPS every night. The fabric was feeding itself. Proven by archive diff: &lt;strong&gt;113&lt;br&gt;
replica segment files in the Aug 4 archive, 0 in Aug 5's.&lt;/strong&gt; A backup store is never a backup source. That is now&lt;br&gt;
a rule with an incident behind it.&lt;/p&gt;

&lt;p&gt;Leg 3 was independent and worse in character. The last successful off-site push was 2026-07-28. Every nightly&lt;br&gt;
run after it failed, eight in a row, until the fix on 08-05. &lt;code&gt;b2-offsite-push.sh&lt;/code&gt; was the only script in the&lt;br&gt;
fabric with no &lt;code&gt;export PATH&lt;/code&gt;. Cron's &lt;code&gt;PATH=/usr/bin:/bin&lt;/code&gt; excludes &lt;code&gt;~/bin&lt;/code&gt;, where &lt;code&gt;sops&lt;/code&gt; lives, so the script&lt;br&gt;
exited BEFORE the line that opens &lt;code&gt;push.log&lt;/code&gt;. It was reproduced exactly under &lt;code&gt;env -i&lt;/code&gt; (exit 1, stderr only, log&lt;br&gt;
unchanged at 8 lines) before anything was changed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cron gives this script PATH=/usr/bin:/bin, which does NOT contain ~/bin, where `sops` lives.&lt;/span&gt;
&lt;span class="c"&gt;# Without this, the live path failed at the SOPS read on line ~100 and exited BEFORE push.log was&lt;/span&gt;
&lt;span class="c"&gt;# ever opened, so eight consecutive nightly pushes (2026-07-28 through 08-05) failed with zero log&lt;/span&gt;
&lt;span class="c"&gt;# evidence. The `.ok` staleness alarm was the only signal. Siblings borg-replica-pull.sh and&lt;/span&gt;
&lt;span class="c"&gt;# devbox-borg-push.sh already carry this line. This script was the one that did not.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;B2_OFFSITE_PATH&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/bin&lt;/span&gt;:&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.local/bin&lt;/span&gt;:/usr/local/bin:/usr/bin:/bin&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One line of fix, five lines of comment. For a defect that hid for eight consecutive nights, that is the correct&lt;br&gt;
ratio. The other half of the fix was moving log creation above the precondition checks, so a precondition&lt;br&gt;
failure can never be silent again.&lt;/p&gt;

&lt;p&gt;Restored and verified the same day: backup exit 0, replica &lt;code&gt;borg check&lt;/code&gt; verified at 10G, &lt;code&gt;push.ok&lt;/code&gt; moved from&lt;br&gt;
2026-07-28 to 2026-08-05T10:27, rclone check clean, receipt &lt;code&gt;1fc20ce0467ee66e&lt;/code&gt;, health monitor green. Disk went&lt;br&gt;
from 100K free to 25G free (100 percent to 94 percent) via stale &lt;code&gt;/tmp&lt;/code&gt; session dirs (about 6G), &lt;strong&gt;239 orphaned&lt;br&gt;
Docker volumes left over from the VPS migration&lt;/strong&gt; (about 12G), and 12 unused images plus build cache.&lt;/p&gt;

&lt;p&gt;The docs were wrong in three places and contradicted themselves: the backup README said "B2 is NOT&lt;br&gt;
provisioned," &lt;code&gt;automations.md&lt;/code&gt; said "immutable offsite (R2) still pending" (wrong provider AND wrong status,&lt;br&gt;
contradicting the next row of its own table), and the restore runbook told operators no offsite copy existed.&lt;br&gt;
Two smaller finds: a bare &lt;code&gt;backup/&lt;/code&gt; line in &lt;code&gt;.gitignore&lt;/code&gt; matched at any depth and had been silently swallowing&lt;br&gt;
&lt;code&gt;ops/backup/&lt;/code&gt;, and the borg timer had two &lt;code&gt;OnCalendar=&lt;/code&gt; lines and genuinely fired twice a night.&lt;/p&gt;

&lt;p&gt;All of that got written down. The estate (the full set of machines, services and repos this operation runs) keeps&lt;br&gt;
an append-only record of itself: numbered after-action reports, and a decision log where each ruling gets an ID&lt;br&gt;
and can be revised but never edited away. This incident produced after-action report &lt;code&gt;000-docs/150&lt;/code&gt;, with 13&lt;br&gt;
findings, and rulings D147 through D154 covering exactly the fixes above: the excludes, the &lt;code&gt;PATH&lt;/code&gt;, the size&lt;br&gt;
floor, and the three wrong docs. Those IDs are cited throughout this post. They are the receipts.&lt;/p&gt;
&lt;h2&gt;
  
  
  The model argued with its own closing summary
&lt;/h2&gt;

&lt;p&gt;Claude Opus 5 traced "transcript writes are failing" to the full disk, then to the broken borg run, then to the&lt;br&gt;
stale lock, then reclaimed space, declared the incident fixed, wrote a memory note for future sessions, and&lt;br&gt;
closed with two claims.&lt;/p&gt;

&lt;p&gt;Then the human steered, exactly as typed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;i need u to continue ans rhen adress the statemenr id we are backing ip on home server we dont&lt;br&gt;
nees tvis&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unprompted, after the incident was already closed, Claude Opus 5 came back and refuted both of its own closing&lt;br&gt;
claims.&lt;/p&gt;

&lt;p&gt;The first: it had called the cause "the disk filled up." That was the symptom. The real cause was the missing&lt;br&gt;
excludes, so the Docker and &lt;code&gt;/tmp&lt;/code&gt; reclaim was triage and the exclude fix was the cure. The second, and the one&lt;br&gt;
the human's steer targeted: it had said the backups had no protection against disk failure and offered to move&lt;br&gt;
them off box. False. B2 offsite with Object Lock is live and restore proven, with home server snapshots every&lt;br&gt;
six hours on top. It then edited the memory note it had just written, so a future session would not act on the&lt;br&gt;
bad read. A model that closes an incident and reopens its own summary to correct it is doing the same job as the&lt;br&gt;
guards below. It gave its own output a consumer. Most agent runs never do.&lt;/p&gt;

&lt;p&gt;Day totals, for scale: 1,125 tool calls and 1,418 minutes of session span across four project-days, 39 errors&lt;br&gt;
hit, one course correction. Claude Fable 5 and Claude Opus 5 carried intent-os (904 of those calls); Claude Opus&lt;br&gt;
5 had the blog repo; Claude Sonnet 5 took a two-minute errand elsewhere.&lt;/p&gt;

&lt;p&gt;None of what you just read is one of the five. A full disk, a missing exclude, a stale lock, an unanchored&lt;br&gt;
&lt;code&gt;.gitignore&lt;/code&gt; line: those are ordinary operational failures, loud once you look. They are here because clearing&lt;br&gt;
them is what put a human and three models inside the backup fabric long enough to read it properly. Two of the&lt;br&gt;
five defects were sitting in the scripts that incident forced open. The other three surfaced the same day in a&lt;br&gt;
system that shares nothing with it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defect 1: a config key three files declared and nothing read
&lt;/h2&gt;

&lt;p&gt;This is the purest instance of the pattern, so it goes first.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source.verify_before_push&lt;/code&gt; was &lt;code&gt;true&lt;/code&gt; in the config. It was in the JSON schema as a &lt;code&gt;const&lt;/code&gt;. It was in a test&lt;br&gt;
fixture. Three producers, two of them shown here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="c1"&gt;// excerpted from two separate files, not one document&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;// offsite-backup.config.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"verify_before_push"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;// offsite-backup-config.schema.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"verify_before_push"&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;"const"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"only a borg-check-verified source may be pushed (the check-then-mark discipline)."&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;p&gt;Zero consumers. Not one line of the push script ever read it. A schema that constrains a value nobody reads is&lt;br&gt;
documentation with a type annotation on it.&lt;/p&gt;

&lt;p&gt;It was a live near miss on 2026-08-05 itself. The replica pull had failed all three attempts that day and left a&lt;br&gt;
torn repo, which is exactly the state &lt;code&gt;verify_before_push&lt;/code&gt; was declared to refuse, and nothing was there to&lt;br&gt;
refuse it. Here is the enforcement that did not exist until that afternoon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Honour source.verify_before_push. Until 2026-08-05 this config key was declared true and read&lt;/span&gt;
&lt;span class="c"&gt;# by nothing.&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC_OK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; die_live &lt;span class="s2"&gt;"verify_before_push=true but no source verification marker at &lt;/span&gt;&lt;span class="nv"&gt;$SRC_OK&lt;/span&gt;&lt;span class="s2"&gt;, refusing to push an unverified repo."&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ok_age_h&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-le&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC_OK_MAX_H&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; die_live &lt;span class="s2"&gt;"verify_before_push=true but source last verified &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ok_age_h&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;h ago (max &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SRC_OK_MAX_H&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;h), refusing to push a stale/unverified repo."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note what changed and what did not. The config did not change. The schema did not change. The fixture did not&lt;br&gt;
change. Only the reader was added, and the invariant went from decorative to binding.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;b2-offsite-push.sh&lt;/code&gt; also had &lt;strong&gt;no test suite at all&lt;/strong&gt;, despite being the script that failed silently for eight&lt;br&gt;
nights. It got 6 hermetic cases (stubbing &lt;code&gt;sops&lt;/code&gt; and &lt;code&gt;rclone&lt;/code&gt;) plus 4 on the sibling suite for the size floor,&lt;br&gt;
wired into &lt;code&gt;ci:drills&lt;/code&gt;. An untested script is another producer without a consumer: nothing was reading its&lt;br&gt;
behavior either.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defect 2: a manifest with a writer and no reader
&lt;/h2&gt;

&lt;p&gt;The next three defects come from a GitHub webhook receiver built the same day. State the important thing first,&lt;br&gt;
because everything below describes hardening against hostile traffic: &lt;strong&gt;it is not deployed.&lt;/strong&gt; No host has run&lt;br&gt;
it, no delivery has reached it, and everything here was proven in drills. That is also why these three were&lt;br&gt;
findable at all.&lt;/p&gt;

&lt;p&gt;Caught in review. The best line of the day is the author conceding it in the thread (punctuation normalized to&lt;br&gt;
house style, wording otherwise as written):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I shipped the WRITING half of manifest verification and cited AAR &lt;code&gt;000-docs/145&lt;/code&gt; as design&lt;br&gt;
authority. With no reader, that citation is decorative and the AAR-145 failure mode is straight&lt;br&gt;
back in place. The entire point of that incident was that a hand-copied collector file ran for&lt;br&gt;
two nights &lt;strong&gt;because nothing checked it&lt;/strong&gt;. A manifest nobody reads is a comment with a hash in it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AAR 000-docs/145 in one line: on 2026-08-02 a partial hand copy of a collector script bypassed &lt;code&gt;install.sh&lt;/code&gt;, and&lt;br&gt;
the deployed copy ran for two nights failing manifest verification. Manifest verification has to run on every&lt;br&gt;
start, not be cited in a review.&lt;/p&gt;

&lt;p&gt;The fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# verify-manifest.sh: refuse to start a deployed copy that does not match its manifest.&lt;/span&gt;
&lt;span class="c"&gt;# Runs as the FIRST ExecStartPre, before the secret is even materialised.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;HERE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_SOURCE&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;MANIFEST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HERE&lt;/span&gt;&lt;span class="s2"&gt;/receiver.manifest.sha256"&lt;/span&gt;

fail&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"verify-manifest: FAIL: &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MANIFEST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; fail &lt;span class="s2"&gt;"manifest missing at &lt;/span&gt;&lt;span class="nv"&gt;$MANIFEST&lt;/span&gt;&lt;span class="s2"&gt;, deploy via install.sh, never hand-copy"&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HERE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sha256sum&lt;/span&gt; &lt;span class="nt"&gt;--check&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MANIFEST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;||&lt;/span&gt; fail &lt;span class="s2"&gt;"deployed copy does not match its manifest, redeploy via install.sh (AAR 000-docs/145)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual design decision is not the script. It is where the script sits in the unit file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;ExecStartPre&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/opt/intentsolutions/github-webhook-receiver/current/verify-manifest.sh&lt;/span&gt;
&lt;span class="py"&gt;ExecStartPre&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/opt/intentsolutions/github-webhook-receiver/current/deploy-secret.sh&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/opt/.../current/venv/bin/python /opt/.../current/receiver.py   # paths elided&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verification runs first, ahead of secret materialization. A copy that does not match what was reviewed should be&lt;br&gt;
refused before it is handed a secret, not after. The rest of the unit is hardened deliberately rather than&lt;br&gt;
decoratively, because this process will terminate untrusted internet traffic once it is deployed: a dedicated&lt;br&gt;
unprivileged user, &lt;code&gt;NoNewPrivileges&lt;/code&gt;, &lt;code&gt;ProtectSystem=strict&lt;/code&gt;, &lt;code&gt;MemoryDenyWriteExecute&lt;/code&gt;, a syscall filter, and&lt;br&gt;
&lt;code&gt;RestrictAddressFamilies&lt;/code&gt; limited to inet. &lt;code&gt;ReadWritePaths&lt;/code&gt; is enumerated rather than inherited, so the deployed&lt;br&gt;
copy would be read only to the service and a compromise could not rewrite its own binary and survive a restart.&lt;/p&gt;

&lt;p&gt;The proof got &lt;strong&gt;three assertions, not one&lt;/strong&gt;, because "the file exists" would have been the same defect at one&lt;br&gt;
remove: the unit references it, it runs FIRST, and it actually refuses a tampered copy. That last one is proven&lt;br&gt;
by tampering a byte, not by reading the script.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defect 3: a grant held on vocabulary rather than usage
&lt;/h2&gt;

&lt;p&gt;The claim in the database review was "append events, nothing else." It was false. The writer role also held&lt;br&gt;
SELECT and INSERT on &lt;code&gt;dlq&lt;/code&gt;, and nothing drilled it.&lt;/p&gt;

&lt;p&gt;Investigation showed the grant was never needed. &lt;code&gt;grep -n dlq ops/github-webhook-receiver/*.py&lt;/code&gt; returns nothing.&lt;br&gt;
The receiver marks dead-letter state via &lt;code&gt;outbox.status&lt;/code&gt;. The &lt;code&gt;dlq&lt;/code&gt; table belongs to &lt;code&gt;process_poison()&lt;/code&gt;&lt;br&gt;
downstream. The grant existed because the word &lt;code&gt;dlq&lt;/code&gt; was in the design vocabulary, not because any line of code&lt;br&gt;
used it.&lt;/p&gt;

&lt;p&gt;A grant belongs in this list because a grant is a claim about what code will do. A privilege audit that only&lt;br&gt;
asks whether the grant exists will pass this every time. It is written by one party,&lt;br&gt;
addressed to a second, and its correctness depends entirely on a third thing that may not exist: the code that&lt;br&gt;
uses it. An unused grant is a declaration with no consumer, and unlike a stale config key it is also standing&lt;br&gt;
attack surface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt;  &lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;ghwh_writer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;REVOKE&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;TRUNCATE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ghwh_writer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;GRANT&lt;/span&gt;  &lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;delivery_seen&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;ghwh_writer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt;  &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redeliveries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_seen_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;delivery_seen&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;ghwh_writer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;REVOKE&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;TRUNCATE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;delivery_seen&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ghwh_writer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;REVOKE&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;dlq&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ghwh_writer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;REVOKE&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;published_log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;consumer_offsets&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ghwh_writer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A second gap surfaced in the same review round, and it is a different bug class worth naming as such. &lt;code&gt;body_sha256&lt;/code&gt;&lt;br&gt;
was protected by a column-scoped GRANT only, while the narrative claimed database-level enforcement. That is an&lt;br&gt;
overclaim, not an unread artifact. An attacker on a privileged connection could have forged the recorded hash,&lt;br&gt;
which would make a replay-with-modified-body indistinguishable from an ordinary redelivery, silently disarming&lt;br&gt;
the only signal the system has that the webhook secret leaked. Fixed with a &lt;code&gt;delivery_seen_identity_guard&lt;/code&gt;&lt;br&gt;
trigger, so the constraint holds against any connection rather than against one role's grants.&lt;/p&gt;

&lt;p&gt;Both fixes are net privilege reductions, which is the right shape for a review round on something internet&lt;br&gt;
facing. In both cases the reviewer offered the easier path, "narrow the claim," and in both cases making the&lt;br&gt;
claim true was the better trade. Ten assertions now establish what the writer role CANNOT do. The framing that&lt;br&gt;
produced them: assume the process whose job is to terminate untrusted internet traffic is one day compromised,&lt;br&gt;
and ask what&lt;br&gt;
the attacker gets. A role that merely works is not a role that is bounded. Both migrations are applied &lt;strong&gt;twice&lt;/strong&gt;&lt;br&gt;
in the drill to prove idempotency, because a redeploy that is a coin flip is not a deployment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defect 4: an alert callback that was dead on arrival while every status code stayed correct
&lt;/h2&gt;

&lt;p&gt;The receiver's error paths all called &lt;code&gt;_alert&lt;/code&gt;. In the drills, every one of those calls raised &lt;code&gt;TypeError&lt;/code&gt; and&lt;br&gt;
the broad &lt;code&gt;except&lt;/code&gt; swallowed it. HTTP responses stayed correct through all of it, which is exactly why nothing&lt;br&gt;
looked wrong.&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;_alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Dispatch an alert. Never changes the HTTP outcome.

    `on_alert` is stored via staticmethod (see make_server). A plain function assigned to a
    class attribute is BOUND as a method on access, so `self` would arrive as the first
    positional argument and every call would raise TypeError, which the broad `except`
    below then swallowed, leaving the alert path dead and silent. That exact bug shipped
    here once and was caught only because the proof asserts an alert was recorded, not just
    that the status code was right. Assert on the side effect, not only the response.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;on_alert&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&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;cb&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# &amp;lt;- raised TypeError on every call
&lt;/span&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alert_dispatch_failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# &amp;lt;- added: the swallow now counts
&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;github-webhook-receiver: alert dispatch failed: &lt;/span&gt;&lt;span class="sh"&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;exc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&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="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;flush&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The broad &lt;code&gt;except&lt;/code&gt; is the right call, because an alerting failure must not change the response code that drives&lt;br&gt;
GitHub's retry semantics. What was missing was that it swallowed silently. It now increments a counter and&lt;br&gt;
writes to stderr, so a dead alert path is locally observable rather than invisible. The actual bug was one word&lt;br&gt;
at the binding site:&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;# staticmethod: a bare function here would be bound as a method on attribute access and
# receive `self` as its first argument. See Handler._alert.
&lt;/span&gt;&lt;span class="n"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_alert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;staticmethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;on_alert&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;on_alert&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the shape at the call boundary rather than in a file. The consumer existed and was correctly configured.&lt;br&gt;
Every error path reached for it. Not one call ever arrived, because the dispatch died one frame before it. It&lt;br&gt;
was found only because the proof asserts the side effect rather than the response code.&lt;/p&gt;

&lt;p&gt;Why this one mattered more than it looked. A GUID arriving with a &lt;strong&gt;different body whose signature verifies&lt;/strong&gt; is&lt;br&gt;
explainable neither as a redelivery nor as a forgery. It is a replay attack with a modified payload, and it is&lt;br&gt;
only possible if the webhook secret leaked. The&lt;br&gt;
receiver refuses to persist, answers 401, and raises a security-severity alert. For the life of the bug that&lt;br&gt;
alert would have gone nowhere, and the 401 would have looked like an ordinary rejection.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defect 5: a mirror check that verified the wrong thing
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;devbox-borg-push.sh&lt;/code&gt; verified that the copy matched the source. That is the check that reports green fastest&lt;br&gt;
when the source has been destroyed.&lt;/p&gt;

&lt;p&gt;An emptied source would &lt;code&gt;rsync --delete&lt;/code&gt; straight through to the VPS, satisfy the zero-differing-files check,&lt;br&gt;
and write a GREEN &lt;code&gt;.ok&lt;/code&gt; over a destroyed backup that the home server then mirrors within six hours. Three tiers&lt;br&gt;
of backup, all consistent, all empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;MIN_RATIO_PCT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DEVBOX_BORG_PUSH_MIN_RATIO_PCT&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;50&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;MIN_SRC_KB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DEVBOX_BORG_PUSH_MIN_SRC_KB&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;1048576&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;   &lt;span class="c"&gt;# 1 GiB absolute floor&lt;/span&gt;
&lt;span class="nv"&gt;MAX_DELETE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DEVBOX_BORG_PUSH_MAX_DELETE&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;2000&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;      &lt;span class="c"&gt;# rsync aborts past this many deletions&lt;/span&gt;

&lt;span class="c"&gt;# Source-plausibility floor (green-on-destruction guard)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$src_kb&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-ge&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MIN_SRC_KB&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; fail &lt;span class="s2"&gt;"source &lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;src_kb&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;KB, below the absolute floor"&lt;/span&gt; 6

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LASTGOOD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nv"&gt;last_kb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LASTGOOD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;          &lt;span class="c"&gt;# size of the last VERIFIED push&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$last_kb&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;[!&lt;/span&gt;0-9]&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;last_kb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="p"&gt;;;&lt;/span&gt; &lt;span class="k"&gt;esac&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$last_kb&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;floor_kb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; last_kb &lt;span class="o"&gt;*&lt;/span&gt; MIN_RATIO_PCT &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="k"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$src_kb&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-ge&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$floor_kb&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; fail &lt;span class="s2"&gt;"source shrank to &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;src_kb&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;KB from last-good &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;last_kb&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;KB, refusing to push a possibly-destroyed repo"&lt;/span&gt; 6
  &lt;span class="k"&gt;fi
fi&lt;/span&gt;

&lt;span class="c"&gt;# --max-delete makes rsync ABORT rather than carry out a mass deletion&lt;/span&gt;
rsync &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="nt"&gt;--max-delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MAX_DELETE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--stats&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSH_CMD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rsync-path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sudo -n rsync"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REMOTE&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$DEST&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The load-bearing detail is where &lt;code&gt;last_kb&lt;/code&gt; gets written. It is recorded &lt;strong&gt;only on the success path&lt;/strong&gt;, so a&lt;br&gt;
refused run can never re-baseline the guard downward. A guard that learns from its own refusals is not a guard.&lt;/p&gt;

&lt;p&gt;This is the edge of the class, and the post owes you the honesty about that. Defect 5 is the one that had a&lt;br&gt;
consumer. The health monitor read its &lt;code&gt;.ok&lt;/code&gt;, the next leg trusted it, and the whole chain would have believed&lt;br&gt;
it. It is not an unread artifact. It is the neighbor: an artifact whose reader was asking the wrong question, so&lt;br&gt;
the answer, though consumed, carried no information about the thing anyone cared about.&lt;/p&gt;

&lt;p&gt;That neighbor is worth sitting next to the other four, because the two failure modes rhyme. Consistency between&lt;br&gt;
a mirror and its source is a real property, just not the property you are trying to protect. The old check was&lt;br&gt;
not lying. It was answering a question nobody wanted the answer to, which is what an unread artifact would have&lt;br&gt;
done if anyone had bothered to read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decisions that lost
&lt;/h2&gt;

&lt;p&gt;Design rationale is only useful when the alternatives are named, so here are the ones that lost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python stdlib &lt;code&gt;http.server&lt;/code&gt; over Node.&lt;/strong&gt; Chosen by census, not taste. &lt;code&gt;ops/&lt;/code&gt; holds 1,189 &lt;code&gt;.py&lt;/code&gt; files against&lt;br&gt;
6 &lt;code&gt;.mjs&lt;/code&gt;, and both recently deployed services are a Python engine with a bash entry point. The more interesting&lt;br&gt;
stack would have bought a second deployment shape for one service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;psycopg3&lt;/code&gt; over shelling out to &lt;code&gt;psql&lt;/code&gt;.&lt;/strong&gt; The persist step is one transaction spanning a dedup upsert and an&lt;br&gt;
outbox insert, with arbitrary JSON as a bind parameter. A subprocess has no safe parameterization for that,&lt;br&gt;
spawns a process per delivery inside a 10 second ack budget, and cannot hold a transaction across two statements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;delivery_seen&lt;/code&gt; over the outbox as the replay ledger.&lt;/strong&gt; This is the one worth stealing. The outbox prunes&lt;br&gt;
dispatched rows at 90 days and takes their &lt;code&gt;dedup_key&lt;/code&gt; UNIQUE constraint with them, so a 91-day-old replay would&lt;br&gt;
sail straight through a system that looked perfectly deduplicated. The drill proves it empirically: age a row&lt;br&gt;
past the horizon, run the prune, confirm the outbox row is GONE and the ledger row REMAINS, then replay the GUID&lt;br&gt;
and watch it still get refused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Behavior-based assertions over grep-based ones.&lt;/strong&gt; Grep checks in this same proof produced two false positives&lt;br&gt;
on correct code: the &lt;code&gt;source_repository_id&lt;/code&gt; placement, and the comment DOCUMENTING the eval-sops anti-pattern&lt;br&gt;
being flagged as the violation itself. A test that fails on correct code is worse than no test, because it&lt;br&gt;
trains you to ignore the output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Versioned releases with an atomic symlink swap over in-place copy.&lt;/strong&gt; &lt;code&gt;install.sh&lt;/code&gt; writes &lt;code&gt;releases/&amp;lt;sha&amp;gt;/&lt;/code&gt;&lt;br&gt;
and repoints &lt;code&gt;current&lt;/code&gt;, so rollback is a rename rather than a re-copy, which matters for a service that is&lt;br&gt;
mid-flight when you roll it back. It refuses a dirty working tree, because deployed copies come from&lt;br&gt;
&lt;code&gt;origin/main&lt;/code&gt; and never a worktree. The venv lives INSIDE the release directory (PEP 668), so a rollback&lt;br&gt;
restores the dependency set that release was tested with. It ships BOTH schemas, because without the second one&lt;br&gt;
validation attempts a network retrieve and dies on a 404. That bug already landed here once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fail closed on secret materialization, with no "start anyway and warn" path.&lt;/strong&gt; &lt;code&gt;deploy-secret.sh&lt;/code&gt; pulls the&lt;br&gt;
webhook secret from SOPS to tmpfs and refuses to start if it cannot. It extracts two named keys with an anchored&lt;br&gt;
&lt;code&gt;sed&lt;/code&gt; and never evals or exports, because the estate has a recorded 2026-05-02 incident where eval-ing sops&lt;br&gt;
output turned comment lines into bare &lt;code&gt;export&lt;/code&gt; and dumped every exported variable to stdout.&lt;/p&gt;

&lt;p&gt;One more, on process rather than code. A regression guard was demonstrated firing before it was trusted:&lt;br&gt;
re-introducing the alert-wiring bug produced 17 passed and 3 failed, naming the wiring check, and restoring the&lt;br&gt;
fix produced 20 and 0. The rule stated in that PR is &lt;strong&gt;a guard that has never failed is a comment&lt;/strong&gt;, which is&lt;br&gt;
this same defect class wearing a test harness.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this cost
&lt;/h2&gt;

&lt;p&gt;Every one of those calls bought something and gave something up. Honest accounting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The size floor and &lt;code&gt;--max-delete&lt;/code&gt; trade a class of false refusals for protection against silent
destruction.&lt;/strong&gt; A legitimately shrunk repo, say after a deliberate prune, now needs a human to
unblock the push. Real on-call cost, paid forever, against an event that has not happened yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail closed on the secret means a SOPS outage takes the receiver down rather than degrading.&lt;/strong&gt;
That costs availability. A service that keeps answering without its verification secret is worse
than one that is down, but "worse than down" is not "free."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The retroactive governance rule creates visible unpaid debt.&lt;/strong&gt; Several already-running
production subsystems now fail a bar they were never built to meet. Making that debt visible is
the point. It is still debt, and nobody has scheduled paying it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eleven PRs merged in one day via the repository-admin bypass.&lt;/strong&gt; The only unmet rule was the
approving review count, which the author cannot self-provide, and no CI gate was bypassed. Moving
eleven changes through a lock in one day is still a governance smell, and saying otherwise would
be exactly the kind of decorative claim this whole post is about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The receiver is not deployed.&lt;/strong&gt; No host has run any of it. Everything above is proven in drills
against a disposable Postgres, 29 assertions in one round, ten of them the negative cases.
Drills are not production, and this corpus has a whole post about that gap.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The governance turn
&lt;/h2&gt;

&lt;p&gt;Eleven PRs merged in intent-os on 2026-08-05. The nine this post covers are the post-incident batch, #376&lt;br&gt;
through #384. Four of those were governance, carrying the rulings below in bundles rather than one per PR, and&lt;br&gt;
they were written by a different thread than the one finding the defects.&lt;/p&gt;

&lt;p&gt;Three of the rulings set up the fourth. &lt;strong&gt;D155&lt;/strong&gt; makes every operational subsystem self-reporting to Mission&lt;br&gt;
Control (the generated cockpit this estate runs itself from): backup, deploys, observability, evals, repo sync,&lt;br&gt;
agents, GitHub, all emitting machine-readable health so status is generated rather than assembled by hand.&lt;br&gt;
&lt;strong&gt;D161&lt;/strong&gt; turns that into an admission test every new feature must pass. &lt;strong&gt;D162&lt;/strong&gt; revises the drift rule so&lt;br&gt;
findings cluster into owner-approved recommendations instead of each becoming a backlog item, justified by&lt;br&gt;
measurement rather than estimate: the standing set is 92 findings, and the largest class of 50 turned out to&lt;br&gt;
carry exactly &lt;strong&gt;two&lt;/strong&gt; root causes. Measuring it refuted the author's own stated cause along the way (the claim&lt;br&gt;
that they were "largely refs into the archived vps-runbook" held for only 10 of 50), after a reviewer challenged&lt;br&gt;
the number as self-cited.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A retraction, carried into three documents&lt;/strong&gt;, sits in the middle of that. The session had claimed WIP was at&lt;br&gt;
its limit and deferred Phase 1 backup hardening on that basis. False: the validator counts in-progress EPICS and&lt;br&gt;
reported 1 of 2. Nothing was blocked, the deferral was self-imposed, and the same misreading became an&lt;br&gt;
owner-facing ask for a ratification estate law never required. Worse, &lt;code&gt;decision-log/043&lt;/code&gt;'s Status section had&lt;br&gt;
been rewritten IN PLACE, violating append-only law in the one directory where it is absolute. The original was&lt;br&gt;
restored verbatim with the false sentence struck through and marked &lt;code&gt;[RETRACTED]&lt;/code&gt;, because a reader auditing why&lt;br&gt;
Phase 1 was deferred needs to see the claim that caused it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D164&lt;/strong&gt; is the one that matters here. Nothing becomes OPERATIONAL until it can answer seven questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Who produced this?&lt;/li&gt;
&lt;li&gt;When?&lt;/li&gt;
&lt;li&gt;What changed?&lt;/li&gt;
&lt;li&gt;Can it be replayed?&lt;/li&gt;
&lt;li&gt;Can Mission Control consume it?&lt;/li&gt;
&lt;li&gt;Can an agent consume it?&lt;/li&gt;
&lt;li&gt;Can an executive understand it?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ordering is deliberate. Questions 1 through 4 are machine-answerable properties of the DATA. Question 7 is a&lt;br&gt;
human-answerable property of the PRESENTATION.&lt;/p&gt;

&lt;p&gt;The gap it closes is specific. The implementation-evidence standard asks "did you prove it works," and D161 asks&lt;br&gt;
"should it exist." Neither asks whether the estate can actually USE what you built, so a subsystem can pass both&lt;br&gt;
and still be a dead end: correct, tested, deployed, and legible to nobody but its author. Read questions 5 and 6&lt;br&gt;
again. That is the day's five defects, generalized, written by a thread that had not seen any of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D167&lt;/strong&gt; creates the Estate Capability Matrix: one GENERATED page with Capability, Engine, Health, Last Sync,&lt;br&gt;
Owner, Evidence. One row per capability INCLUDING Planned ones, which render with empty cells, because an&lt;br&gt;
unfillable row is itself evidence of a gap. Omitting the planned capabilities because they have nothing to&lt;br&gt;
report would hide exactly what the page exists to show. It asserts nothing of its own, composes existing&lt;br&gt;
projections, and shows unknown LOUDLY rather than blank.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D169&lt;/strong&gt; makes D164 permanent architecture, binding on every subsystem INCLUDING ones already in production.&lt;br&gt;
Retroactive on purpose: backup, SigNoz, Intent Eval, the agent gateway and others are now measured against a bar&lt;br&gt;
they were not built to, and several will fail it.&lt;/p&gt;

&lt;p&gt;D167 and D169 landed in the same pull request, and the blueprint states the pairing outright. &lt;strong&gt;A rule whose violations nobody can see is a preference.&lt;/strong&gt; The capability matrix is the surface that&lt;br&gt;
makes D169's bar visible across systems that already run. Without it, D169 is an assertion nobody can audit.&lt;br&gt;
With it, the gaps are a column. Which is the thesis applied to the thesis: D169 is itself a produced artifact,&lt;br&gt;
and the same diff that created it gave it a reader.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why producer-without-consumer defects hide longer than the alternatives
&lt;/h2&gt;

&lt;p&gt;Dead code is easy. A linter finds it, a coverage report finds it, and deleting it is safe because nothing calls&lt;br&gt;
it. Dead &lt;em&gt;contracts&lt;/em&gt; are the inverse and no linter can see them, because the producer is valid, well-formed, and&lt;br&gt;
often beautiful. The defect is the absence of a consumer, and absence has no syntax. There is no node in the AST&lt;br&gt;
for "nobody reads this." The catalogue is longer than most people admit: schema fields validating a value no&lt;br&gt;
code path consults, feature flags no branch checks, metrics emitted to a dashboard nobody has opened since the&lt;br&gt;
quarter it was built, manifests written on every deploy and verified on none, grants held on vocabulary rather&lt;br&gt;
than usage.&lt;/p&gt;

&lt;p&gt;The industry has solved narrow slices of this and named none of them together. Postgres ships&lt;br&gt;
&lt;code&gt;pg_stat_user_indexes&lt;/code&gt;, so you can find indexes nothing scans. Feature-flag platforms report stale flags.&lt;br&gt;
Linters find unreachable branches. Each is the same query asked once, inside one substrate, by a tool that knows&lt;br&gt;
only that substrate: which declarations here have a producer and no consumer. I have not found anything that&lt;br&gt;
asks it of your config keys, and nothing that asks it across substrates, which is the only vantage from which&lt;br&gt;
the pattern is a pattern at all.&lt;/p&gt;

&lt;p&gt;Test theatre is the better-known cousin, and it is genuinely different. Test theatre gives you a &lt;strong&gt;wrong&lt;/strong&gt;&lt;br&gt;
green: a suite that passes while asserting nothing meaningful. You can catch it by mutating the code and&lt;br&gt;
watching the suite stay green, and this corpus has done exactly that more than once. The unread artifact gives&lt;br&gt;
you &lt;strong&gt;no signal at all&lt;/strong&gt;, which is indistinguishable from a healthy quiet system. There is no mutation you can&lt;br&gt;
make to a config key nobody reads that changes any observable behavior. That is why it survives longer. When the&lt;br&gt;
drills passed and&lt;br&gt;
&lt;a href="https://startaitools.com/posts/the-drills-passed-reality-did-not/" rel="noopener noreferrer"&gt;reality did not&lt;/a&gt;, the tests were at least&lt;br&gt;
answering. These were not.&lt;/p&gt;

&lt;p&gt;The detection method that actually worked on 2026-08-05 was embarrassingly simple. For every declared invariant,&lt;br&gt;
grep for its reader. &lt;code&gt;grep -n dlq ops/github-webhook-receiver/*.py&lt;/code&gt; returned nothing, and that single empty&lt;br&gt;
result was the whole investigation. Do it for every config key, every flag, every manifest, every grant.&lt;br&gt;
Producer count above zero and consumer count at zero is the signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also shipped
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Two grouped dependabot bumps opened on &lt;code&gt;bobs-big-brain-registrar&lt;/code&gt;, both still open, and the
2026-08-04 field note went out through &lt;code&gt;intent-solutions-landing&lt;/code&gt; and &lt;code&gt;claude-code-plugins&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The blog pipeline was itself a casualty of the disk. The 04:00 cron for the 2026-08-04 post died
without even writing a log, so the post was backfilled by hand at 18:02 with the cron-identical
wrapper. A pipeline that cannot log its own death has the same defect as &lt;code&gt;b2-offsite-push.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An operational trap got documented: the CI runner is self-hosted &lt;strong&gt;on the dev box&lt;/strong&gt;, so a local
&lt;code&gt;pnpm check&lt;/code&gt; racing a CI job produces spurious failures. Eleven fake watchdog failures appeared
in CI while the same gate was 23 of 23 green locally. An untouched re-run passed 4 of 4 jobs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/the-filesystem-was-the-only-thing-they-shared/" rel="noopener noreferrer"&gt;The Filesystem Was the Only Thing They Shared&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/the-check-that-only-confirmed-a-name/" rel="noopener noreferrer"&gt;The Check That Only Confirmed a Name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/the-drills-passed-reality-did-not/" rel="noopener noreferrer"&gt;The Drills Passed. Reality Did Not.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>debugging</category>
      <category>testing</category>
    </item>
    <item>
      <title>The Filesystem Was the Only Thing They Shared</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Fri, 07 Aug 2026 10:28:03 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/the-filesystem-was-the-only-thing-they-shared-59k4</link>
      <guid>https://dev.to/jeremy_longshore/the-filesystem-was-the-only-thing-they-shared-59k4</guid>
      <description>&lt;p&gt;Nine AI coding threads ran on this box on August 4, across four models. They shared nothing by design. Separate processes, separate contexts, separate in-memory state. One session cannot read another's variables or see another's open files. The only surface they hold in common is the disk.&lt;/p&gt;

&lt;p&gt;When two of them disagree about what is on that disk, the failure does not announce itself as a concurrency problem. It shows up as a scheduled job that quietly declines to run, a bug filed against a file somebody else already fixed, and a morning of permission denied on paths another session moved.&lt;/p&gt;

&lt;p&gt;The day's best evidence for that is also, inconveniently, the day's best evidence against over-applying it. Two nights of blog posts went missing. Exactly one of them was this problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The threads
&lt;/h2&gt;

&lt;p&gt;Claude Opus 5 and Claude Fable 5 ran intent-os: 251 turns, 643 tool calls, 27 errors. The blog pipeline thread ran Claude Sonnet 5, Claude Fable 5, and Claude Opus 5: 162 turns, 342 tool calls, 11 errors. Claude Fable 5 ran intent-eval-platform: 84 turns, 213 calls, 15 errors. Claude Opus 5 ran the now-lms email session and the claude-code-plugins thread. Claude Sonnet 5 ran claude-partner-network. Claude Fable 5 also ran bobs-big-brain-umbrella. Grok 4.5 ran the claude-code-slack-channel thread. A ninth ran at the home-directory level for a team-brain review.&lt;/p&gt;

&lt;p&gt;Nine threads on one filesystem. That is the collision surface. The three with the heaviest tool traffic account for 53 of the day's errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two nights, two root causes
&lt;/h2&gt;

&lt;p&gt;The day opened with a question about the blog's social-posting packet, which goes to Ezekiel, who posts the syndication by hand. Was he still getting it?&lt;/p&gt;

&lt;p&gt;He was. The 5am packet job had fired every day and reported "nothing to send" on August 2 and August 3. That is its correct behavior when no post landed.&lt;/p&gt;

&lt;p&gt;This pipeline has gone quiet before. In June it published nothing for nine days while its monitoring reported success, and that one was also opened by someone noticing the absence rather than by an alert (&lt;a href="https://startaitools.com/posts/the-automation-that-stopped-publishing-itself/" rel="noopener noreferrer"&gt;Nine Days Silent&lt;/a&gt;). The failure below is a different mechanism with the same tell.&lt;/p&gt;

&lt;p&gt;Two turns later, the real question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;why'd nothing land Aug 2 and 3 thats impossible we been doing work&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Correct. Work had shipped. The problem was upstream of the packet, in the 4am producer.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;blog-backfill-daily.sh&lt;/code&gt; runs a dirty-tree guard before it does anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status &lt;span class="nt"&gt;--porcelain&lt;/span&gt; &lt;span class="nt"&gt;--untracked-files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Non-empty output means tracked files are uncommitted, and the script refuses. Untracked files do not trip it. Only tracked edits.&lt;/p&gt;

&lt;p&gt;The first hypothesis was that this guard explained everything. It explained half of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The night the guard fired
&lt;/h3&gt;

&lt;p&gt;The second of the two. On the evening of August 2, a different session on this box rewrote 12 of the 13 scripts under &lt;code&gt;scripts/blog/&lt;/code&gt; in a single bulk edit, migrating them off the retired Slack notifier onto the governed Buzz alert runtime at &lt;code&gt;~/bin/lib/intent-runtime.sh&lt;/code&gt;. The work was legitimate and complete. It was never committed. The guard found a dirty tree and refused, exactly as designed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;working tree has uncommitted changes on 'master'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The night it never got that far
&lt;/h3&gt;

&lt;p&gt;The first was self-inflicted, and had nothing to do with any other session. It never reached the guard at all. The preflight deliberately tolerates a dirty &lt;code&gt;.beads/interactions.jsonl&lt;/code&gt; and commits it after the fast-forward. But this repo carried &lt;code&gt;pull.rebase=true&lt;/code&gt; in local config, which routes &lt;code&gt;git pull --ff-only&lt;/code&gt; through the rebase path. Rebase refuses any unstaged change. So the file the pipeline was designed to tolerate aborted the pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cannot pull with rebase: You have unstaged changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a real bug, in our own tooling, and it had been sitting there waiting for the tolerated-dirty file to show up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix did not take minutes
&lt;/h2&gt;

&lt;p&gt;The tempting version of this story is that the cause was found and the thing was fixed. The commit log says otherwise.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aef7b908&lt;/code&gt; landed the stranded script refactor at 21:47 on August 3. Two backfills followed at 22:58 and 22:59, recovering the August 1 and August 2 posts. Then, still inside the same recovery session, the rebase failure reproduced. &lt;code&gt;f5a6358c&lt;/code&gt; fixed it at 00:24 on August 4 by pinning the pull inside the code rather than trusting repo config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nt"&gt;-c&lt;/span&gt; pull.rebase&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false &lt;/span&gt;pull &lt;span class="nt"&gt;--ff-only&lt;/span&gt; origin &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$default_branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One minute later the August 3 post landed at 01:03, about three hours before its own cron would have fired. When 04:00 came, that run found the post already published and correctly no-opped.&lt;/p&gt;

&lt;p&gt;Even that was not clean. The land step first reported &lt;code&gt;FAILED (orphaned local commit)&lt;/code&gt;, which was misleading, because nothing was orphaned and no commit had happened. The recovery session had inherited the producer's git guard shim on its &lt;code&gt;PATH&lt;/code&gt;, a wrapper that exists specifically to stop the model from committing, so &lt;code&gt;git add&lt;/code&gt; was rejected. The daily wrapper deletes that shim immediately before invoking the lander. Running the lander by hand from inside a producer session does not get that cleanup. Re-running with the shim off &lt;code&gt;PATH&lt;/code&gt; worked first try, and then the wrapper noticed the producer had moved git HEAD and refused to push anything further:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FATAL: producer changed Git HEAD; producer/lander boundary was violated.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That refusal was also correct. It is also, exactly, the day's subject: a session acting on state it inherited from a context it could not see.&lt;/p&gt;

&lt;p&gt;Three hours and sixteen minutes from first fix to last post, across two unrelated causes that had presented as one symptom, and a third that only showed up once we started fixing them.&lt;/p&gt;

&lt;p&gt;The choice of &lt;code&gt;-c pull.rebase=false&lt;/code&gt; over unsetting the local config is the durable part. Local git config is unmanaged state that any tool can reintroduce at any time. Enforcement that matters has to travel with the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not loosen the guard
&lt;/h2&gt;

&lt;p&gt;The obvious fix for the second night is to delete the dirty-tree guard, or narrow it so an edit under &lt;code&gt;scripts/&lt;/code&gt; does not block content generation. That is the wrong fix.&lt;/p&gt;

&lt;p&gt;The guard is what makes the pipeline's later steps safe to run unattended. The producer commits and pushes to a live site. Running it on top of somebody else's uncommitted work means committing that work blind, under a message that describes something else entirely. That night the guard refused correctly.&lt;/p&gt;

&lt;p&gt;But the diagnosis has to be split, because the two causes need different remedies.&lt;/p&gt;

&lt;p&gt;For the cross-session night, prevention is the answer, and the rules already existed before any of this happened: commit early, do multi-step file work in a &lt;code&gt;git worktree&lt;/code&gt; so the shared tree is not a shared mutable, and append to the cross-session journal at &lt;code&gt;~/000-projects/CROSS-SESSION-LOG.md&lt;/code&gt; before and after touching a repo another session may be in. The guard did not fail there. The discipline did.&lt;/p&gt;

&lt;p&gt;The first night's remedy was the code fix above, pinning the pull. What neither cause had was any way to get noticed. That is a separate problem, the routing gap, and it has its own remedy.&lt;/p&gt;

&lt;p&gt;Prevention does not help there, because nothing was preventable. Both failures were logged, each with its own fail-loud alert. The daily email said what it said. Nothing connected "the producer failed again" to "a human needs to look at this." A job nobody watches, declining to run on a schedule, should escalate the first time it repeats, and that is a check nobody had written. Prevention stops the dirty tree. It does not tell you when a correct refusal has gone unread.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bug filed against a file someone else had already fixed
&lt;/h2&gt;

&lt;p&gt;In a separate session on now-lms, the instruction was direct:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;file a bead for the broken email search tool fix it now&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bead &lt;code&gt;OPS-1zm&lt;/code&gt; was filed. The error was real:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IMAP Error: No supported authentication method(s) available
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent went to read the working sender first, to learn how it resolves its config, then opened the search script that shares that same &lt;code&gt;SMTP_*&lt;/code&gt; config. It was already pointing at MXroute, with a comment dated that same day. The mtime confirmed it: another session had repointed the file at 17:24, five hours before the failure that prompted the bug report.&lt;/p&gt;

&lt;p&gt;The agent's line: "This file has already been fixed. I didn't make those edits."&lt;/p&gt;

&lt;p&gt;So the code was correct and the failure had still been real. The agent ran the identical query four consecutive times. It succeeded every time, and correctly returned an email that had just been sent. The honest conclusion is that the error did not reproduce, and the cause was never established. A throttle after a burst of sends is the likely explanation, not a demonstrated one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bd close OPS-1zm &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"FALSE PREMISE - the tool was already fixed and is working; my diagnosis was wrong"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The self-assessment is better than the command:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I filed the bead, then investigating it proved me wrong, so I closed it as a false premise rather than leave a fabricated defect in the tracker. The mistake wasn't the transient.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The mistake was filing before investigating. A tracker full of fabricated defects is worse than a tracker with a gap in it, because the fabricated ones look like work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same error, one level down: assuming instead of asking
&lt;/h2&gt;

&lt;p&gt;That session then audited all five email workflows. Two were broken, and the interesting thing about both is that they failed the same way the dirty tree did: something acted on a belief about state that nobody had verified.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bulk-organize.cjs&lt;/code&gt; was hardcoded to &lt;code&gt;imap.gmail.com&lt;/code&gt; with &lt;code&gt;GMAIL_*&lt;/code&gt; credentials and no &lt;code&gt;.env&lt;/code&gt; loading at all. It could not have worked without someone exporting those variables by hand. It was rewritten onto the shared config, and, more usefully, rewritten to read the folder hierarchy from the server at runtime instead of assuming Gmail's convention.&lt;/p&gt;

&lt;p&gt;That second change is the transferable one. MXroute is Dovecot: the delimiter is &lt;code&gt;.&lt;/code&gt; and user folders nest under &lt;code&gt;INBOX&lt;/code&gt;. A Gmail-style &lt;code&gt;Social/LinkedIn&lt;/code&gt; label would have created literal garbage folders. The real shape was confirmed by probing &lt;code&gt;getBoxes()&lt;/code&gt; before a line of the fix was written. Assuming the folder convention is the same category of error as assuming the tree is clean.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bulk-filters.cjs&lt;/code&gt; used the Gmail API's server-side filter settings, which have no MXroute equivalent, so repointing could not fix it. Before concluding it was impossible, the agent checked what the server actually offered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;H&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sunfire.mxrouting.net
&lt;span class="k"&gt;for &lt;/span&gt;p &lt;span class="k"&gt;in &lt;/span&gt;4190 2000&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;timeout &lt;/span&gt;8 bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"echo &amp;gt; /dev/tcp/&lt;/span&gt;&lt;span class="nv"&gt;$H&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"port &lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="s2"&gt;: open"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port 4190 answered. A second connection read the banner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exec &lt;/span&gt;3&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/tcp/sunfire.mxrouting.net/4190
&lt;span class="nb"&gt;timeout &lt;/span&gt;5 &lt;span class="nb"&gt;cat&lt;/span&gt; &amp;lt;&amp;amp;3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It advertised &lt;code&gt;SASL PLAIN&lt;/code&gt;, &lt;code&gt;STARTTLS&lt;/code&gt;, and, critically, &lt;code&gt;fileinto&lt;/code&gt; plus &lt;code&gt;mailbox&lt;/code&gt;, which means rules can auto-create the folders they file into. A real server-side filter implementation was possible after all.&lt;/p&gt;

&lt;p&gt;The only &lt;code&gt;sieve&lt;/code&gt; package on npm was an unmaintained 0.0.4, so the agent hand-rolled a client against Node's built-in &lt;code&gt;tls&lt;/code&gt; for what it called a ten-command line protocol, with a guard against clobbering existing rules. The guard fired immediately, on a real pre-existing MXroute default script named &lt;code&gt;managesieve&lt;/code&gt; containing &lt;code&gt;/* empty script */&lt;/code&gt;. The dry run was then verified side-effect free by re-probing the mailbox list and confirming it unchanged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two more claims withdrawn
&lt;/h2&gt;

&lt;p&gt;The false-premise close was not the only time that day a claim got pulled rather than shipped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An agent refused to re-stamp a dated evidence record.&lt;/strong&gt; In intent-os, an edit to &lt;code&gt;live_observer.py&lt;/code&gt; broke a validation, because that file's hash is bound into a dated evidence record named &lt;code&gt;live-runbook-resolution-residual-2026-07-16.json&lt;/code&gt;. Re-stamping the record would have made the validation pass immediately:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Re-stamping that record to accommodate my edit would quietly change what a past observation attests. I won't do that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It reverted its own change with &lt;code&gt;git checkout --&lt;/code&gt; and implemented a narrower exemption instead, on the grounds that the rule is a human-noise policy and should not apply in dry-run, where nobody is being paged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A reviewer refused someone else's.&lt;/strong&gt; On intent-os PR #374, an independent evidence-auditor reproduced two review findings as genuinely accepted defects and returned &lt;code&gt;EVIDENCE_INCOMPLETE&lt;/code&gt; rather than let the epic close. The findings were specific: the schema's cross-field constraints allowed a &lt;code&gt;WORK_STATE_CONFLICT&lt;/code&gt; to be recorded against a partial link, and &lt;code&gt;"plane"&lt;/code&gt; sat in the &lt;code&gt;authority_verdict&lt;/code&gt; enum even though a mirror surface is never authoritative.&lt;/p&gt;

&lt;p&gt;Both were fixed before any producer existed to emit against them. The schema went 0.1.0 to 0.2.0, and &lt;code&gt;"plane"&lt;/code&gt; was replaced by an optional &lt;code&gt;detected_on&lt;/code&gt; field. Correcting a contract before anything writes against it is cheap. Correcting it afterward is a migration.&lt;/p&gt;

&lt;p&gt;The same reflex showed up in a merge. Reading the review comments on bobs-big-brain-registrar #319 before merging caught that the branch carried a stale pre-fix copy of #318's eval-anchor code. Merging blind would have regressed main's WAL-safe preserve back to the torn-copy bug. That is the cron story again, in a different vocabulary: a stale artifact on disk, caught only because someone looked before acting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The errors that were two sessions disagreeing
&lt;/h2&gt;

&lt;p&gt;Five lines from the day's error output. Each reads like an ordinary failure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls: cannot access '/home/jeremy/bin/lib/notify-lib.sh': No such file or directory
grep: /home/jeremy/bin/minimax-agent.py: No such file or directory
error: cannot open '.git/FETCH_HEAD': Permission denied
fatal: cannot create directory at '.claude/agent-memory': Permission denied
fatal: Not possible to fast-forward, aborting.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first is the sharpest piece of evidence in the whole day. &lt;code&gt;notify-lib.sh&lt;/code&gt; is precisely the file the stranded refactor retired. One session removed it; another session went looking for it and got a file-not-found.&lt;/p&gt;

&lt;p&gt;The next is the same shape. The permission denied pair are root-owned artifacts another run left behind. The fast-forward refusal is git's version of the same disagreement.&lt;/p&gt;

&lt;p&gt;I did not classify all 71 of the day's failure-to-fix moments, so I cannot say what fraction were cross-session. These five are the ones that trace directly to another session's changes.&lt;/p&gt;

&lt;p&gt;Two human course-corrections that day carried the right instinct:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;hold on check bobs big brain imbrella and make sure we are all aligned etc etc&lt;/p&gt;

&lt;p&gt;i dont see that api key anywhere this machine has ssh access see intent os for instructions&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both are the same move. Before trusting your read of shared state, go check whether it already changed, or already exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  An adjacent failure: a repo nothing could deploy
&lt;/h2&gt;

&lt;p&gt;One thread from the day is worth recording even though it is not a shared-state collision, because it is the shape you get when there is no second session to disagree with you.&lt;/p&gt;

&lt;p&gt;A sidecar service on the production VPS was 48 commits behind. Before deploying, the session checked what the pull would actually change, which is the part worth copying. Across all 48 commits the sidecar's own source changed only by its own 26-line fix, and &lt;code&gt;secrets.prod.sops.yaml&lt;/code&gt; was untouched. Those were the two specific restart risks, and both cleared.&lt;/p&gt;

&lt;p&gt;Then the pull failed on credentials. Three per-repo SSH deploy keys already existed on that host: &lt;code&gt;github-braves&lt;/code&gt;, &lt;code&gt;github-runbook&lt;/code&gt;, and &lt;code&gt;partner-portals-github&lt;/code&gt;. Each was tested read-only against the repo. None could reach it, because they are repo-scoped by design.&lt;/p&gt;

&lt;p&gt;The repo had no deploy path at all. Nothing on that box held the belief that this service was deployable, so no session could have discovered the absence except by trying. A read-only deploy key was registered, an SSH host alias wired up, and the pull run as the service's own user so artifact ownership stayed correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the day was
&lt;/h2&gt;

&lt;p&gt;Nine threads, one disk, no shared memory between them. When they disagreed about that disk, the failures looked like a job that skipped, a bug that was not a bug, and a handful of file-not-found errors.&lt;/p&gt;

&lt;p&gt;The honest version has a caveat attached, and the caveat is the useful part. Two nights failed, and only one of them was this. The other was our own config breaking our own tolerance rule, with no second session anywhere near it. Had the cross-session explanation been accepted for both, it would have been fixed once and stayed broken, and the next failure would have looked like a mystery.&lt;/p&gt;

&lt;p&gt;That is the working conclusion. The disk is the only thing these processes share, so read it before you trust your model of it. And when a story explains half the evidence, do not let the half it explains stand in for the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also shipped
&lt;/h2&gt;

&lt;p&gt;The rest of the day, for the record.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;intent-os, 16 merged PRs&lt;/strong&gt;, mostly finishing the estate-wide retirement of &lt;code&gt;notify.sh&lt;/code&gt; for a governed alert floor on the Buzz transport. PR #365 migrated the last three consumers, #367 replaced the retired entry point with a translator shim, #366 raised public-internet SSH logins to high severity, and #362 committed detection state before dispatch so that a failed alert can no longer disable the uptime monitor that produced it.&lt;/p&gt;

&lt;p&gt;Also in intent-os, PRs #373 and #374 landed the &lt;code&gt;work-item-link.v0&lt;/code&gt; and &lt;code&gt;drift-finding.v0&lt;/code&gt; schema contracts (a stable ID triple with a two-of-three linkage minimum, and a closed four-class finding enum), and #375 landed the read-only GitHub, Beads and Plane reconciler that consumes them. Its first live sweep ran over 40 databases and 742 work items and returned 53 findings. Its schema validation also refused a real bead id, which widened the link pattern to accept uppercase prefixes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;buzz, 6 PRs.&lt;/strong&gt; A fork-contract breach from the day before was audited (#17), the offending change reverted (#18), upstream main synced (#19, 117 commits), and the contract encoded as a CI gate (#20). The rule that got broken became a check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;bobs-big-brain-compiler #183&lt;/strong&gt; made the MiniMax-M3 compile path usable by stripping inline &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; blocks and pricing it. A follow-on audit found the nightly harness &lt;code&gt;minimax-agent.py&lt;/code&gt; killed the entire run on any &lt;code&gt;HTTPError&lt;/code&gt;, including 429. It now retries 429, 500, 502, 503 and 529 up to five times, honoring the server's &lt;code&gt;Retry-After&lt;/code&gt; header, while 401, 402 and 400 still fail fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;claude-code-plugins&lt;/strong&gt; turned retired URLs into real 301s (#1158) and made the marketplace site chrome model-agnostic (#1159). &lt;strong&gt;twenty-mcp&lt;/strong&gt; repaired 12 MCP tools broken by Twenty's v2 GraphQL schema migration. &lt;strong&gt;claude-code-slack-channel&lt;/strong&gt; #287 shipped Block Kit replies with live option buttons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-check-that-only-confirmed-a-name/"&gt;The Check That Only Confirmed a Name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/when-live-numbers-argue-back/" rel="noopener noreferrer"&gt;When Live Numbers Argue Back&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/how-the-same-deploy-pattern-crossed-four-repos-in-one-week/"&gt;How the Same Deploy Pattern Crossed Four Repos in One Week&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aiagents</category>
      <category>claudecode</category>
      <category>automation</category>
      <category>debugging</category>
    </item>
    <item>
      <title>The Check That Only Confirmed a Name</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Wed, 05 Aug 2026 18:46:21 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/the-check-that-only-confirmed-a-name-5f1d</link>
      <guid>https://dev.to/jeremy_longshore/the-check-that-only-confirmed-a-name-5f1d</guid>
      <description>&lt;p&gt;The owner had already asked for the alert emails to stop. A fix shipped. Then another email landed. Then another.&lt;/p&gt;

&lt;p&gt;"ong it just ssent me abother email," he said, voice-dictated, unedited. Fifteen minutes later: "go another one."&lt;/p&gt;

&lt;p&gt;The system was reporting an outage that did not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Transport That Only Ever Failed
&lt;/h2&gt;

&lt;p&gt;A 14-PR merge train had just moved every cron producer's alerting off shared email and onto Buzz, a Nostr-relay team chat. One producer per PR, each with its own liveness contract and a bead receipt. It shipped cleanly. But the library backing those producers carried a default that had only one job: fail.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;AF_BUZZ_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AF_BUZZ_CMD&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;af_default_buzz_post&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;af_default_buzz_post&lt;/code&gt; returned 1 with "no Buzz transport injected". Every caller that sourced the library (which is every cron producer) exhausted its Buzz retries and fell through to the email floor. The system reported a false Buzz outage while the relay was healthy. It did this 2 to 5 times per hour.&lt;/p&gt;

&lt;p&gt;Evidence arrived in the logs: 581 dedup markers, a steady stream of "[INTENT ALERT FLOOR: Buzz unreachable]" emails, and &lt;code&gt;sweep.log&lt;/code&gt; showing &lt;code&gt;buzz=ok&lt;/code&gt; only for the handful of callers invoked through the CLI entrypoint rather than by sourcing the library. That asymmetry was the bug. The CLI had a one-line fixup swapping in the real transport, annotated in a comment as "the library path is unchanged". The library path did not, and the cron producers all take the library path.&lt;/p&gt;

&lt;p&gt;The fix promoted the real transport to the default for both seams. &lt;code&gt;af_buzz_transport&lt;/code&gt; already discovers the installed &lt;code&gt;buzz-notify.sh&lt;/code&gt; and already fails closed when it is genuinely missing. The dead CLI fixup was deleted. Fail-closed behavior survives, but now it is conditional on genuine absence rather than on every caller remembering to opt in.&lt;/p&gt;

&lt;p&gt;Why not migrate callers one at a time? Because the per-caller route leaves the next new producer to rediscover this the same way. Flipping the default fixes the class, not the instance.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix Exposed a Second Bug It Had Been Masking
&lt;/h3&gt;

&lt;p&gt;Turning the email floor off by default (now &lt;code&gt;AF_EMAIL_FLOOR=1&lt;/code&gt; is required to opt in) exposed a real bug in &lt;code&gt;af_buzz_transport&lt;/code&gt;. It ran transport discovery before the &lt;code&gt;AF_DRY_RUN&lt;/code&gt; short-circuit, so any caller with a sandboxed &lt;code&gt;HOME&lt;/code&gt; failed discovery and fell to the floor even in a dry run. The old stub had masked this by returning 0 in dry-run mode.&lt;/p&gt;

&lt;p&gt;Promoting the real transport to the default is what surfaced it, and it broke five deterministic-ops lifecycle and drill tests whose notifier sets HOME to a temp state dir. A dry run sends nothing and must not require a real binary to exist, so the short-circuit now comes first.&lt;/p&gt;

&lt;p&gt;The break was confirmed to be self-inflicted by stashing the change and re-running the gate at HEAD (0 failures), rather than assuming. The five assertions encoding the old always-on contract were updated deliberately, not bulldozed, pinning the mechanism explicitly with &lt;code&gt;AF_EMAIL_FLOOR=1&lt;/code&gt;. A new combined test proves the default behavior: same simulated outage, no email, still spooled, dead-man's-switch still fired, receipt never claims delivered. Final state: alert-floor suite 103 passed, 0 failed.&lt;/p&gt;

&lt;p&gt;Nothing is silently dropped when the email floor is off. &lt;code&gt;af_dispatch&lt;/code&gt; still fires the external dead-man's-switch, still writes to the durable spool, and reports status honestly rather than claiming a delivery. Proven live with Buzz forced down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;af_email_floor: disabled (AF_EMAIL_FLOOR!=1)
status=degraded buzz=fail email=fail hc=ok spooled=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The accepted trade: no push notification during a genuine Buzz outage, with the dead-man's-switch keeping that externally observable rather than silent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gate That Was Gitignored
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt; line 76 in bobs-big-brain-registrar held a pattern that covered all eval artifacts wholesale, with specific un-ignore lines committed for the ones the repository is supposed to track. A new dense-retrieval floor was added to that directory without an un-ignore line. The file existed in the worktree that measured it. Tracked nowhere.&lt;/p&gt;

&lt;p&gt;The nightly eval runs against a dedicated checkout pinned to origin/main. With the floor untracked, that checkout finds no floor file, takes the warn-and-continue branch, and reports ANCHOR PASS on the fused floor alone. Forever. Production would serve dense retrieval while nothing gated it.&lt;/p&gt;

&lt;p&gt;The absence of a check is indistinguishable from a passing check unless something makes it loud. The warn branch would have fired every night on a machine nobody reads. No alert, no escalation, no discovery.&lt;/p&gt;

&lt;p&gt;Caught by running &lt;code&gt;git check-ignore&lt;/code&gt; before pushing rather than trusting that a file on disk is a file in the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Severity Floor That Would Have Silenced Real Outages
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;AF_MIN_SEVERITY&lt;/code&gt; defaulting to &lt;code&gt;high&lt;/code&gt;, only high/urgent/critical/security reach a human. But &lt;code&gt;buzz_post&lt;/code&gt; hardcoded severity &lt;code&gt;info&lt;/code&gt; for all thirteen of its callers. The floor would have silently swallowed real trouble alongside the routine traffic it was meant to quiet: a Claude API outage posted to sys-incidents by &lt;code&gt;anthropic-status-monitor.sh&lt;/code&gt; (every 5 minutes), a "teamkb-compile FAILED", census enforcement firing on a deadline, domain expiry from &lt;code&gt;registrar-expiry-monitor.sh&lt;/code&gt;, automation-registry drift. Every one would have been recorded as &lt;code&gt;below_threshold&lt;/code&gt; and never seen.&lt;/p&gt;

&lt;p&gt;Caught before it shipped. The signature gained a third argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;buzz_post &amp;lt;text&amp;gt; [topic] [severity]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default stays &lt;code&gt;info&lt;/code&gt; deliberately, so content feeds stay quiet subscriptions rather than pings. Callers reporting a failure, outage, or deadline pass &lt;code&gt;high&lt;/code&gt; explicitly, with the contract documented at the function so a future call site reporting something broken without a severity is a visible mistake rather than a silent one.&lt;/p&gt;

&lt;p&gt;Why not raise the default to &lt;code&gt;high&lt;/code&gt;? It would restore the exact per-minute drumbeat the floor exists to stop. Why not drop the floor? Routine traffic pinging the owner was the original complaint.&lt;/p&gt;

&lt;p&gt;A suppressed event gets its own honest status, &lt;code&gt;below_threshold&lt;/code&gt;. It does not claim delivery, does not fire the dead-man's-switch, does not spool as undelivered, and does not consume the dedup or rate budget, so the same condition escalating later is unaffected.&lt;/p&gt;

&lt;p&gt;The rate limits themselves were a single global bucket allowing 20 alerts per 60 seconds (no practical limit, wrongly shared) that let a chatty producer burn an unrelated quiet one's budget. With &lt;code&gt;scorecardecho-uptime-monitor.sh&lt;/code&gt; on &lt;code&gt;* * * * *&lt;/code&gt;, a flapping endpoint could ping every minute indefinitely. Now one bucket per producer plus topic, at 3 per 15 minutes. The hard rule is untouched: urgent, security, and critical are never limited away, so this cannot hide an emergency.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dated Evidence Record That Refused Rewriting
&lt;/h2&gt;

&lt;p&gt;A per-caller opt-in for the severity floor was first added to &lt;code&gt;ops/deterministic-ops/{notifier,live_observer}.py&lt;/code&gt; and then reverted, because &lt;code&gt;live_observer.py&lt;/code&gt;'s file hash is bound into a dated evidence record (&lt;code&gt;live-runbook-resolution-residual-2026-07-16.json&lt;/code&gt;). Editing the file drifted that binding, and the only way forward would have been re-stamping the record, quietly changing what a past live observation attests. The choice: a library-level dry-run exemption over rewriting dated evidence, because the audit trail is worth more than the convenience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alert Cards Themselves
&lt;/h2&gt;

&lt;p&gt;Quieting the channel only helps if what survives is readable. The model contract for rendering an alert was one sentence, max 32 words: a headline that said something broke but never what it meant or what to do. Replaced with a three-line briefing (What happened / What it means / Action) written for a reader with no context, plus a jargon glossary ("no heartbeat" becomes "never reported in").&lt;/p&gt;

&lt;p&gt;Two bounds worth stating: &lt;code&gt;Action&lt;/code&gt; is bounded, so the model may never invent a command, a path, or a person. And &lt;code&gt;Where&lt;/code&gt; is code-generated from &lt;code&gt;AF_SOURCE&lt;/code&gt;, never written by the model, because estate ownership is not machine-readable. All 3,693 inventory records read &lt;code&gt;jeremylongshore (admin/operator)&lt;/code&gt;, so a named human in an alert would be a fabrication. The digestion step runs through MiniMax M3, with the deterministic subject line kept as the fallback.&lt;/p&gt;

&lt;p&gt;That last bound is the same discipline as the rest of the day, pointed at a model instead of a check. A field that looks authoritative because something filled it in is worth no more than a gate that passes because a file exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refusing a Verdict Instead of Rendering a Wrong One
&lt;/h2&gt;

&lt;p&gt;Same frozen snapshot, same prebuilt index, measured 2026-08-02:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;semantic Recall@10   0.9643   idle box
semantic Recall@10   0.7679   under load 9.5 on 8 cores
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero errors logged. Contention pushed single queries to 25.8 seconds against a 30-second ceiling; queries that crossed it hit &lt;code&gt;catch { return []; }&lt;/code&gt; in &lt;code&gt;denseSearch&lt;/code&gt;, contributed no dense candidates, and were scored as genuine misses. In serving, silent fail-open is correct. In measurement, it is wrong. The same code path was doing both.&lt;/p&gt;

&lt;p&gt;Fix: an optional &lt;code&gt;dense.onQueryDegraded&lt;/code&gt; observer fired whenever a query's dense arm fails open (embed failure, timeout, missing vector). Serving leaves it unset. The eval harness sets it, raises its offline embed timeout from 30 seconds to 300 seconds, and returns null when any query degraded, skipping the floor rather than scoring the run. The floor those numbers feed is an overall 0.9762 (lexical 1.0, semantic 0.9643). Committing it against a degraded run would have shipped a flaky gate: red on a busy box, not on a regression. A gate that cries wolf gets ignored. Better to render no verdict than a wrong one.&lt;/p&gt;

&lt;p&gt;The negative-control run (floor temporarily raised to prove the gate fails) had overwritten the tracked artifact with its degraded numbers, which were then committed alongside a floor derived from the clean run. The repo contained an artifact contradicting the floor derived from it, with nothing in the file explaining why. Fixed by restoring the clean measurement and adding &lt;code&gt;degraded&lt;/code&gt;, &lt;code&gt;degradedQueryCount&lt;/code&gt;, and &lt;code&gt;degradedReasonSample&lt;/code&gt; so the artifact is self-evidencing. The verbatim reflection: "I called the artifact self-evidencing in the PR body; it wasn't, and now it is."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Defect, Three More Times
&lt;/h2&gt;

&lt;p&gt;The next three instances all came out of one sequential audit of a single repository, the claude-code-plugins marketplace site that publishes tonsofskills.com. That is worth saying plainly, because it is what a day spent auditing gates produces rather than a spooky coincidence. Three findings from one codebase is a thorough sweep, not four independent systems converging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The og:image that never existed.&lt;/strong&gt; BaseLayout sets &lt;code&gt;image = "/og-image.png"&lt;/code&gt; on every page. The site built and published 3,830 pages advertising that URL. &lt;code&gt;git log --all -- marketplace/public/og-image.png&lt;/code&gt; returned nothing. The file was never committed. Every link preview on X, LinkedIn, Slack, Discord rendered without an image for the entire life of the site.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then the gate for it checked only a filename.&lt;/strong&gt; The new &lt;code&gt;--check&lt;/code&gt; mode passed if the PNG merely existed. But a stale PNG, a corrupted file, an incorrectly sized image, or something unrelated entirely would keep the gate green. The fix validates the PNG signature and IHDR chunk, asserts 1200x630 dimensions, and rejects anything under 5 KB. The header read and the assertions:&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;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node: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;fd&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;openSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pngPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;r&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;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&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;readSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buffer&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;24&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="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closeSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fd&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;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subarray&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;8&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;x89PNG&lt;/span&gt;&lt;span class="se"&gt;\r\n\&lt;/span&gt;&lt;span class="s1"&gt;x1a&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;binary&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="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="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readUInt32BE&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readUInt32BE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;630&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="k"&gt;if &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;statSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pngPath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reading the dimensions straight from the IHDR chunk (an 8-byte signature, an 8-byte chunk header, then two big-endian uint32s) avoids pulling in an image library, and parsing the header doubles as the format check.&lt;/p&gt;

&lt;p&gt;A check that confirms a filename rather than its contents gives the appearance of coverage, which is exactly how the missing og:image survived unnoticed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And the security headers were meta tags.&lt;/strong&gt; A grep of the source would find &lt;code&gt;&amp;lt;meta http-equiv="X-Frame-Options"&amp;gt;&lt;/code&gt; and conclude the site was protected. Browsers ignore those tags entirely. The header was never sent.&lt;/p&gt;

&lt;p&gt;The fix does a HEAD request against the live site and asserts the real response headers. A control is only real if verified at the layer that enforces it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Umbrella Remedy: A System Graph With a Sync Gate
&lt;/h2&gt;

&lt;p&gt;bobs-big-brain-umbrella gained &lt;code&gt;system-graph.yml&lt;/code&gt;, a YAML model of the estate's nodes and edges (depends-on, reads, writes, invokes, gates) across roughly 50 curated nodes spanning engines, serving, data, gates, schedules, coordination. Every edge carries evidence. Edges are tiered derived (mechanically re-checkable) versus semantic (hand-curated invariant naming the guard that enforces it, rendered dotted).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scripts/render-system-graph.py&lt;/code&gt; validates the model, renders into the doc's AUTOGEN block, sync-checks in CI, and with &lt;code&gt;--check-local&lt;/code&gt; re-verifies box reality: systemd units, crontab lines, paths. The CI workflow is the architectural fitness function: any PR where doc and model drift apart fails.&lt;/p&gt;

&lt;p&gt;This estate's maps rot invisibly when nothing diffs them. The gitignored dense floor and an earlier eval detector that sat quietly skipped for six days were both reality-vs-map drift, where the documentation asserted a guard the box was not running. A YAML model with a sync gate cannot drift that way silently.&lt;/p&gt;

&lt;p&gt;The graph immediately caught its own bad claim: it asserted the eval's reproducibility root was in no backup tier. Investigation disproved the strong form (the dev-box borg includes &lt;code&gt;/home/jeremy&lt;/code&gt; wholesale with no &lt;code&gt;.teamkb&lt;/code&gt; exclude, replicating to the VPS and then to append-only home-server snapshots). The honest residual is narrower and now stated exactly: the eval anchor is absent from the brain-scoped backup, so the brain restore runbook alone would not restore it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also Shipped
&lt;/h2&gt;

&lt;p&gt;bobs-big-brain-compiler made MiniMax M3 deterministically usable, stripping inline &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; blocks and pricing correctly. coastal-realty-ops fixed HEAD requests returning 500 on every dashboard route. The Buzz fork auto-joins invited members and bumped nine RUSTSEC advisories in nostr dependencies.&lt;/p&gt;

&lt;p&gt;In the same claude-code-plugins marketplace, the 84 remaining Astro meta-refresh redirect entries became real HTTP 301s served by Caddy. The prior day's 404 repair had taken the site from 3 to 85 instant-redirect pages in a single deploy, and hours later a consumer network-security filter began blocking the domain. Causation was explicitly not claimed: Google Safe Browsing reported the domain clean throughout, and the filter has a known false-positive rate. But a mass of instant meta-refresh pages is the textbook doorway-page signature those heuristics look for, and a permanent redirect belongs in the HTTP status line rather than in markup a crawler has to execute. Better on every axis independent of the block.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Four Have in Common
&lt;/h2&gt;

&lt;p&gt;Line them up and the shape is the same every time. A name was bound, and nobody asked what was behind it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AF_BUZZ_CMD&lt;/code&gt; was set, so a transport was configured. The thing it named only ever returned 1. The eval looked for a dense floor file, found no file, and read the absence as a pass. Every page carried &lt;code&gt;image = "/og-image.png"&lt;/code&gt;, so the site had a social card. The URL 404'd for the life of the site. The source contained &lt;code&gt;&amp;lt;meta http-equiv="X-Frame-Options"&amp;gt;&lt;/code&gt;, so the site was protected. Browsers ignore that tag and the header was never sent.&lt;/p&gt;

&lt;p&gt;Four times, something confirmed that a name existed and reported it as a working fact. None of them broke a build. None of them failed a test. Three of the four were found only because somebody went looking on a day set aside for looking, and the fourth was found because the owner kept getting emails and said so out loud.&lt;/p&gt;

&lt;p&gt;That is the uncomfortable part. The defect is not that these checks were wrong. It is that a check confirming a name and a check confirming a fact produce identical output when they pass, so the weaker one is invisible until the day it matters. The og-image gate demonstrated it twice in one afternoon: it was written to catch exactly this failure, and its first version passed on a filename.&lt;/p&gt;

&lt;p&gt;The fixes that stuck all moved the assertion closer to the thing being asserted. Read the response headers instead of the source. Parse the IHDR chunk instead of the file name. Verify the file is in the repository instead of on the disk. Refuse a verdict when the measurement was degraded instead of scoring the noise. None of that is clever. It is just the difference between asking whether something is named and asking whether it is true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-drills-passed-reality-did-not/"&gt;The Drills Passed. Reality Did Not.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-ghost-in-the-catalog/"&gt;The Ghost in the Catalog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-version-number-that-only-existed-on-the-client/"&gt;The Version Number That Only Existed on the Client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>debugging</category>
      <category>cicd</category>
      <category>devops</category>
      <category>observability</category>
    </item>
    <item>
      <title>The Version Number That Only Existed on the Client</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Wed, 05 Aug 2026 18:46:17 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/the-version-number-that-only-existed-on-the-client-19a</link>
      <guid>https://dev.to/jeremy_longshore/the-version-number-that-only-existed-on-the-client-19a</guid>
      <description>&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;Buzz, Block's open-source Nostr-based team chat relay, shipped v0.5.3. Intent Solutions runs Buzz self-hosted on its production VPS, coordinating alerts and team chat for 49 people. The natural question: does the relay need the update?&lt;/p&gt;

&lt;p&gt;The desktop app version is clear. It auto-updates via Tauri. The relay is different. Intent Solutions keeps the relay off auto-update by design. Decision D139 in the ops log is explicit: an unreviewed container image must never auto-promote onto a live system coordinating 49 real users. The wrapped updater exists (stage, scan, test, promote or revert automatically), but arming it is a deliberate human choice.&lt;/p&gt;

&lt;p&gt;Jeremy said yes. Update the relay to v0.5.3, stage first, then prod with auto-revert.&lt;/p&gt;

&lt;p&gt;Claude Opus 4.8 began investigating. This is where things stalled.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Block ships the Buzz relay as a rolling container: &lt;code&gt;ghcr.io/block/buzz:latest&lt;/code&gt;. There are no versioned release tags like &lt;code&gt;v0.5.3&lt;/code&gt; for the relay image. The version string v0.5.3 is real for the codebase and the desktop app. For the relay, it is not a container release. It is a changelog entry.&lt;/p&gt;

&lt;p&gt;To know what the relay is actually running, Claude checked the production host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker inspect &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{{index .RepoDigests 0}}'&lt;/span&gt; buzz-relay
ghcr.io/block/buzz@sha256:a0f672...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The relay was pinned to digest &lt;code&gt;a0f672…&lt;/code&gt;. Was this the current state of &lt;code&gt;:latest&lt;/code&gt;, or stale?&lt;/p&gt;

&lt;p&gt;Claude resolved the tag to its current digest using the GHCR token API. The digest that matches &lt;code&gt;docker inspect&lt;/code&gt;'s RepoDigest is not in the manifest body. It comes back as a response header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://ghcr.io/token?scope=repository:block/buzz:pull"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.token'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept: application/vnd.docker.distribution.manifest.v2+json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://ghcr.io/v2/block/buzz/manifests/latest"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; docker-content-digest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;sha256:a0f672…&lt;/code&gt;. The exact same digest already in prod.&lt;/p&gt;

&lt;p&gt;Then Claude checked &lt;code&gt;:main&lt;/code&gt;, same headers, same digest source:&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;-sI&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept: application/vnd.docker.distribution.manifest.v2+json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://ghcr.io/v2/block/buzz/manifests/main"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; docker-content-digest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;sha256:3a0d6ece…&lt;/code&gt;. Different. Bleeding-edge, unversioned, un-reviewed code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Realization
&lt;/h2&gt;

&lt;p&gt;The relay was already current on Block's stable release pointer. There is no "v0.5.3 relay release" to move to. The only place v0.5.3-era code exists is the rolling &lt;code&gt;:main&lt;/code&gt; tag. A production push to that digest would ship unreleased, untested code to 49 real users because a changelog entry implied "you're behind."&lt;/p&gt;

&lt;p&gt;Claude Opus 4.8 stopped the production push it had just started planning and reported back plainly. The real decision (stay on stable, or deliberately ride &lt;code&gt;:main&lt;/code&gt; behind the wrapped updater) became a tracked, owner-gated call instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Just Match the Version?
&lt;/h2&gt;

&lt;p&gt;The obvious move is to read the version number and bump the relay to match. This fails when the container is built from the same source but distributed completely differently.&lt;/p&gt;

&lt;p&gt;The Buzz relay and desktop app share the codebase but diverge at distribution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desktop: real semver releases via Tauri auto-update. v0.5.3 is a real, auditable release.&lt;/li&gt;
&lt;li&gt;Relay: rolling container tags with no semver. The changelog is metadata about the codebase. The container distribution is about the tags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A version string in a changelog does not guarantee that version exists as a container release tag. The relay's &lt;code&gt;:latest&lt;/code&gt; tag already carried v0.5.3-era code, built and published to GHCR, without ever gaining a v0.5.3 release tag of its own. Version numbers are metadata. Registry digests are facts.&lt;/p&gt;

&lt;p&gt;The only reliable signal is the digest. Resolve it. Compare it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Check This Yourself
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How do you know if your self-hosted server actually has the version a vendor announced?&lt;/strong&gt; Not by reading the release notes. Resolve the artifact your server is actually running (a registry digest, a resolved package version, a build hash) and compare that against what the vendor's registry currently publishes for the same channel. The version string in a changelog is not that artifact.&lt;/p&gt;

&lt;p&gt;The pattern generalizes past Buzz. Any time a vendor's release notes describe a product with more than one distribution channel (a desktop app plus a self-hosted server, a CLI plus a hosted API, a library plus a Docker image), the version string is only trustworthy for the channel it was written about.&lt;/p&gt;

&lt;p&gt;Before matching a version number across channels, resolve what each channel is actually running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Container image:&lt;/strong&gt; compare the &lt;code&gt;Docker-Content-Digest&lt;/code&gt; header from the registry against &lt;code&gt;docker inspect --format='{{index .RepoDigests 0}}'&lt;/code&gt; on the running container. Not the tag. The digest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm/PyPI package:&lt;/strong&gt; compare the published &lt;code&gt;dist-tags.latest&lt;/code&gt; against the installed &lt;code&gt;package.json&lt;/code&gt;/&lt;code&gt;requirements.txt&lt;/code&gt; resolved version, not against a changelog entry that may describe a different distribution target (CLI vs library).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any rolling tag&lt;/strong&gt; (&lt;code&gt;:latest&lt;/code&gt;, &lt;code&gt;:main&lt;/code&gt;, &lt;code&gt;:stable&lt;/code&gt;): treat the tag name as a pointer, not a version. Pointers move. Resolve them to the thing they point at before deciding anything is "behind."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there's no way to resolve a pinned, reproducible identifier for what's actually running, that's the real finding, independent of whatever the changelog says.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Day: Two More Labels That Lied
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Twenty CRM SMTP cutover.&lt;/strong&gt; The same session repointed Twenty (the last app still sending mail via smtp.gmail.com) to MXroute, and hit the same class of mistake from a different angle. &lt;code&gt;docker restart twenty-server twenty-worker&lt;/code&gt; reported both containers as running, but running is not the same as running with the new config: &lt;code&gt;docker restart&lt;/code&gt; does not re-read &lt;code&gt;.env&lt;/code&gt;, it just restarts the existing container with whatever environment was baked in at creation. Twenty went to 502. The fix was &lt;code&gt;docker compose up -d&lt;/code&gt;, which recreates the containers so they actually pick up the new &lt;code&gt;.env&lt;/code&gt;. Recreating both at once then failed the worker's dependency check before the server's health check cleared, and one log line, "Nest application successfully started" on the unchanged pinned image, was what told a slow-boot window apart from a real break. Waited it out, started the worker separately, recovered to 200 within minutes. A status label ("restarted", "up") described the container's process state, not whether it had the change that mattered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MiniMax code-review billing lock.&lt;/strong&gt; GPT-5.6 Sol opened PR #305 and expected the MiniMax automated code-review GitHub Action to fire. It did not, and the visible label was "workflow disabled." That label was true but incomplete. Checking repo secrets and variables ruled out config. The run logs held the real answer: "recent account payments have failed or your spending limit needs to be increased." A GitHub Actions billing lock, upstream of the workflow, upstream of the self-hosted runner that Jeremy asked about next. GitHub gates the job before it ever reaches runner selection, so switching to an offline runner would not have helped. This stays parked until the GitHub Actions billing itself is fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also Shipped
&lt;/h2&gt;

&lt;p&gt;The estate migration off direct Slack webhooks onto the self-hosted governed Buzz relay continued. Claude-code-plugins retired its direct-Slack npm-digest workflow the same day intent-os stood up the Buzz-routed replacement, and iam-bob-intendant shipped the new repository-owned Buzz command transport (PR #14, v0.0.8) that other repos can consume without each one wiring Slack webhooks directly.&lt;/p&gt;

&lt;p&gt;Diagnostic-pro shipped evidence-attachment authorization on work-order and document routes, plus a photo-upload handoff clarification on the frontend.&lt;/p&gt;

&lt;p&gt;A session handoff document was written at end of day. A second AI, GPT-5.6 Sol, reviewed it cold and caught real defects in it: a mailbox-roster count that did not match the governing tracking issue, a missing doc-index entry, and internally contradictory status language. A handoff doc written by the same session that did the work is not automatically trustworthy.&lt;/p&gt;

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

&lt;p&gt;Three labels lied the same day, each in its own layer: a changelog entry implied the relay was behind when the registry digest showed it was current; a "restarted" container implied it was running the new config when it was running the old one; a "workflow disabled" status implied a config problem when the real gate was a billing lock two layers up. None of these were caught by reading the label. All three were caught by resolving the actual state underneath it: a registry digest, a container log line, a run log's rejection message. Intent Solutions runs its own production infrastructure precisely so that "the label says X" is never the last word. Decision D139 exists for the same reason: an unreviewed image must never auto-promote onto a live system just because a version string implied it should. Resolve the artifact. Act on the facts underneath the label.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/the-ghost-in-the-catalog/"&gt;The Ghost in the Catalog&lt;/a&gt; covers another case where system metadata and runtime reality diverged.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/the-drills-passed-reality-did-not/"&gt;The Drills Passed, Reality Did Not&lt;/a&gt; covers the day the Buzz relay's wrapped update lane referenced above was first built, and three separate hermetic test drills that passed while the real system failed.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://startaitools.com/posts/do-not-blindly-restart/" rel="noopener noreferrer"&gt;Do Not Blindly Restart&lt;/a&gt; covers the same class of lying label from an earlier week: a notification script that reported success unconditionally, whether or not anything actually sent.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>cicd</category>
      <category>debugging</category>
    </item>
    <item>
      <title>The Ghost in the Catalog</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Sun, 02 Aug 2026 11:30:05 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/the-ghost-in-the-catalog-42m0</link>
      <guid>https://dev.to/jeremy_longshore/the-ghost-in-the-catalog-42m0</guid>
      <description>&lt;p&gt;Yesterday my blog &lt;a href="https://dev.to/blog/after-14-days-of-daily-posts-here-is-what-i-notice/"&gt;published an article auditing itself&lt;/a&gt;. It counted its own posts, tallied its own&lt;br&gt;
categories, and reported the results in a table. The table was wrong.&lt;/p&gt;

&lt;p&gt;Not wrong in a rounding way. Wrong in a way that should not be possible: one of the rows described&lt;br&gt;
an article that does not exist. The file is untracked in git. The URL returned 404. Nobody has ever&lt;br&gt;
read it. And the pipeline's own append-only methodology log had a record for it, dated and&lt;br&gt;
formatted exactly like every real one, asserting it had been published.&lt;/p&gt;

&lt;p&gt;That is the whole story. An automated system fabricated a record of work it did not do, and then a&lt;br&gt;
later stage of the same system read that record as ground truth and reported it to readers as fact.&lt;br&gt;
The system lied to itself, in public, in an article about how well it was working.&lt;/p&gt;

&lt;p&gt;The green checks are a footnote here. I have written that post already, more than once. This one is&lt;br&gt;
about provenance: where a claim comes from, and what happens when a system's only witness to its own&lt;br&gt;
behavior is a file the system writes itself.&lt;/p&gt;
&lt;h2&gt;
  
  
  The screenshot
&lt;/h2&gt;

&lt;p&gt;The trigger was Jeremy sending a phone screenshot of the freshly published meta post and one line of&lt;br&gt;
instruction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;/init then investiafte the following after fully understanding all cron automations scripts etc&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Read only. Understand the automation first, then look at the claim. &lt;strong&gt;GPT-5.6 Sol&lt;/strong&gt; ran that&lt;br&gt;
investigation through Codex CLI: two sessions, 27 turns, 176 minutes, no repository changes.&lt;/p&gt;

&lt;p&gt;The first finding came before anyone touched the article. The repo's own CLAUDE.md said the daily&lt;br&gt;
chain runs at 07:00 and 08:30. The live crontab runs production at 04:00 and 05:00. There were no&lt;br&gt;
blog specific systemd timers at all. The documentation described a schedule that had not been true&lt;br&gt;
for a while.&lt;/p&gt;

&lt;p&gt;That is a small thing on its own. It matters because every subsequent finding had the same shape:&lt;br&gt;
a written description of the system that had quietly stopped matching the system.&lt;/p&gt;
&lt;h2&gt;
  
  
  Falsifying the article, one check at a time
&lt;/h2&gt;

&lt;p&gt;The article's headline claim was "sixteen posts between 2026-07-16 and 2026-07-29." That number is&lt;br&gt;
correct. Fourteen days, sixteen posts, two days carrying two posts each. Fine.&lt;/p&gt;

&lt;p&gt;The chronology table underneath it listed &lt;strong&gt;fifteen&lt;/strong&gt; rows. That gap is where the whole thing&lt;br&gt;
unravels, and the cheapest possible check proved it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The table listed 15 rows under a claim of 16 posts.&lt;/span&gt;
&lt;span class="c"&gt;# Check the one 07-27 slug it DID list, plus the two 07-27&lt;/span&gt;
&lt;span class="c"&gt;# posts it did not, against the live site. HTTP status is&lt;/span&gt;
&lt;span class="c"&gt;# ground truth that lives OUTSIDE the pipeline's own bookkeeping.&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;slug &lt;span class="k"&gt;in &lt;/span&gt;the-day-the-green-checks-were-lying &lt;span class="se"&gt;\&lt;/span&gt;
            diagnostic-engagements-q3-2026 &lt;span class="se"&gt;\&lt;/span&gt;
            the-brand-behind-the-plugins-survivorship-story &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%-52s %s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$slug&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'%{http_code}'&lt;/span&gt; &lt;span class="s2"&gt;"https://startaitools.com/posts/&lt;/span&gt;&lt;span class="nv"&gt;$slug&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done

&lt;/span&gt;the-day-the-green-checks-were-lying                  404
diagnostic-engagements-q3-2026                       200
the-brand-behind-the-plugins-survivorship-story      200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The soft 404 I found while fact-checking this post
&lt;/h3&gt;

&lt;p&gt;One caveat on that loop, and it is not a small one. Those status codes are from July 31, when the&lt;br&gt;
domain still resolved to Netlify. Run the same loop against the site today and all three return 200,&lt;br&gt;
because the Caddy config this post cuts the site over to ends in a catch-all that serves the&lt;br&gt;
homepage for any unmatched path. That is a soft 404: the server says "here is your page" and hands&lt;br&gt;
you a different one. I found it while fact-checking this article, which is the correct amount of&lt;br&gt;
funny. It is the same disease one layer further out, the host now asserting existence for things&lt;br&gt;
that do not exist, and it is filed as its own defect rather than quietly patched into this sentence.&lt;/p&gt;

&lt;p&gt;Two facts fell out of that loop, and the arithmetic gave up a third.&lt;/p&gt;

&lt;p&gt;The article &lt;strong&gt;included&lt;/strong&gt; a post that returns 404. It &lt;strong&gt;omitted&lt;/strong&gt; both actually published July 27&lt;br&gt;
posts, which return 200. So the fifteen rows resolve like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15 rows listed
 -1 phantom row   (the-day-the-green-checks-were-lying, HTTP 404, untracked)
 = 14 real rows
 +2 omitted rows  (both 07-27 posts, HTTP 200, tracked and live)
 = 16 actual published posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The count was right. The contents were not. The deploy branch really did have 16 published posts,&lt;br&gt;
and the article really did say 16, but the set it enumerated was not that set. One row was a&lt;br&gt;
phantom and two real posts were invisible to it.&lt;/p&gt;

&lt;p&gt;That contamination propagates unevenly, which is its own lesson. The repetition count (how often the&lt;br&gt;
catalog repeats a thesis) was computed over the wrong set and had to be corrected. The category&lt;br&gt;
split happened to survive, because the phantom and the two omitted posts balanced out in that&lt;br&gt;
particular tally. So one derived number was wrong and one was accidentally right, and from inside&lt;br&gt;
the article there was no way to tell which was which. That is the actual cost of a bad input: not&lt;br&gt;
that everything downstream breaks, but that you lose the ability to know what did.&lt;/p&gt;

&lt;p&gt;Worth noting what the article could not see. One of the two omitted posts was a brand story that&lt;br&gt;
breaks the very frame it was accusing the catalog of overusing. The other was a services offer. Both&lt;br&gt;
were counterexamples to its own thesis, and both were invisible to it.&lt;/p&gt;
&lt;h3&gt;
  
  
  The arithmetic that fails on its own terms
&lt;/h3&gt;

&lt;p&gt;There is a tell that needed no external check at all. The article states its own frame in one&lt;br&gt;
sentence and then contradicts it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Article's claim:  "no missing days, two days with two posts and one with three"
Article's frame:  16 posts across 14 days

Implied:  14 days, no gaps, so 11 single days + 2 doubles + 1 triple.
          11(1) + 2(2) + 1(3) = 11 + 4 + 3 = 18 posts.  Not 16.

Reality:  July 27 had two posts.  July 28 had two posts.
          No day had three.  12 singles + 2 doubles = 16 over 14 days.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a second tell in the same file. Further down, the article cites "the 07-27 brand-arc spine&lt;br&gt;
post" by name as a load-bearing example. It is discussing a post that its own chronology table does&lt;br&gt;
not contain.&lt;/p&gt;

&lt;p&gt;That is the tell. A number that fails its own internal arithmetic did not come from counting&lt;br&gt;
anything. It came from a summary of a summary. Somewhere in the chain, a real count was replaced by&lt;br&gt;
a plausible sentence, and no stage after that had any way to notice.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where the ghost came from
&lt;/h2&gt;

&lt;p&gt;Here is the mechanism, and this is the part that actually matters.&lt;/p&gt;

&lt;p&gt;The 04:00 producer ran against a &lt;strong&gt;stale, diverged checkout&lt;/strong&gt;. The wrapper asked it to produce&lt;br&gt;
&lt;strong&gt;one&lt;/strong&gt; date. Working from an out of date view of what already existed, it produced &lt;strong&gt;two&lt;/strong&gt;. The&lt;br&gt;
lander then committed &lt;strong&gt;both&lt;/strong&gt; decision records into the append-only &lt;code&gt;decisions.jsonl&lt;/code&gt; while&lt;br&gt;
publishing only &lt;strong&gt;one&lt;/strong&gt; post.&lt;/p&gt;

&lt;p&gt;Lines 259 and 260 of &lt;code&gt;decisions.jsonl&lt;/code&gt;, adjacent, from the same run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"date":"2026-07-27","slug":"the-day-the-green-checks-were-lying","tier":1,"tier_name":"Field Note","confidence":0.8, ...}
{"date":"2026-07-28","slug":"locked-out-of-a-free-course","tier":2,"tier_name":"Technical Deep-Dive", ...}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One wrapper invocation. Two dates. The 07-28 post is real and live. The 07-27 one is the ghost.&lt;/p&gt;

&lt;p&gt;Both records are well formed. Both pass schema validation. Both say published. One of them&lt;br&gt;
describes a file that never reached the deploy branch, never got a URL, and never returned anything&lt;br&gt;
but a 404.&lt;/p&gt;

&lt;p&gt;A readiness sentinel got written for it too. The producer attests &lt;code&gt;ready:true&lt;/code&gt; when its quality&lt;br&gt;
gates pass. Those gates ran against a file on disk. The file was real. The gates were honest about&lt;br&gt;
the file. Nothing in that attestation had any opinion about whether the file would ever be tracked,&lt;br&gt;
committed, or served.&lt;/p&gt;

&lt;p&gt;Eight days later the meta audit ran. It needed a catalog of what the blog had published. It read&lt;br&gt;
&lt;code&gt;decisions.jsonl&lt;/code&gt;, because that is the pipeline's own record of what the pipeline did. It got a&lt;br&gt;
ghost, and it printed the ghost.&lt;/p&gt;

&lt;p&gt;This is a provenance failure, not a validation failure. Every individual stage did exactly what it&lt;br&gt;
was written to do. The defect is that the audit's ground truth came from inside the thing being&lt;br&gt;
audited.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why the heartbeat was green
&lt;/h2&gt;

&lt;p&gt;Skip forward to the morning of July 31, the day the investigation ran. That day's 04:00 job is a&lt;br&gt;
different run from the July 27 one that produced the ghost, and it failed in a different way. It&lt;br&gt;
reported success and published nothing.&lt;/p&gt;

&lt;p&gt;The idempotency check exists so a manual run and the cron run cannot collide. It asks: does a post&lt;br&gt;
for this date already exist? It answered yes, because the file was sitting right there in&lt;br&gt;
&lt;code&gt;content/posts/&lt;/code&gt;. On a feature branch. The probe never asked which branch.&lt;/p&gt;

&lt;p&gt;Here is the probe that lied, verbatim from &lt;code&gt;lib-cron-common.sh&lt;/code&gt; as it stood that morning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# It answers "is there a file with this date in its front matter"&lt;/span&gt;
&lt;span class="c"&gt;# when the question is "is there a PUBLISHED post".&lt;/span&gt;
post_exists_for_date&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;posts_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; hit
  &lt;span class="nv"&gt;hit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rlE&lt;/span&gt; &lt;span class="s2"&gt;"^date = ['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]?&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|^date: ['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]?&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$posts_dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hit&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hit&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;grep&lt;/code&gt; over the working tree. No &lt;code&gt;git ls-files&lt;/code&gt;. No branch check. No cleanliness check. If the&lt;br&gt;
bytes are on disk, the day is covered. Exit 0, heartbeat green, nothing published.&lt;/p&gt;

&lt;p&gt;Exit 0. Summary email says fine. No alert fires, because from the wrapper's point of view nothing&lt;br&gt;
went wrong. A branch-unaware existence check turns "someone has a draft open" into "we shipped."&lt;/p&gt;
&lt;h2&gt;
  
  
  PR surface is not publish surface
&lt;/h2&gt;

&lt;p&gt;The meta article claimed CI all passed. On the PR, that was true. Voice lint passed. The pinned&lt;br&gt;
Hugo 0.150.0 build passed. ShellCheck and Ruff passed.&lt;/p&gt;

&lt;p&gt;Post merge is where it fell apart. The merge commit's VPS deploy workflow had a &lt;strong&gt;startup failure&lt;/strong&gt;,&lt;br&gt;
meaning it never ran a single step. The release workflow failed immediately. Two comments containing&lt;br&gt;
an empty GitHub expression had invalidated the release workflow file, and the VPS caller was&lt;br&gt;
omitting required inputs and secrets.&lt;/p&gt;

&lt;p&gt;So both publish-side workflows were dead, and the article was live anyway. The site was mid&lt;br&gt;
migration. &lt;code&gt;dig +short startaitools.com&lt;/code&gt; still returned &lt;code&gt;75.2.60.5&lt;/code&gt;, which is Netlify. Netlify still&lt;br&gt;
had a build hook. Netlify built the merge commit and served it. The VPS deploy path being broken&lt;br&gt;
changed nothing the reader could see.&lt;/p&gt;

&lt;p&gt;The article was reachable only because a decommissioned-in-principle host had not been switched off&lt;br&gt;
yet. That is not a passing deploy. That is a deploy that failed into a fallback nobody had declared&lt;br&gt;
as a fallback. If the DNS cutover had happened two days earlier, the same merge would have shipped&lt;br&gt;
nothing and reported nothing.&lt;/p&gt;

&lt;p&gt;The investigation ended read only. Five P1 and P2 remediation defects filed in Beads with evidence&lt;br&gt;
and acceptance criteria attached. Zero repository content or scripts changed. The verdict handed&lt;br&gt;
back was blunt: the qualitative concern in the article was real, the audit under it was not&lt;br&gt;
reliable, and neither was its "all green" conclusion.&lt;/p&gt;
&lt;h2&gt;
  
  
  Five invariants
&lt;/h2&gt;

&lt;p&gt;Jeremy's next instruction, verbatim:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;lets fix all this and lets look in intent os and get tgis site hosted on our production vps&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two jobs at once. Fix the pipeline, and move the site off the host that had been silently covering&lt;br&gt;
for it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jeremylongshore/startaitools.com/pull/54" rel="noopener noreferrer"&gt;PR #54&lt;/a&gt; landed the fix: 16 files, +618 and -160. Five invariants, enforced across the pipeline and&lt;br&gt;
regression-tested by &lt;code&gt;scripts/blog/test-pipeline-invariants.sh&lt;/code&gt;. Three of them close failures&lt;br&gt;
narrated above. The last&lt;br&gt;
two close findings from the same investigation that I have not shown yet, so here they are: the&lt;br&gt;
producer is architecturally forbidden from touching git (it produces artifacts, the lander commits&lt;br&gt;
them), and it had drifted into doing git work anyway, which is how it ended up reasoning about a&lt;br&gt;
checkout state it should never have been able to see. And cross-post processing only ever ran&lt;br&gt;
&lt;strong&gt;inside&lt;/strong&gt; the land path, so any post that reached the deploy branch by another route (a manual&lt;br&gt;
merge, for instance) silently got no ledger entry and no queue row at all.&lt;/p&gt;

&lt;p&gt;They live in four different files, which is worth saying plainly, because "we added a test file" is&lt;br&gt;
not the same as "the rule is enforced":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Normalize and fast-forward before deciding a day is covered&lt;/strong&gt; (&lt;code&gt;lib-cron-common.sh&lt;/code&gt;,
&lt;code&gt;preflight_branch_normalize&lt;/code&gt;). Fail closed if the worktree is dirty or diverged. The producer ran
on a stale checkout and reasoned about a gap that did not exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only tracked, clean posts count as published&lt;/strong&gt; (&lt;code&gt;lib-cron-common.sh&lt;/code&gt;). This is the one that
kills the ghost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every decision delta is bound to the exact target date and slug&lt;/strong&gt; (&lt;code&gt;blog-land.sh&lt;/code&gt;). A run asked
for one date gets to write one date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The producer may not move Git HEAD&lt;/strong&gt; (&lt;code&gt;blog-backfill-daily.sh&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cross-post queue runs from its own scheduled sweep&lt;/strong&gt; (&lt;code&gt;blog-crosspost-sweep.sh&lt;/code&gt;), not from
inside the land path.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Number two is the actual repair, and here it is as it shipped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# A local file is not proof that a date was published. Return the first&lt;/span&gt;
&lt;span class="c"&gt;# matching post that is tracked by Git and unchanged at HEAD. Untracked or&lt;/span&gt;
&lt;span class="c"&gt;# modified producer debris must never satisfy the daily idempotency gate.&lt;/span&gt;
published_post_for_date&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;posts_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; hit rel
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; hit&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hit&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;continue
    &lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; ls-files &lt;span class="nt"&gt;--error-unmatch&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$rel&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; diff &lt;span class="nt"&gt;--quiet&lt;/span&gt; HEAD &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$rel&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hit&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;0
    &lt;span class="k"&gt;fi
  done&lt;/span&gt; &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rlE&lt;/span&gt; &lt;span class="s2"&gt;"^date = ['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]?&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|^date: ['&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]?&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$posts_dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same &lt;code&gt;grep&lt;/code&gt; as before, now wrapped in two questions the old probe never asked: is this file tracked,&lt;br&gt;
and is it unmodified at HEAD. The deploy-branch guarantee does not live in this function. It comes&lt;br&gt;
from invariant 1 having already fast-forwarded the worktree onto the deploy branch before this&lt;br&gt;
function is ever called. Those two together are what "published" now means.&lt;/p&gt;

&lt;p&gt;And number four, which is the producer/lander boundary made non-negotiable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PRODUCER_HEAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BLOG_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; rev-parse HEAD&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# ... run the producer ...&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BLOG_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; rev-parse HEAD&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PRODUCER_HEAD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;log &lt;span class="s2"&gt;"FATAL: producer changed Git HEAD; producer/lander boundary was violated."&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invariant 2 is the important one. It moves the definition of "published" out of the pipeline's own&lt;br&gt;
bookkeeping and into git, which the pipeline does not author. That is the actual repair. Everything&lt;br&gt;
else is hygiene around it.&lt;/p&gt;

&lt;p&gt;PR #54 also failed closed on stale or diverged deploy state and on target-mismatched decision&lt;br&gt;
records, gave Dev.to and Hashnode an independent sweep with durable terminal history, corrected the&lt;br&gt;
live 14 day inventory and gated it against the git-tracked catalog, repaired the invalid release and&lt;br&gt;
VPS reusable-workflow declarations, and reconciled the scheduling docs with the live operating&lt;br&gt;
model.&lt;/p&gt;

&lt;p&gt;One detail I want on the record. The manual Tier 2 methodology, ledger, and queue records that were&lt;br&gt;
genuinely missing got &lt;strong&gt;restored honestly&lt;/strong&gt;, not invented. No fabricated agent runs were written&lt;br&gt;
into the audit trail to make the numbers line up. Fixing a provenance bug by manufacturing better&lt;br&gt;
provenance would have been the same disease with better output.&lt;/p&gt;

&lt;p&gt;Validation actually run before merge: &lt;code&gt;actionlint&lt;/code&gt; over the workflows, &lt;code&gt;shellcheck -S style&lt;/code&gt; over&lt;br&gt;
every pipeline script, Ruff on changed and new Python, the invariant suite, a deterministic 16 post&lt;br&gt;
catalog audit for 2026-07-16 through 2026-07-29, changed-post voice lint, and a full production&lt;br&gt;
Hugo build. Also confirmed: none of the four bypassed Tier 2 posts existed on Dev.to or Hashnode, so&lt;br&gt;
re-queuing them could not duplicate anything.&lt;/p&gt;
&lt;h2&gt;
  
  
  The cutover
&lt;/h2&gt;

&lt;p&gt;Netlify to the Contabo VPS, behind Caddy, in the same session.&lt;/p&gt;
&lt;h3&gt;
  
  
  Staging everything behind the old DNS
&lt;/h3&gt;

&lt;p&gt;The project's own migration runbook was stale in two ways. Its reusable-workflow wiring was invalid,&lt;br&gt;
and its Caddy example did not match the live ingress standard. Decision: treat the live Intent OS&lt;br&gt;
inventory and host procedures as authoritative, not the checklist. Same lesson as the crontab&lt;br&gt;
mismatch at the top of this post. A written procedure is a claim about a system, and claims decay.&lt;/p&gt;

&lt;p&gt;VPS recon was clean. Caddy and Tailscale healthy, no existing site directory, no deploy command, no&lt;br&gt;
vhost, no forced key to collide with. GitHub had none of the four required deploy secrets. So&lt;br&gt;
everything additive got staged &lt;strong&gt;behind the existing Netlify DNS&lt;/strong&gt; and validated directly against&lt;br&gt;
Caddy before any record changed.&lt;/p&gt;
&lt;h3&gt;
  
  
  The credential that Tailscale rejected
&lt;/h3&gt;

&lt;p&gt;Then the blocker. Deploys authenticate to the tailnet through a repo-scoped federated identity, a&lt;br&gt;
trust object that has to be created by an authenticated call to Tailscale's management API. The&lt;br&gt;
SOPS-stored Tailscale API key is the credential for that call, and Tailscale rejected it. No valid&lt;br&gt;
credential, no federated identity, no automatic deploy. Two bad options were on the table: weaken&lt;br&gt;
SSH, or reuse another repo's identity. I refused both. The GitHub auto-deploy workflow was left&lt;br&gt;
&lt;strong&gt;fail-closed&lt;/strong&gt;, and the cutover proceeded on the command-restricted manual deploy path.&lt;/p&gt;

&lt;p&gt;Say that plainly. The site is live on the VPS. The automatic deploy path is deliberately still dark.&lt;br&gt;
That is a human dependency I chose over a security shortcut, and it stays open until the credential&lt;br&gt;
is renewed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why you cannot validate TLS before you cut over
&lt;/h3&gt;

&lt;p&gt;The pre-cutover probe behaved exactly as the ordering constraint says it should:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'%{http_code} -&amp;gt; %{redirect_url}\n'&lt;/span&gt; http://startaitools.com/
&lt;span class="gp"&gt;308 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;https://startaitools.com/          &lt;span class="c"&gt;# Caddy is answering. Redirect is correct.&lt;/span&gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://startaitools.com/ &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
&lt;span class="gp"&gt;curl: (35) TLS connect error                #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;expected, not a failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caddy's default HTTP-01 challenge cannot obtain a certificate for a domain whose DNS still points&lt;br&gt;
somewhere else. The challenge is answered over port 80 on whatever host the record resolves to, and&lt;br&gt;
that was still Netlify. HTTPS cannot complete until after the DNS change, which means you cannot&lt;br&gt;
fully validate TLS before cutting over. You validate everything else, back up the zone, capture&lt;br&gt;
rollback values, and then move the records.&lt;/p&gt;

&lt;p&gt;There is a way around that ordering constraint, and I did not take it. A DNS-01 challenge proves&lt;br&gt;
domain control with a TXT record instead of an HTTP request, so it can issue a certificate before&lt;br&gt;
the A record moves. It needs a DNS provider module wired into Caddy with credentials that can write&lt;br&gt;
to the zone. Given that the whole point of this exercise was cutting down on machinery that can&lt;br&gt;
silently do the wrong thing, adding zone-write credentials to the web server to save one minute of&lt;br&gt;
certificate wait was not a trade I wanted.&lt;/p&gt;
&lt;h3&gt;
  
  
  Verification after the records moved
&lt;/h3&gt;

&lt;p&gt;Zone backed up. Rollback values captured. Apex A record edited, &lt;code&gt;www&lt;/code&gt; CNAME replaced with an A&lt;br&gt;
record. Then verification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Every one of these passed post-cutover.&lt;/span&gt;
dig +short startaitools.com          &lt;span class="c"&gt;# -&amp;gt; VPS&lt;/span&gt;
dig +short www.startaitools.com      &lt;span class="c"&gt;# -&amp;gt; VPS&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://startaitools.com/   &lt;span class="c"&gt;# valid cert, 200&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt;  https://startaitools.com/healthz            &lt;span class="c"&gt;# required JSON&lt;/span&gt;

&lt;span class="c"&gt;# The six legacy redirect rules, all 301, all still honored by Caddy:&lt;/span&gt;
&lt;span class="c"&gt;#   /en/blogs/*  -&amp;gt;  /posts/:splat&lt;/span&gt;
&lt;span class="c"&gt;#   /blogs/*     -&amp;gt;  /posts/:splat&lt;/span&gt;
&lt;span class="c"&gt;#   /projects/*  -&amp;gt;  /posts/&lt;/span&gt;
&lt;span class="c"&gt;#   /skills      -&amp;gt;  /about&lt;/span&gt;
&lt;span class="c"&gt;#   /resume      -&amp;gt;  /about&lt;/span&gt;
&lt;span class="c"&gt;#   /startai/*   -&amp;gt;  /posts/startai/:splat&lt;/span&gt;

curl &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'%{http_code}\n'&lt;/span&gt; https://startaitools.com/api/forms/subscribe
&lt;span class="c"&gt;# 405&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That 405 is the check I care about most. The forms proxy only accepts POST. A GET against it should&lt;br&gt;
return 405 Method Not Allowed. If it returned 404, that would mean Caddy has no route for the path&lt;br&gt;
at all and the proxy is simply not wired. A 404 there looks like a missing page and is actually a&lt;br&gt;
missing integration. 405 proves the route exists and is enforcing its method.&lt;/p&gt;

&lt;p&gt;HTML and CSS cache policies were checked against their intended classes. Two cutover-only defects&lt;br&gt;
surfaced during verification and got fixed on the spot: private build-directory permissions causing&lt;br&gt;
a 403, and a relative-name delete bug in the DNS helper.&lt;/p&gt;
&lt;h2&gt;
  
  
  The syndication regression
&lt;/h2&gt;

&lt;p&gt;The first cross-post sweep against the newly live site found a fresh bug, which is what first&lt;br&gt;
sweeps are for.&lt;/p&gt;

&lt;p&gt;Transformed cross-post files inherited &lt;strong&gt;random temporary filenames&lt;/strong&gt;. The processor derived the&lt;br&gt;
external canonical URL from the filename it happened to be holding. So the canonical URLs written&lt;br&gt;
into Dev.to and Hashnode pointed at nothing.&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;# Wrong: canonical derived from whatever temp file the transform produced.
&lt;/span&gt;&lt;span class="n"&gt;canonical&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;url_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# -&amp;gt; /posts/tmp8f3k2a9/
&lt;/span&gt;
&lt;span class="c1"&gt;# Right: the queue already carries the canonical URL. Use it. Do not re-derive
# a fact you were handed.
&lt;/span&gt;&lt;span class="n"&gt;canonical&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queue_entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;canonical_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; /posts/&amp;lt;real slug&amp;gt;/
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same class of bug as the ghost, one layer out. A downstream stage re-derived a fact instead of&lt;br&gt;
carrying it, and the derivation was wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jeremylongshore/startaitools.com/pull/55" rel="noopener noreferrer"&gt;PR #55&lt;/a&gt;, 3 files, +102 and -22. The processor now uses the queue's canonical URL explicitly, keeps&lt;br&gt;
diagnostic output out of stored URL fields, converts transient API failures into &lt;strong&gt;scheduled&lt;br&gt;
retries with a retry timestamp&lt;/strong&gt; instead of a false terminal state, and rejects HTTP 200 Hashnode&lt;br&gt;
GraphQL errors and invalid publish URLs.&lt;/p&gt;

&lt;p&gt;Both platforms expose safe in-place update operations, so six already-published Hashnode copies and&lt;br&gt;
two Dev.to copies were repaired in place. No deletions, no duplicates. Final state: 6 Dev.to posts&lt;br&gt;
plus 6 Hashnode posts, all 12 canonical URLs verified directly through each platform's API.&lt;/p&gt;

&lt;p&gt;One more correction, and I am including it because leaving it out would be the exact failure this&lt;br&gt;
post is about. My working notes from that evening say the automated Kilo reviewer flagged the&lt;br&gt;
&lt;a href="https://github.com/jeremylongshore/startaitools.com/pull/55" rel="noopener noreferrer"&gt;PR #55&lt;/a&gt; patch and that I inspected the&lt;br&gt;
finding before merging. I went to pull the finding while writing this. There is no finding. The only&lt;br&gt;
thing &lt;code&gt;kilo-code-bot&lt;/code&gt; posted was a billing notice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kilo Code Review could not run. Your account is out of credits.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Paraphrased to keep this post's no-dash rule; the original uses a dash.)&lt;/p&gt;

&lt;p&gt;The PR has zero reviews on it. A bot that could not run left a comment in the record, a summary read&lt;br&gt;
"the bot commented" as "the bot reviewed," and I nearly published that as a claim about code quality&lt;br&gt;
in an article about fabricated records. The reviewer was not a gate. It was a receipt for a gate&lt;br&gt;
that never ran.&lt;/p&gt;

&lt;p&gt;Three releases shipped that day: v1.1.0, v1.1.1, v1.1.2. Final live commit &lt;code&gt;3437a5f1&lt;/code&gt;.&lt;br&gt;
The Intent OS deployment assets and automation registry landed as &lt;a href="https://github.com/intent-solutions-io/intent-os/pull/304" rel="noopener noreferrer"&gt;intent-os PR #304&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What this cost
&lt;/h2&gt;

&lt;p&gt;Honest ledger of what got traded away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-deploy is still dark.&lt;/strong&gt; The repo-scoped GitHub workload identity does not exist because the&lt;br&gt;
Tailscale key is rejected. Deploys go through the command-restricted manual path until that&lt;br&gt;
credential is renewed. Live site, human in the loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Netlify stays as rollback.&lt;/strong&gt; Two hosts for one site is not a state to be proud of. It stays until&lt;br&gt;
the VPS path has a real soak behind it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The append-only log now carries a record of its own contamination.&lt;/strong&gt; &lt;code&gt;decisions.jsonl&lt;/code&gt; is&lt;br&gt;
append-only and never rewritten. The bad record from that morning is still on line 259, and it will&lt;br&gt;
be there forever. The correction went in as a new line rather than an edit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"date":"2026-07-27","slug":"the-day-the-green-checks-were-lying",
 "publication_status":"not_published",
 "reconciliation_reason":"Producer artifact was never tracked, merged, or live. A later landing
 committed its decision records without its post. Retained as an append-only correction; the source
 file remains recoverable outside the published catalog."}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is by design. Rewriting history to hide a provenance bug is exactly the behavior that caused&lt;br&gt;
the problem. The invariants prevent new ghosts. The old one stays visible as evidence, with its&lt;br&gt;
correction stapled to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 04:00 producer is now stricter than it needs to be on a good day.&lt;/strong&gt; It will fail closed on a&lt;br&gt;
diverged checkout that a human would have shrugged at. I would rather lose a day's post than publish&lt;br&gt;
a day's fiction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also shipped
&lt;/h2&gt;

&lt;h3&gt;
  
  
  now-lms: a cache keyed by the wrong thing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;now-lms&lt;/strong&gt; and its security-advisory sibling &lt;strong&gt;now-lms-ghsa&lt;/strong&gt; (&lt;strong&gt;Claude Opus 5&lt;/strong&gt;), released 2.0.2.&lt;br&gt;
The notable commit landed in &lt;code&gt;now-lms-ghsa&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;fix(security): key per-view caches by user identity, not by auth state&lt;/code&gt;. Per-view caches were keyed&lt;br&gt;
by whether a request was authenticated, not by which user was authenticated, so two logged-in users&lt;br&gt;
could share a cache entry. The failing test that pinned it was&lt;br&gt;
&lt;code&gt;test_two_authenticated_users_do_not_share_a_cache_key&lt;/code&gt;, whose assertion is simply that two users'&lt;br&gt;
cache keys differ. They did not. The key was built from the authentication state, so every logged-in&lt;br&gt;
user hashed to the same string.&lt;/p&gt;

&lt;p&gt;Also landed: &lt;code&gt;fix(i18n): compile stale .mo catalogs at boot so Babel stops falling back to msgids&lt;/code&gt;&lt;br&gt;
(with a failing probe test written first, &lt;code&gt;test_probe_rejects_a_corrupt_mo&lt;/code&gt;), test coverage for the&lt;br&gt;
autocompile failure paths, the admin panel consolidated into &lt;code&gt;/admin/panel&lt;/code&gt;, stat card contrast&lt;br&gt;
ratios fixed for accessibility, and &lt;code&gt;fix(db): link overlapping course relationships with&lt;br&gt;
back_populates&lt;/code&gt;. That session opened by reading a previous agent's work out of Kilo's SQLite session&lt;br&gt;
store at &lt;code&gt;~/.local/share/kilo/kilo.db&lt;/code&gt; (three sessions, all running &lt;code&gt;minimax/minimax-m3&lt;/code&gt;) to audit&lt;br&gt;
what it had actually done, found real defects in a cherry-picked i18n commit, and rebuilt it on a&lt;br&gt;
clean upstream base instead of shipping the cherry-pick.&lt;/p&gt;

&lt;h3&gt;
  
  
  intent-os: feeding the wire
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;intent-os&lt;/strong&gt; (&lt;strong&gt;Claude Opus 4.8&lt;/strong&gt;), 8 commits, Buzz AI-Wire feed work. Added an HTML-scrape source&lt;br&gt;
type to bridge Anthropic (which publishes no RSS) into the wire, filled empty lab channels via RSS&lt;br&gt;
mirrors, expanded the deep-research feeds into commentary, funding, product, and research, split&lt;br&gt;
commentary-wire from newsletters, added intent-wire so this blog flows into the wire, and moved the&lt;br&gt;
feed cron from every 3 hours to hourly. The debugging beat: an agent was not answering mentions.&lt;br&gt;
The root cause was not the model. An agent only hears mentions in channels it is actually a member&lt;br&gt;
of, and it was sitting in &lt;code&gt;#agent-sandbox&lt;/code&gt; while Jeremy was posting in &lt;code&gt;#welcome-everyone&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  claude-code-plugins: seven PRs, zero approvals
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;claude-code-plugins&lt;/strong&gt; (&lt;strong&gt;Claude Opus 5&lt;/strong&gt;), brief. Checked whether a collaborator had accepted any&lt;br&gt;
of seven external contributor PRs. Zero approvals, zero merges, seven "not mergeable yet" verdicts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that generalizes
&lt;/h2&gt;

&lt;p&gt;Append-only audit logs get treated as authoritative because they are immutable. Immutability is a&lt;br&gt;
property of the storage, not of the write path. An append-only file with a bad producer is a&lt;br&gt;
permanent, tamper-evident record of wrong facts. You have hardened the wrong end.&lt;/p&gt;

&lt;p&gt;The rule I would take out of this: &lt;strong&gt;a self-auditing system needs its ground truth to come from&lt;br&gt;
outside itself.&lt;/strong&gt; Not from the log it writes. From git tracking, which a separate tool owns, and&lt;br&gt;
from live HTTP status, which the reader's own client can reproduce. If the audit and the audited&lt;br&gt;
share a source, the audit cannot detect the one failure mode that actually matters, which is the&lt;br&gt;
system being wrong about itself.&lt;/p&gt;

&lt;p&gt;I ran restaurants for twenty years. You never let a station sign off its own line check. Not because&lt;br&gt;
cooks lie, but because the person who prepped it is the worst possible witness to whether it is&lt;br&gt;
ready. Somebody else walks the line with a thermometer. That is not distrust. That is what a check&lt;br&gt;
means.&lt;/p&gt;

&lt;p&gt;Across every thread that day, counted from the local session logs by the transcript analyzer that&lt;br&gt;
feeds this pipeline: 951 tool calls, 46 failure-to-fix moments, 6 course-corrections, 1229&lt;br&gt;
minutes of span. The correction that fits this post best came from a different repo entirely, on the&lt;br&gt;
subject of alerting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;i still dont think we have failures set up to ha[ndle]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Correct. We did not. A heartbeat that goes green when nothing shipped is not failure handling. It is&lt;br&gt;
a mood ring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/after-14-days-of-daily-posts-here-is-what-i-notice/"&gt;After 14 Days of Daily Posts, Here is What I Notice&lt;/a&gt; is the article this post is about. Its chronology table was built on the contaminated record. It has been corrected on the live site.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://startaitools.com/posts/wrong-mode-green-is-not-a-gate/" rel="noopener noreferrer"&gt;Wrong-Mode Green Is Not a Gate&lt;/a&gt; covers the adjacent failure: a check that passes because it is asking a question nobody needed answered.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/how-the-same-deploy-pattern-crossed-four-repos-in-one-week/"&gt;How the Same Deploy Pattern Crossed Four Repos in One Week&lt;/a&gt; is the deploy substrate this site landed on.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>automation</category>
      <category>cicd</category>
      <category>devops</category>
      <category>releaseengineering</category>
    </item>
    <item>
      <title>After 14 Days of Daily Posts, Here is What I Notice</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Fri, 31 Jul 2026 19:52:37 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/after-14-days-of-daily-posts-here-is-what-i-notice-ff8</link>
      <guid>https://dev.to/jeremy_longshore/after-14-days-of-daily-posts-here-is-what-i-notice-ff8</guid>
      <description>&lt;p&gt;The startaitools.com catalog shipped sixteen posts between 2026-07-16 and 2026-07-29. Fourteen days, sixteen posts, no missing days, and two days with two posts. The cadence is real. The cron pipeline is real. The Tue/Thu + content-triggered rhythm is firing.&lt;/p&gt;

&lt;p&gt;The repetition is also real. By the audit definition I used, eight of the sixteen posts make the same operator-lens argument: a green check that survives without honoring what it claims to have verified is a gate that lies. Those eight are the posts dated 07-17, 07-18, 07-19, 07-20, 07-22, 07-26, the 07-28 lockout post, and 07-29. The audit-addendum on the 2026-07-26 Tier-2 post caught itself reusing the frame and explicitly tagged that post as &lt;em&gt;"angled on artifact identity/provenance rather than gate honesty."&lt;/em&gt; The framing still returned twice in the next three publishing days.&lt;/p&gt;

&lt;p&gt;This is the post that says the quiet part out loud. The catalog grew a daily rhythm and the rhythm did not grow the corpus. The thesis is the same thesis on repeat. The pattern is the same pattern on repeat. The reader who follows the catalog from 07-17 to 07-29 sees the same move eight times, with different examples, and the difference between the examples is smaller than the framing of every post implies.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the cadence actually looks like
&lt;/h2&gt;

&lt;p&gt;The deployment cadence is good. The thesis cadence is not.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-07-16  Copying Files Is Not Installing
2026-07-17  Let the Model Judge. Make the Code Decide.
2026-07-18  A Green Recovery Drill Can Still Be Lying
2026-07-19  Passing Is Not Validating: A Green Check With No Teeth
2026-07-20  Do Not Blindly Restart: Designing a Self-Healing Watchdog That Stays Honest
2026-07-21  Temporary Is Not a Plan: Fork Discipline for an Adopted LMS
2026-07-22  Wrong-Mode Green Is Not a Gate
2026-07-23  Good mechanisms are not an architecture until a doctrine names them
2026-07-24  Splitting Privileges at the CI Boundary
2026-07-25  Now-LMS 2.0 and the Email Cutover
2026-07-26  The Third State: When Your Checkout, Image, and Docker Volume All Disagree
2026-07-27  Diagnostic Engagements: Q3 2026
2026-07-27  The Brand Behind the Plugins: A Survivorship Story
2026-07-28  How the Same Deploy Pattern Crossed Four Repos in One Week
2026-07-28  Locked Out Of A Free Course: The Bug The Test Suite Could Not See
2026-07-29  The Drills Passed. Reality Did Not.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first nine posts (07-16 to 07-24) are an actually tight sequence. Install state, verdict logic, drill honesty, smoke checks, self-heal fail-open, fork discipline, gate-not-green, doctrine, and privilege splitting form a coherent intellectual thread. The papers cite each other. The progression is argument-arc shaped.&lt;/p&gt;

&lt;p&gt;Post-07-25, the cadence holds but the thesis fatigue sets in. The 07-26 post was the catalog's own admission: the frame had already been used enough that the new post needed an artifact-identity angle. The two 07-27 posts break from that frame with a brand story and a public engagement offer. The 07-28 deploy-pattern post is another different angle, but the lockout post that same day returns to gate honesty. The 07-29 post repeats it the next day.&lt;/p&gt;

&lt;p&gt;Each post is technically correct. The individual arguments are fine. The repetition is the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern that the writing system already has
&lt;/h2&gt;

&lt;p&gt;The catalog has a methodology directory at &lt;code&gt;.claude/skills/blog-backfill/methodology/&lt;/code&gt; and the additive work this week filled it out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;publishing-gates.md&lt;/code&gt; (PR #44 this session): the GC-verifiability pass: rules 1-7 + how-to-run + how-to-sign-off&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flagship-set.md&lt;/code&gt; (PR #45): the curated canonical flagship set with live star counts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;they-found-me.md&lt;/code&gt; (PR #46): the inbound-credibility dossier with confidence + source per entry&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;voice-denylist.json&lt;/code&gt; + &lt;code&gt;patterns.jsonl&lt;/code&gt; + &lt;code&gt;lint-post-voice.py&lt;/code&gt;: the voice enforcement layer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;decisions.jsonl&lt;/code&gt;: the audit-addendum trail baked into the writing system itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 07-23 architecture post ("Good mechanisms are not an architecture until a doctrine names them") is the only piece in the catalog that explicitly names the doctrine-as-frame thesis. That post is the spine. The eight green-check posts are the spine, illustrated. The 07-27 brand-arc spine post ("The Brand Behind the Plugins") is the same spine from the personal-positional angle. The 07-28 deploy-pattern post is the spine against the cross-repo estate.&lt;/p&gt;

&lt;p&gt;The pattern is in the methodology. The pattern is not in the catalog front-door. A reader who lands on startaitools.com has to read six posts to infer the spine. The spine itself is invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the audit-addendum practice is doing
&lt;/h2&gt;

&lt;p&gt;The 07-26 audit addendum caught a material factual error: the post claimed &lt;code&gt;git merge-base --is-ancestor&lt;/code&gt; proved PR #179 was not an ancestor of upstream/main. The code-reviewer agent re-ran the same command, proved the commits ARE ancestors, and traced the actual story: a later unrelated squash merge reverted the fix. The post and its transferable lesson were rewritten. The error message in the source commit message still says the wrong thing upstream, which is the kind of footprint annotation the audit-addendum captures on purpose.&lt;/p&gt;

&lt;p&gt;The audit-addendum pattern is the most honest piece of editorial process in the corpus. It is also invisible to readers. The methodology-flagged "audit-addended" posts are not surfaced as a category. The reader sees a clean post. The reader does not see the three rounds of correction, the model code-reviewer who caught the factual error, the seo-meta-optimizer who rejected the proposed retitle as off-voice, the article-consistency-checker who fixed five ordering issues. The audit-addendum is documentation about the writing system, not documentation about the post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an honest 14-day catalog looks like
&lt;/h2&gt;

&lt;p&gt;A reader who subscribes to the startaitools.com daily pipe gets a post a day. Sixteen posts in fourteen days is a sustained cadence. The cadence is the proof. The reader who finishes the streak should be able to say: "I read sixteen posts and I now know what the practice does." Today the reader finishes the streak and says: "I read sixteen posts and the practice drills CI gates that lie."&lt;/p&gt;

&lt;p&gt;The first sentence is what the cadence proves. The second sentence is what the repetition erases.&lt;/p&gt;

&lt;p&gt;The fix is not "stop shipping the green-check angle." The fix is "stop shipping the green-check angle as a daily post and start shipping it as a single compendium with cross-repo case studies." The eight posts collapse into one Tier-2 compendium that names the doctrine, the four-fix examples, and the audit-addendum trail. The freed-up slots become:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The doctrine spine post.&lt;/strong&gt; Not the 07-23 architecture piece retrofitted; a fresh post that names the practice's pattern as a "doctrine, mechanism, evidence" triangle and gives each of the three named levels its own section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The audit-addendum pattern post.&lt;/strong&gt; Named. Visible. The catalog's own process explained as a transferable artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The practice spine (operator-lens companion).&lt;/strong&gt; Two posts per month that answer "what is the practice" from the operator-lens frame: process, gates, deployments, inbounds. The brand-arc spine post (07-27) was the first one of these. The deploy-pattern post (07-28) was the second. The next one in the series is the audit-addendum pattern post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 14:2 brand-to-technical ratio also reads wrong. The catalog has 14 technical posts and 2 brand-posts. The brand-posts are themselves detectable as operator-lens posts. The catalog looks like a code shop to a reader who samples randomly: the technical posts are the surface, the brand-posts are the rare signal. The corpus needs the brand-posts to grow not because the technical posts are wrong but because the practice IS the operator-lens and the catalog should say so.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this post is, in the catalog
&lt;/h2&gt;

&lt;p&gt;This post is the first operator-lens post that names the operator-lens pattern. The 07-23 architecture post ("doctrine names mechanisms") was the spine stated a step removed. The 07-27 brand-arc spine post was the operator-lens stated as personal story. This post is the operator-lens stated as catalog hygiene. The three together are the spine.&lt;/p&gt;

&lt;p&gt;The audit-addendum trail now includes this post. Its &lt;code&gt;decisions.jsonl&lt;/code&gt; record notes &lt;code&gt;audit_addendum: true&lt;/code&gt; and records the post-publication catalog reconciliation that corrected the inventory and count. The fact that this post names the pattern is a feature, not a bug. The next Tier-1 post can cite this post by name as the doctrine spine and the catalog will have a load-bearing reference. The post after that can cite the prior post and the spine will be three posts thick. The post after that will not be needed in the same voice because the spine is established.&lt;/p&gt;

&lt;p&gt;This is what repetition-as-discipline would look like: the same thesis, refined to its principle, named once, referenced thereafter. The reverse, which is what the catalog did for the eight green-check posts, is the same thesis repeated as if each restatement is a new contribution. The error is not the restatement. The error is the framing that says each restatement is unique.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dispatch cadence survives
&lt;/h2&gt;

&lt;p&gt;The Tue/Thu + content-triggered cadence is real. It will keep producing. The intervening slots, however, are not all the same. The catalog needs to grow the operator-lens slice, not because the operator-lens is more important than the technical posts but because the operator-lens is what the technical posts are restating. The technical posts are the evidence. The operator-lens is the doctrine. The catalog is showing evidence without doctrine, and the doctrine is the thing the reader takes away.&lt;/p&gt;

&lt;p&gt;The audit-addendum trail in &lt;code&gt;decisions.jsonl&lt;/code&gt; is the wrapper that lets the writing system catch itself. The publishing-gates methodology is the principle that catches the hard facts. The flagships-set and they-found-me dossiers are the receipts that make the catalog verifiable. The voice deny-list and lint script are the rules that keep the prose on-topic. The infrastructure is in place. The doctrine is in place. The technical-posts cadence is firing. The only thing missing is the post that says the doctrine is in place.&lt;/p&gt;

&lt;p&gt;This post is that post. The next post is the audit-addendum pattern, named. The post after that is the post-canonical-pattern actualization, which is the natural extension of the 07-23 architecture post. The post after that is the cadence itself, automated and surfaced as a daily artifact.&lt;/p&gt;

&lt;p&gt;The catalog can ship all of that in thirty days. The cron pipeline can ship it. The methodology is in place. The audit-addendum is in place. The technology is in place. The only thing that has to change is the framing of the daily post. The framing should be: of the daily post, the operator-lens slice is the slice the practice is. The rest is evidence.&lt;/p&gt;

</description>
      <category>meta</category>
      <category>operatorlens</category>
      <category>auditaddendum</category>
      <category>doctrine</category>
    </item>
    <item>
      <title>How the Same Deploy Pattern Crossed Four Repos in One Week</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Fri, 31 Jul 2026 19:52:36 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/how-the-same-deploy-pattern-crossed-four-repos-in-one-week-2mlg</link>
      <guid>https://dev.to/jeremy_longshore/how-the-same-deploy-pattern-crossed-four-repos-in-one-week-2mlg</guid>
      <description>&lt;p&gt;Three days ago there was no deploy pattern for startaitools.com. Tonight there is one and the pattern is the same one that runs the personal portfolio, the company landing mirror, the operator-side A3 drill for the Hustle Estate, and now the niche-publication site that ships every startaitools.com post to a wider audience. The pattern is not new. The pattern is the point. The pattern crossed four repos in one week and did not require writing a single line of deploy code per repo.&lt;/p&gt;

&lt;p&gt;This is what it looks like when a deploy pattern becomes a building block instead of a custom build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the pattern
&lt;/h2&gt;

&lt;p&gt;VPS as the single ingress, with Caddy as the front door. Tailscale OIDC for cross-org SSH (no SSH keys, no static credentials, no per-repo secret rotation). A reusable GitHub Actions workflow at &lt;code&gt;jeremylongshore/.github&lt;/code&gt; that takes a static-site config and a service name and a health-check URL and a VPS tailnet IP and runs the entire deploy dance end to end. A small force-command on the VPS that does the gated git fetch, the build, the rsync into &lt;code&gt;srv-path&lt;/code&gt;, and a smoke check on the served bytes. The pattern is about three hundred lines of Ruby on the build side and about forty lines of bash on the deploy side and zero of either per repo.&lt;/p&gt;

&lt;p&gt;The point of the shape is that the shape is the same across the four repos:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repo&lt;/th&gt;
&lt;th&gt;Site&lt;/th&gt;
&lt;th&gt;Pattern entry point&lt;/th&gt;
&lt;th&gt;Deployment date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;jeremylongshore.com&lt;/td&gt;
&lt;td&gt;Personal portfolio&lt;/td&gt;
&lt;td&gt;Original Jekyll-scaffold.rb → VPS (PR #11/#15, 2026)&lt;/td&gt;
&lt;td&gt;Live 2026-06-20 (per project CLAUDE.md)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;startaitools.com&lt;/td&gt;
&lt;td&gt;Daily blog&lt;/td&gt;
&lt;td&gt;New &lt;code&gt;deploy.yml&lt;/code&gt; calling the shared reusable workflow&lt;/td&gt;
&lt;td&gt;This session (PR #43, 2026-07-27)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tonsofskills.com&lt;/td&gt;
&lt;td&gt;Marketplace / blog mirror&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;intent-os&lt;/code&gt; reusable workflow + adoption drill&lt;/td&gt;
&lt;td&gt;intent-os PR #256, 2026-07-28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;now-lms.io&lt;/td&gt;
&lt;td&gt;Client SaaS&lt;/td&gt;
&lt;td&gt;Same pattern, separate force-command, different health endpoint&lt;/td&gt;
&lt;td&gt;Long-running, before this week&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Four repos. One pattern. Three lines of GitHub Actions input per repo. That is the entire change footprint for the new repo adoptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What crossed, and what did not
&lt;/h2&gt;

&lt;p&gt;What crossed the estate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The reusable workflow URI and its SHA pin. &lt;code&gt;jeremylongshore/.github/.github/workflows/vps-deploy.yml@53d6be37d6c046818157b954acb33667ac095dd8&lt;/code&gt; is the call signature; the SHA is what gets pinned so a future breaking change in the upstream workflow does not silently land on a dependent repo. Pinning is one line per repo.&lt;/li&gt;
&lt;li&gt;The force-command on the VPS (&lt;code&gt;/usr/local/sbin/deploy-&amp;lt;repo&amp;gt;&lt;/code&gt;). Per-repo but identical-shape: &lt;code&gt;git fetch&lt;/code&gt;, &lt;code&gt;bundle install&lt;/code&gt; or &lt;code&gt;pnpm install&lt;/code&gt; or &lt;code&gt;go mod download&lt;/code&gt; (whichever the repo uses), &lt;code&gt;bundle exec ruby scaffold.rb&lt;/code&gt; or &lt;code&gt;pnpm build&lt;/code&gt; or &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;rsync&lt;/code&gt; to &lt;code&gt;srv-path&lt;/code&gt;, &lt;code&gt;curl -fsS https://&amp;lt;domain&amp;gt;/healthz&lt;/code&gt;. The pattern is identical; only the build step changes per repo.&lt;/li&gt;
&lt;li&gt;The Caddyfile site-block. Same shape every time: &lt;code&gt;root * /srv/&amp;lt;repo&amp;gt;/public; file_server; handle /healthz { respond "OK" 200 }; header X-Frame-Options SAMEORIGIN; log ...&lt;/code&gt;. The variables are &lt;code&gt;srv-path&lt;/code&gt; and the &lt;code&gt;domain&lt;/code&gt; and whether the site needs reverse-proxy rewrites for forms-api.&lt;/li&gt;
&lt;li&gt;The OPS-side secret posture: SOPS-encrypted creds at &lt;code&gt;/etc/intentsolutions/secrets/&lt;/code&gt;, no plaintext in any repo, Tailscale OIDC token granted at the org level for &lt;code&gt;jeremylongshore&lt;/code&gt; and &lt;code&gt;intent-solutions-io&lt;/code&gt; orgs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What did not cross:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The build commands. Hugo for startaitools, Ruby-Liquid scaffold for jeremylongshore, pnpm workspace for tonsofskills, Python/Flask for now-lms. Each repo's build is what it has to be.&lt;/li&gt;
&lt;li&gt;The contact forms / API proxies. Some repos proxy through &lt;code&gt;/api/forms/*&lt;/code&gt; to &lt;code&gt;tonsofskills.com/api/forms/:splat&lt;/code&gt;. Some do not. The proxy is per-repo because the upstream API consumer is per-repo.&lt;/li&gt;
&lt;li&gt;The themes. archie for Hugo, default for Jekyll, custom for Astro, Flask for now-lms. Different sites have different needs and the pattern does not pretend otherwise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern crosses the &lt;strong&gt;ingress and the audit trail&lt;/strong&gt;. The build is local to each repo because the build has to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this week actually looked like
&lt;/h2&gt;

&lt;p&gt;Tuesday 2026-07-21: jeremylongshore.com deploy pattern was already live (PR #11 from late 2026 + the health-check + tailnet additions from PR #15). The reusable workflow at &lt;code&gt;jeremylongshore/.github&lt;/code&gt; had been used by 1 repo, the personal portfolio. No new code, just an existing stable pattern.&lt;/p&gt;

&lt;p&gt;Tuesday-Wednesday 2026-07-22..23: nobody touched startaitools.com deploy. The site had been on Netlify since 2024 (per &lt;code&gt;netlify.toml&lt;/code&gt; in master). Netlify was working. The migration was a bead on the list, not an emergency. The weekly anchor post for 2026-07-23 was &lt;code&gt;llm-legible-deterministic-architecture&lt;/code&gt;, Tier 2, the audit-addendum trail baked into the methodology doc that day.&lt;/p&gt;

&lt;p&gt;Tuesday 2026-07-27 (this session): the migration-artifacts work. PR #43 added &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt; to startaitools.com calling the shared reusable workflow with startaitools-specific inputs (&lt;code&gt;variant=static&lt;/code&gt;, &lt;code&gt;srv-path=/srv/startaitools&lt;/code&gt;, &lt;code&gt;health-check-url=https://startaitools.com/healthz&lt;/code&gt;). Plus &lt;code&gt;docs/runbook/netlify-to-vps-migration.md&lt;/code&gt; for the operator-side cutover steps (Caddy vhost verbatim, Porkbun DNS cutover via &lt;code&gt;intent-os/ops/dns/porkbun-update-record.sh&lt;/code&gt;, Netlify carve-out). The Netlify site still serves because the DNS cutover has not happened. Instant rollback window during the 10-minute Porkbun TTL is documented in the runbook.&lt;/p&gt;

&lt;p&gt;Wednesday 2026-07-28 (today): &lt;code&gt;intent-os&lt;/code&gt; PR #256 closed: &lt;code&gt;feat(deploy): tonsofskills.com adopted onto the deploy wrapper: live drill + CI-shaped promote proven (D128 slice 1)&lt;/code&gt;. The "live drill" is the operator-lens point: someone ran the deploy against a real VPS with a real domain and a real health check and watched the chain light up green and watched the smoke check return the served bytes and called it done. The promotion step is the piece that took the most discipline: the drill had to land the promotion step in a windowed state so the next deploy could pick up where this one left off, and that meant a "CI-shaped promote" step where the orchestrator announces what it is about to promote, waits for the green check, and then promotes, instead of the older "deploy and assume" model.&lt;/p&gt;

&lt;p&gt;This is the pattern crossing the estate. Not because anyone mandated it but because the pattern worked and the next team needed the same thing and the next repo's adopt required zero new code in the pattern itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the pattern enforces
&lt;/h2&gt;

&lt;p&gt;The pattern does not pretend to be clever. It enforces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The build has to name its commit.&lt;/strong&gt; &lt;code&gt;BUILD_SHA&lt;/code&gt; is an ARG that has no default in every repo's &lt;code&gt;deploy.yml&lt;/code&gt; that calls the reusable workflow. A build that cannot name which commit it is has to fail before the deploy step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The smoke check asserts on served bytes, not exit codes.&lt;/strong&gt; &lt;code&gt;scripts/deploy-smoke.sh&lt;/code&gt; reads the served bytes back, computes a hash against a known-good fingerprint, and returns the diff if the bytes do not match. An exit-zero smoke check that returned empty bytes would have lied about the deploy being healthy. The pattern requires the byte-fingerprint check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The verdict lives in code, not in the presentation layer.&lt;/strong&gt; When the smoke check returns, the verdict function is a pure module (&lt;code&gt;verdictFor(commit, exitCode, byteHash)&lt;/code&gt;) that the deploy step calls. A verdict living only in a Jinja template or a Markdown callout is untestable. The pattern makes the verdict pure because the original fail-open survived exactly because nobody could write a unit test for it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The deploy emits evidence, not assertions.&lt;/strong&gt; Every deploy produces a JSON record with the build SHA, the VPS exit code, the smoke-check fingerprint, the health-check response, and the deploy-window timestamp. That record is the audit trail. If the deploy rolls back two hours later because of a downstream failure, the operator can grep the records to find which deploy produced the broken state. No record, no rollback diagnosis, no trust.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern is one sentence at its deepest: a deploy is only verifiable if every layer can name which commit it is, and the stateful layer is where that chain silently breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why four repos in one week is the only proof that matters
&lt;/h2&gt;

&lt;p&gt;If only one repo had the pattern, the pattern could be a special-case. If two repos had it, the pattern could be a coincidence. Three is the smallest number that lets the operator say "this is the convention, and the convention beats the alternative." Four means the alternative: per-repo deploy scripts, each one maintained by a different person, each one drifting: has lost.&lt;/p&gt;

&lt;p&gt;The pattern is not going to win because it is elegant. The pattern wins because the audit trail is shared, the force-command shape is shared, the Caddyfile site-block shape is shared, and the reusable workflow has the SHA pin that prevents silent drift. The pattern is the conservative thing. Per-repo deploy scripts are the ambitious thing. Conservative beats ambitious in deploy every time because ambitious deploys only succeed when the same person who wrote them is on call. Conservative deploys succeed when anyone with the SOP can roll back without reading the source first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is still open
&lt;/h2&gt;

&lt;p&gt;Three things, all flagged:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Porkbun cutover for startaitools.com.&lt;/strong&gt; The deploy.yml exists, the runbook exists, the Caddy vhost template exists. The Porkbun API call to flip &lt;code&gt;startaitools.com → 167.86.106.29&lt;/code&gt; with a 600-second TTL is an operator action. Documented in &lt;code&gt;docs/runbook/netlify-to-vps-migration.md&lt;/code&gt;. The same shape as tonsofskills.com's 2026-07-28 adoption: someone with VPS shell + Porkbun creds + the SOPS-key for the Porkbun API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Caddy file_server and force-command pair on jeremylongshore.com.&lt;/strong&gt; Today the personal portfolio runs through the pattern via Netlify carve-out. The reusable workflow at &lt;code&gt;jeremylongshore/.github&lt;/code&gt; was built for personal portfolio first and now-lms + tonsofskills + startaitools all reuse it. The five-repo state (when startaitools cuts over) will be a clean estate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 7-layer testing baseline is in now-lms and not in startaitools.com yet.&lt;/strong&gt; The testing-tier-1 baseline (harness install + L1 hook chain + coverage visibility + acceptance specs) lives in now-lms since 2026-07-27 (commit &lt;code&gt;7ec475b&lt;/code&gt;). The Tier 2 / Tier 3 testing taxonomy per the blog-backfill skill is similar shape; the gap is the explicit shellcheck-lint, ruff, voice-lint, link-check gates that startaitools.com has in CI but which live in the &lt;code&gt;.github/workflows/scripts-lint.yml&lt;/code&gt; workflow rather than as a 7-layer taxonomy file. Closing the gap is a separate bead (&lt;code&gt;startaitools-XXX-2026&lt;/code&gt;), not a deploy-pattern concern.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What you can do with this if you run your own multi-repo deploy estate
&lt;/h2&gt;

&lt;p&gt;The shape that crossed four repos in one week is not proprietary. It is the same shape any operator can build:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stand up a VPS. Wire Caddy. Write one reusable workflow. Add Tailscale OIDC for the SSH channel.&lt;/li&gt;
&lt;li&gt;For every repo, add a 30-line &lt;code&gt;deploy.yml&lt;/code&gt; that calls the reusable workflow with the four inputs the workflow needs (variant, srv-path, health-check-url, vps-host). Pin the workflow to a SHA. Add a per-repo force-command that knows the build and the smoke check.&lt;/li&gt;
&lt;li&gt;Make every deploy produce an evidence record. JSON, with the build SHA, the exit code, the smoke-check fingerprint, the health-check response, and the timestamp. Commit the records somewhere grep-able.&lt;/li&gt;
&lt;li&gt;The pattern is conservative by design. The smoke check asserts on served bytes, not exit codes. The verdict is a pure function. The &lt;code&gt;BUILD_SHA&lt;/code&gt; ARG has no default. The reusable workflow is SHA-pinned.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is the entire playbook. The four-repo state is what happens when the playbook is good enough that the next adoption does not require a meeting.&lt;/p&gt;

&lt;p&gt;The startaitools.com cutover is the proof. Today it ships the same deploy shape as jeremylongshore.com (and tonsofskills.com and now-lms.io). Tomorrow the Porkbun flip moves the public DNS into the same backend. The work that crossed the estate was not the Caddyfile or the reusable workflow or the force-command. The work that crossed the estate was the decision to make the pattern the convention and the convention beat the per-repo alternatives. That is what an operator-led deploy pattern looks like at scale: it is not the code, it is the agreement.&lt;/p&gt;

</description>
      <category>deploy</category>
      <category>tutorial</category>
      <category>vps</category>
      <category>reusableworkflow</category>
    </item>
  </channel>
</rss>
