<?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>Photo to Listing: Barcode Decoding and LLM Re-rank</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Fri, 04 Sep 2026 10:35:18 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/photo-to-listing-barcode-decoding-and-llm-re-rank-1135</link>
      <guid>https://dev.to/jeremy_longshore/photo-to-listing-barcode-decoding-and-llm-re-rank-1135</guid>
      <description>&lt;p&gt;A comic shop employee photographs a back issue on a phone. The system has to come back with the right title, the right issue number, and the right variant, because a first-print variant and a common reprint of the same book are the same picture with different economics. That is the identification problem in &lt;strong&gt;intent-longbox&lt;/strong&gt;, a photo to listing pipeline that ended 2026-09-01 at v0.2.1 after eleven commits.&lt;/p&gt;

&lt;p&gt;The research that preceded the build settled the architecture in one finding: LLM vision alone is not viable for issue-exact and variant-exact identification. Every incumbent that actually works in this space runs image-similarity retrieval against a reference cover corpus. The model is a ranker, never the source of truth.&lt;/p&gt;

&lt;p&gt;So the pipeline puts the &lt;a href="https://startaitools.com/posts/llm-legible-deterministic-architecture/" rel="noopener noreferrer"&gt;deterministic parts first&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;barcode decode → candidate retrieval → LLM re-rank → human confirm → condition + price → Shopify draft
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing publishes without a person. The Shopify product lands as a DRAFT for owner review. The pilot shop is Gotham City Limit, running free.&lt;/p&gt;

&lt;p&gt;The deterministic front of that chain is a barcode parser with no model in it at all. Post-1990 comics carry a 12-digit UPC-A that identifies the series, plus a 5-digit UPC supplement encoding issue, cover variant, and printing:&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;supp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&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="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;upc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;supplement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;supp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;issue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;supp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="na"&gt;cover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;supp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;printing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;supp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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;When that supplement is readable, the variant question is already answered by arithmetic. The model never gets asked.&lt;/p&gt;

&lt;p&gt;The honest version of that diagram is that the retrieval leg is not built yet. v0 ships barcode plus vision plus human pick, with no similarity index behind the candidate step. So a barcode miss (pre-1990 stock, a damaged code, a variant with no UPC) falls to vision plus the gate below plus a mandatory human confirmation, which is the weakest path in the system and the one the pilot is meant to measure. That gap is tracked as the project's top open decision, not as a solved problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The database refuses to mutate
&lt;/h2&gt;

&lt;p&gt;Every event in a scan session is a separate immutable row, which makes the table an audit trail rather than a current-state cache. &lt;code&gt;scan_session&lt;/code&gt; is the identity. &lt;code&gt;candidate_set&lt;/code&gt; holds the deterministic result (barcode decode plus similarity k-NN, FK'd to a &lt;code&gt;corpus_version&lt;/code&gt;). &lt;code&gt;llm_rerank&lt;/code&gt; holds the probabilistic value: provider, model, prompt hash, the verbatim response, confidence, band, contradiction flag, tokens, cost. It annotates the candidate set. It cannot edit it.&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;human_confirmation&lt;/code&gt;, &lt;code&gt;condition_assessment&lt;/code&gt;, &lt;code&gt;pricing_snapshot&lt;/code&gt;, &lt;code&gt;shopify_draft&lt;/code&gt;, &lt;code&gt;cost_log&lt;/code&gt;. Every shop-scoped table carries &lt;code&gt;shop_id&lt;/code&gt;. The only UPDATE anywhere in the codebase is on &lt;code&gt;scan_session.status&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The obvious way to enforce append-only is code discipline. Write no UPDATE statements, review for them, move on. I rejected that, because it holds exactly as long as every future query is well behaved. A migration script, a hotfix, or one psql session at two in the morning ends the guarantee quietly, and the tell is that the audit trail looks fine afterward.&lt;/p&gt;

&lt;p&gt;So the rule lives in the database:&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;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;forbid_mutation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="k"&gt;trigger&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="n"&gt;RAISE&lt;/span&gt; &lt;span class="n"&gt;EXCEPTION&lt;/span&gt; &lt;span class="s1"&gt;'table % is append-only (Hickey model): % not allowed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TG_TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TG_OP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt; &lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="n"&gt;plpgsql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;DO&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="n"&gt;FOREACH&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;ARRAY&lt;/span&gt; &lt;span class="n"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'corpus_version'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'scan_photo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'candidate_set'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'llm_rerank'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'human_confirmation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'condition_assessment'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'pricing_snapshot'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'shopify_draft'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'cost_log'&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;
    &lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s1"&gt;'CREATE TRIGGER %I_append_only BEFORE UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION forbid_mutation()'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verified against a real Postgres, not asserted in a comment. An UPDATE on &lt;code&gt;cost_log&lt;/code&gt; raises &lt;code&gt;table cost_log is append-only (Hickey model)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One more schema decision belongs here. Condition is a grade range label, and no numeric grade type exists anywhere in the schema, the API, the prompts, or the UI copy:&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="n"&gt;grade_range_low&lt;/span&gt;  &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grade_range_low&lt;/span&gt;  &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'PR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'FR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'GD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'VG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'FN'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'VF'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'NM'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="n"&gt;grade_range_high&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grade_range_high&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'PR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'FR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'GD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'VG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'FN'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'VF'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'NM'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 9.4 is a claim a phone photo does not entitle anyone to make. If the type does not exist, nobody adds it later under deadline pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The evidence contradiction gate
&lt;/h2&gt;

&lt;p&gt;Confidence scores from a model are self-reported. Asking for one and thresholding on it is the cheap version of a quality gate, and it fails in the direction you care about, because a model is most fluent when it is wrong about a plausible thing.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;VisionProvider&lt;/code&gt; interface therefore requires structured evidence alongside the answer:&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="cm"&gt;/** REQUIRED structured evidence. The contradiction gate's raw material (R7). */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Evidence&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;issue_number_read&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nl"&gt;price_box_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nl"&gt;logo_era_guess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prompt states the same requirement in the model's own terms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- evidence fields are REQUIRED: report exactly what you can read on the cover
  (issue number printed, cover price box text, publisher logo era guess).
  Use null only when genuinely unreadable.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now there is something to check. &lt;code&gt;src/services/rerank.ts&lt;/code&gt; cross-validates each field against the top candidate's metadata. Issue number read against the candidate's issue. Cover price against a coarse US newsstand era table. Logo era decade against the candidate year:&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price_box_text&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;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;priceMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price_box_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;¢c&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\$\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;(?:\.\d{1,2})?)&lt;/span&gt;&lt;span class="sr"&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;priceMatch&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;cents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;priceMatch&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="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;priceMatch&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;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;priceMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&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;era&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;priceEraBounds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cents&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;era&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;era&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;era&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;`price_box_text "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price_box_text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" implies ~&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;era&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;era&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, contradicts candidate year &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The era bounds are deliberately loose. The gate catches decade-scale misses and does not quibble about a two-year overlap.&lt;/p&gt;

&lt;p&gt;A contradiction then costs the model its fast path:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;applyContradiction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;band&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Band&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contradiction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Band&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;contradiction&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;band&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;band&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;high&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="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;band&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;Three bands drive the phone UI. High is a one-tap confirm. Medium is a candidate grid with a forced pick. Low is manual search. Downgrading high to medium means a confident but self-contradicting answer costs the employee one extra tap instead of putting a wrong book into inventory.&lt;/p&gt;

&lt;p&gt;The transferable piece has nothing to do with comics. Do not ask a model how sure it is. Make it report the specific things it read, then check those against something deterministic you already trust.&lt;/p&gt;

&lt;p&gt;Seeded cases in the test suite all flag and downgrade: a wrong issue number read, a twelve cent price box on a 1988 book, a 1960s logo on a modern year.&lt;/p&gt;

&lt;p&gt;The provider seam behind that gate is a &lt;a href="https://startaitools.com/posts/the-moat-is-the-trust-layer-nexus-byok-rag/" rel="noopener noreferrer"&gt;bring your own key provider architecture&lt;/a&gt; per shop, with an Anthropic adapter (Messages API, image blocks, &lt;code&gt;claude-sonnet-5&lt;/code&gt; as default and reference model) and an OpenAI-compatible adapter (chat completions, &lt;code&gt;image_url&lt;/code&gt; data URIs). Resolution order is a gateway override first, then a shop credential row whose &lt;code&gt;key_ref&lt;/code&gt; names an env var, then a global env fallback. Raw keys never enter the database, only refs to env var names. Two pieces of reliability lore carried over from the estate's existing provider registry shape in &lt;code&gt;@intentsolutions/refiner&lt;/code&gt; and the Transport seam in &lt;code&gt;@intentsolutions/jrig-cli&lt;/code&gt;: a 2048 max-output-token floor, and a parser that strips &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; blocks before it goes looking for JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  One snapshot per source, and no source can block
&lt;/h2&gt;

&lt;p&gt;The 23:56 commit added a second seam. A &lt;code&gt;PricingProvider&lt;/code&gt; declares a &lt;code&gt;source&lt;/code&gt;, a &lt;code&gt;kind&lt;/code&gt; of &lt;code&gt;live_asks&lt;/code&gt; or &lt;code&gt;historical_fmv&lt;/code&gt;, and returns comps plus a low/median/high summary plus &lt;code&gt;fetched_at&lt;/code&gt; plus a stub flag. Two adapters implement it: a new eBay Browse adapter (OAuth2 client-credentials app token, cached until near expiry, query built from title, issue number, and variant against the comics category) and PriceCharting refined behind the same interface.&lt;/p&gt;

&lt;p&gt;Two decisions in that step went against the obvious version.&lt;/p&gt;

&lt;p&gt;First, provider isolation over sequencing. Calling two pricing APIs in a row is simpler to write and means the second one never runs when the first one has a bad morning:&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;settled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getComps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shopCtx&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A failed source is reported in the outcome list with its error and writes no snapshot row, because nothing was fetched. The other source still prices the book.&lt;/p&gt;

&lt;p&gt;Second, one snapshot row per source, with the overall suggestion stamped on every row:&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="k"&gt;for &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;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;fulfilled&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`INSERT INTO pricing_snapshot
       (scan_session_id, shop_id, source, query, comps, suggested_cents, override_cents, policy_id, fetched_at)
     VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) RETURNING id`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shopId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;queryText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comps&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;suggested&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overrideCents&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="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;policyId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetched_at&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Per-source suggested prices would have been more honest-looking and worse to consume. The draft step would have needed to know which source wins before it could read a price, which is ordering ambiguity in a table that no one is allowed to correct afterward. Stamping the overall figure on every row keeps one rule for the draft step: the latest snapshot carries the price of record.&lt;/p&gt;

&lt;p&gt;Precedence is fixed rather than clever:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pickDrivingResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PricingResult&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;PricingResult&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;real&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PricingResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comps&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;historical_fmv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;real&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;
    &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;live_asks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;real&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;
    &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;real&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;Historical fair market value beats live asking prices, because an ask is a wish. When neither source has real comps, the shop's policy floor wins. The UI shows both sources side by side, highlights the driving one, and labels stubs as stubs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Governance, tests, and the release cycle
&lt;/h2&gt;

&lt;p&gt;Governance came first, at 18:07, through the &lt;code&gt;/repo-dress&lt;/code&gt; pass: LICENSE, SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md, SUPPORT.md, AGENTS.md, CI. The 18:12 commit authored the six master planning docs (business case, PRD with R1 through R20 MoSCoW-tagged, architecture, user journeys, technical spec, status) alongside the index and the project CLAUDE.md, which brought &lt;code&gt;000-docs/&lt;/code&gt; to eight filed documents with the competitor analysis and the approved build plan already in the tree. Then an isolated beads workspace with prefix &lt;code&gt;longbox&lt;/code&gt;. Five automated release commits took version.txt from v0.1.0 to v0.2.1.&lt;/p&gt;

&lt;p&gt;The API is shop-scoped by path prefix, &lt;code&gt;/api/shops/:shopId/scan-sessions&lt;/code&gt;, chosen over a header because a path is visible in logs, cacheable, and curl-friendly. Onboarding a shop is one command, &lt;code&gt;pnpm register-shop&lt;/code&gt;. Every model call writes a cost row from day one.&lt;/p&gt;

&lt;p&gt;Verification at end of day: &lt;code&gt;pnpm lint&lt;/code&gt;, &lt;code&gt;format:check&lt;/code&gt;, and &lt;code&gt;typecheck&lt;/code&gt; green. 118 unit tests, up from 92 at the core-pipeline commit. Coverage 99.67% of lines against a floor of 80. Fourteen integration and smoke tests green against a dockerized &lt;code&gt;postgres:16&lt;/code&gt;, including one that asserts two snapshot rows come out of a single price call. Migration &lt;code&gt;002&lt;/code&gt; extends the &lt;code&gt;shop_credentials.kind&lt;/code&gt; CHECK with &lt;code&gt;ebay&lt;/code&gt; and leaves &lt;code&gt;001&lt;/code&gt; untouched. &lt;code&gt;tests/TESTING.md&lt;/code&gt; was re-pinned with &lt;code&gt;audit-harness init&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not do yet
&lt;/h2&gt;

&lt;p&gt;Both pricing sources are stubs in real terms right now. PriceCharting's live field mapping needs verification the day the Premium token lands, and eBay returns a flagged stub without credentials.&lt;/p&gt;

&lt;p&gt;No similarity index exists. That is a locked decision rather than an oversight: v0 ships barcode plus vision plus human pick, and if the pilot shows real misses the plan is to buy before building. Ximilar sells a commercial comics visual-search API and a quote is pending. A self-built cover-image index would rest on a fair-use posture instead of a granted license, which is the project's top logged risk.&lt;/p&gt;

&lt;p&gt;The CI static eval regression set is a Phase 2 exit item that has not been built. The &lt;code&gt;human_confirmation&lt;/code&gt; table is designed to grow into that eval set, and it currently holds nothing. The UI &lt;code&gt;override_cents&lt;/code&gt; smoke assertion is still pending.&lt;/p&gt;

&lt;p&gt;And none of this has met a real comic. Every number above came from a test suite and a Docker container. The pilot has not run.&lt;/p&gt;

&lt;p&gt;Also shipped that day, both routine pipeline output: the blog automation dual-published the previous day's post &lt;code&gt;working-is-not-proven&lt;/code&gt; to tonsofskills.com/blog, and the comehomealabama journal published a piece on July coastal market numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why not use a vision model alone for comic identification?
&lt;/h3&gt;

&lt;p&gt;Issue-exact and variant-exact identification is retrieval work. Every incumbent that works in this space runs image similarity against a reference cover corpus, which is why the model here sits in the re-rank seat instead of the identifier seat. A first print and a common reprint of the same book are the same picture with different economics, and that difference is carried by metadata rather than by the image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should barcode decoding run before or after the vision model?
&lt;/h3&gt;

&lt;p&gt;Before. Post-1990 comics carry a 12-digit UPC-A plus a 5-digit supplement that encodes issue, cover variant, and printing, so a readable supplement answers the variant question by arithmetic and the model is never asked. Vision is the fallback for the books that arithmetic cannot reach, and today that fallback runs without a similarity index behind it.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you stop a vision model from confidently returning a wrong answer?
&lt;/h3&gt;

&lt;p&gt;Require structured evidence alongside the answer, then check that evidence against something deterministic. This pipeline asks for the issue number read, the cover price box text, and the logo era, then cross-validates each against the top candidate's metadata. A contradiction downgrades the confidence band from high to medium, which costs the employee one extra tap and keeps a wrong book out of inventory.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/building-cad-dxf-agent-from-zero-to-v010/" rel="noopener noreferrer"&gt;Shipping a CAD Agent from Zero: DXF Parsing, Edit Engines, and LLM Planner Interfaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/every-safety-gate-has-a-failure-direction/" rel="noopener noreferrer"&gt;Every Safety Gate Has a Failure Direction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/noise-robust-signed-llm-judge-evals/" rel="noopener noreferrer"&gt;Noise-Robust LLM-Judge Evals: Don't Sign a Coin Flip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>aiagents</category>
      <category>typescript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Every Claim Needs a Shipped Source and an Executable Proof</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Wed, 02 Sep 2026 14:49:15 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/every-claim-needs-a-shipped-source-and-an-executable-proof-3l0e</link>
      <guid>https://dev.to/jeremy_longshore/every-claim-needs-a-shipped-source-and-an-executable-proof-3l0e</guid>
      <description>&lt;p&gt;I told GPT 5.6 Luna, running through Codex, to &lt;code&gt;finish teh epics and beads&lt;/code&gt; on the plugins repo. It ran for about 361 minutes across 2 sessions and 187 turns, and it closed nothing. No file mutated, no Beads record touched, no GitHub state changed. Its closing line was that the worktree was clean at &lt;code&gt;origin/main&lt;/code&gt; &lt;code&gt;3c5be4a5981ed5089deedff53d18136b9848a18c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is not a failure report. Asked to finish three epics, the honest deliverable turned out to be an inventory of what "finished" would actually require, and the five open beads had five different meanings of "not done". Two of them are closable by writing code. The other three need an owner clicking a setting, a calendar to run out, and a record corrected to match reality.&lt;/p&gt;

&lt;p&gt;The same gap kept showing up until the day ended, and three of the day's fixes were to &lt;a href="https://startaitools.com/posts/a-green-result-only-covers-what-it-ran/" rel="noopener noreferrer"&gt;proof machinery that could not be trusted&lt;/a&gt; about its own state: a gate runner manufacturing false failures, a render check poisoned by its own output, and a liveness marker that could not tell quiet from dead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five ways a finished feature is still not done
&lt;/h2&gt;

&lt;p&gt;The audit read Epics 6, 7 and 10 against Blueprint 727, the live Beads Dolt database, &lt;code&gt;origin/main&lt;/code&gt; code, tests, workflows, branches and PRs. Read-only throughout. What came back was a taxonomy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code live, acceptance failing at the platform.&lt;/strong&gt; &lt;code&gt;claude-nfzl.6&lt;/code&gt; ships in &lt;code&gt;242d8e051&lt;/code&gt;: &lt;code&gt;validate-plugins.yml&lt;/code&gt;, &lt;code&gt;check-marketplace-compliance-baseline.py&lt;/code&gt;, &lt;code&gt;.github/CODEOWNERS&lt;/code&gt;, and 13 focused tests. Then &lt;code&gt;gh api repos/.../branches/main/protection&lt;/code&gt; returns &lt;code&gt;required_approving_review_count=0&lt;/code&gt; and &lt;code&gt;require_code_owner_reviews=false&lt;/code&gt;. The gate is written, committed and switched off. Nothing in the repository can close that bead. It needs an owner clicking a setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calendar-gated, not code-gated.&lt;/strong&gt; &lt;code&gt;claude-nfzl.7&lt;/code&gt; has PR #1384 merged as &lt;code&gt;b786149e1&lt;/code&gt;, R2 and R4 code live, and a full-corpus run passing in about 58 seconds across 2053 live triples with zero newcomers. The only thing outstanding is a mandatory two-week R1 observation window and a flap receipt. Time closes that one. Code cannot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complete but stale.&lt;/strong&gt; &lt;code&gt;claude-jqvw.11&lt;/code&gt; runs &lt;code&gt;check-mirror-licenses.mjs&lt;/code&gt; green at 36 of 36 configured sources and 36 of 36 &lt;code&gt;.source.json&lt;/code&gt; mirrors, with sync hard-failing on a missing license include. Blueprint and Beads still carry the historical 63/63 denominator. The record is wrong, not the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Green suite, missing red run.&lt;/strong&gt; &lt;code&gt;claude-jqvw.1&lt;/code&gt; has the whole chain working: tag, GitHub Release, reassertion, npm publish, with &lt;code&gt;npm-publication-lock.test.mjs&lt;/code&gt; passing 11 of 11. What it does not have is the required fault-injection RED run proving no orphan npm publication and retained signed evidence-row proof. A passing test says the happy path holds. It says nothing about the failure mode you built the lock for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag exists, workflow never calls it.&lt;/strong&gt; The evidence emitter supports &lt;code&gt;--certification-report&lt;/code&gt;. &lt;code&gt;.github/workflows/emit-evidence.yml&lt;/code&gt; never generates or passes a real one, so only catalog, unicode and required-context rows get signed. &lt;code&gt;claude-snmr.5&lt;/code&gt; is open because of that, and &lt;code&gt;claude-snmr.6&lt;/code&gt; is explicitly blocked behind it.&lt;/p&gt;

&lt;p&gt;The audit also decomposed a 79-entry corpus shrink (2132 pinned against 2053 live) into 78 &lt;code&gt;E-MISSING-REQUIRED-SECTION&lt;/code&gt; plus 1 &lt;code&gt;E-FRONTMATTER&lt;/code&gt;, rather than treating it as one bot-authored rule change. Last baseline commit was bot PR #1367 on Aug 27. And mid-run another agent modified &lt;code&gt;freshie/scripts/promote-to-curated.py&lt;/code&gt; and moved the branch to &lt;code&gt;fix/curated-promotion-cohort-parity&lt;/code&gt;. The auditor refused to reset or touch it and took all its Epic 6 evidence from read-only Git views of &lt;code&gt;origin/main&lt;/code&gt; instead. That is the correct call in a shared working tree, and it is a call I have watched agents get wrong.&lt;/p&gt;

&lt;p&gt;Merged in that repo the same day anyway: PR #1401 (&lt;code&gt;3c5be4a59&lt;/code&gt;, secure projections and Snowflake, the same commit the auditor later signed off as its clean baseline), PR #1403 (Snowflake operator skills), and &lt;code&gt;d6d14da83&lt;/code&gt; unifying the freshie curated promotion cohort.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not just close the beads
&lt;/h3&gt;

&lt;p&gt;Because a closed bead that traces back to switched-off branch protection is worse than an open one. An open bead is a question. A closed bead is an answer, and nobody re-audits an answer. Convert the first into the second and you have not finished the work, you have deleted the only record that the work is unfinished. Six hours of audit output that closes nothing is cheaper than one wrong close, because the wrong close comes back as a production surprise with no bead pointing at it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the requirement down as an enforced file
&lt;/h2&gt;

&lt;p&gt;While that audit ran, the Omarchy fleet moved: &lt;code&gt;omarchy-widget-template&lt;/code&gt; plus 15 &lt;code&gt;omarchy-*-entry&lt;/code&gt; repos: docket, quiet-queue, foundry, loose-ends, bazaar, capture-conveyor, listening-post, crew-chief, desk-transition, flow-boundary, wait-state, workspace-storyboard, x-files, mlb-booth and pit-wall. The commit shapes repeat: &lt;code&gt;test: certify &amp;lt;X&amp;gt; on Buzz&lt;/code&gt;, &lt;code&gt;chore: sync canonical Omarchy gates&lt;/code&gt;, &lt;code&gt;fix: bind &amp;lt;X&amp;gt; marketplace claims&lt;/code&gt;, &lt;code&gt;test: refresh &amp;lt;X&amp;gt; Buzz proof&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The artifact worth naming is 18 lines of markdown in the template, &lt;code&gt;contracts/marketplace.md&lt;/code&gt;, from commit &lt;code&gt;0607dcc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Marketplace claim ledger&lt;/span&gt;

Replace this template ledger before calling a generated plugin submission-ready.
Every meaningful listing claim needs a shipped source and an executable proof.
Do not infer behavior from a mockup, README, test name, or intended design.

| Claim | Shipped source | Executable proof |
|---|---|---|
| Visible bar outcome and primary panel action | &lt;span class="sb"&gt;`BarWidget.qml`&lt;/span&gt;, &lt;span class="sb"&gt;`Panel.qml`&lt;/span&gt; | plugin-specific contract and interaction tests |
| Data source, scope, cadence, and bounds | service QML, &lt;span class="sb"&gt;`Model.js`&lt;/span&gt;, or shipped helper | fixture-backed unit, boundary, and failure tests |
| Local writes, network use, credentials, and explicit exclusions | every shipped runtime path | security contract tests plus canonical gates |
| Marketplace image tells the same product story | &lt;span class="sb"&gt;`assets/banner.svg`&lt;/span&gt;, deterministic E2E fixture | hash-bound Buzz render receipt and visual approval |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two columns per claim, and both are mandatory. A test name is not a proof. A mockup is not a source. The ledger also fixes the description rule so it stops being a matter of taste: the final listing description and &lt;code&gt;barWidget.description&lt;/code&gt; must be identical, exactly 500 characters, name the product, explain what appears in the bar or panel, state what the user can do, and disclose the material trust boundary.&lt;/p&gt;

&lt;p&gt;A markdown file nobody enforces is a wish. The same commit added six lines to &lt;code&gt;tests/contract.test.js&lt;/code&gt;, five assertions plus the read, so the ledger cannot be quietly deleted or hollowed out into a heading with nothing under it:&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;marketplaceContract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contracts/marketplace.md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;marketplaceContract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="sr"&gt; Claim &lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="sr"&gt; Shipped source &lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="sr"&gt; Executable proof &lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;marketplaceContract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/exactly&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+500 characters/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;marketplaceContract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/bar or panel/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;marketplaceContract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/trust boundary/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;marketplaceContract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/hash-bound Buzz render receipt/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commit touched &lt;code&gt;.harness-hash&lt;/code&gt; (+8/-7), &lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;contracts/marketplace.md&lt;/code&gt; (+18), &lt;code&gt;tests/RTM.md&lt;/code&gt;, and &lt;code&gt;tests/contract.test.js&lt;/code&gt; (+6). Small diff. It is the same move the audit was asking for, applied one layer earlier: state the requirement in a file, and make the test suite fail if the file stops saying it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two bugs where the proof machinery broke its own preconditions
&lt;/h2&gt;

&lt;p&gt;Both of these landed the same day, in the same fleet, and they are the same shape: the thing that verifies work was interfering with the work it verified.&lt;/p&gt;

&lt;h3&gt;
  
  
  A gate runner racing its own input
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;scripts/run-plugin-gates.sh&lt;/code&gt; in omarchy-docket-entry fed each gate a small JSON envelope through a pipe. A gate that exits before reading stdin races the producer into SIGPIPE, exit 141. So a deterministic invalid-verdict check became an intermittent gate crash, dependent on scheduling. Commit &lt;code&gt;240b2d6&lt;/code&gt; swaps the pipe for a here-string:&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;INPUT&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;jq &lt;span class="nt"&gt;-nc&lt;/span&gt; &lt;span class="nt"&gt;--arg&lt;/span&gt; c &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TARGET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{candidate:$c, action:"omarchy-submit", env:{repo:""}}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;gate &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GATES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;/c&lt;span class="k"&gt;*&lt;/span&gt;.sh&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c"&gt;# Feed the small JSON envelope with a here-string. A pipe lets a gate that&lt;/span&gt;
  &lt;span class="c"&gt;# exits before reading stdin race the producer into SIGPIPE (141), turning a&lt;/span&gt;
  &lt;span class="c"&gt;# deterministic invalid-verdict check into an intermittent gate crash.&lt;/span&gt;
  &lt;span class="nv"&gt;verdict&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;bash &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$gate&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INPUT&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="c"&gt;# A gate that emits nothing has crashed hard. Fail closed rather than&lt;/span&gt;
  &lt;span class="c"&gt;# silently counting it as clean, which is how a broken gate becomes theater.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$verdict&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="c"&gt;# (excerpt: the loop goes on to print CRASH, set blocked=1, and continue)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fail-closed-on-empty branch and that comment about theater were already in the file. Somebody had already thought carefully about a gate emitting nothing. What was broken was that the runner could manufacture the empty verdict itself, and then correctly fail closed on a condition it had caused. This is the inverse of the audit's problem: there the evidence was missing, here the evidence was lying. A safety check firing on its own noise is still a false alarm, and false alarms are how people learn to ignore gates.&lt;/p&gt;

&lt;h3&gt;
  
  
  A render that dirtied the source it was proving
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;scripts/rig-render.sh&lt;/code&gt; in the template will only issue a render receipt if the source tree is clean, which is the entire point of a receipt: it binds an image to a specific source state. The glob of files whose modification marks the tree dirty included &lt;code&gt;preview.png&lt;/code&gt;, the render's own output.&lt;/p&gt;

&lt;p&gt;So a failed render left a stale &lt;code&gt;preview.png&lt;/code&gt; behind. That file marked the source dirty. No retry could ever produce a clean receipt. One bad render poisoned every attempt after it. Commit &lt;code&gt;52a9d42&lt;/code&gt; removes the artifact from the precondition: the pathspec used to carry &lt;code&gt;preview.png&lt;/code&gt; between &lt;code&gt;manifest.json bin&lt;/code&gt; and &lt;code&gt;README.md&lt;/code&gt;, and after the fix it reads:&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;SOURCE_DIRTY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&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;$SOURCE_COMMIT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"unknown"&lt;/span&gt; &lt;span class="o"&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; &lt;span class="nt"&gt;-n&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;$TARGET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 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;all &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="s1"&gt;'*.qml'&lt;/span&gt; &lt;span class="s1"&gt;'*.js'&lt;/span&gt; manifest.json bin README.md assets/banner.svg &lt;span class="se"&gt;\&lt;/span&gt;
     e2e scripts/rig-render.sh 2&amp;gt;/dev/null&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nv"&gt;SOURCE_DIRTY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The obvious fix is to delete &lt;code&gt;preview.png&lt;/code&gt; at the top of every run. That fix is wrong, and the reason is worth stating. The receipt exists to distinguish a render of clean source from a render of dirty source. If the script scrubs the output first, every dirty-source failure gets laundered into a clean run and the distinction the receipt sells is gone. Removing the output from the precondition is a smaller change and it keeps the signal. The same class of fix landed in two other entries that day: "keep failed Capture renders retryable" in capture-conveyor (&lt;code&gt;04ca3ae&lt;/code&gt;) and "allow clean render retry after failed capture" in loose-ends (&lt;code&gt;88054b8&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  A dead-man that could not tell quiet from dead
&lt;/h2&gt;

&lt;p&gt;At 22:12 I asked for something unrelated: &lt;code&gt;i need ezekiel to start recievinf the emails like he does withe blog backfill skill that runs the blog work u know what i mean&lt;/code&gt;. Ezekiel does the social posting. The blog pipeline already emails him a per-post packet. The real-estate content machine behind comehomealabama.com, run out of coastal-realty-ops, had been soaking unattended for 11 days and it was time to point it at him too.&lt;/p&gt;

&lt;p&gt;Claude Fable 5 ran a health check before flipping anything, on the reasoning that Ezekiel should not start receiving packets from a broken producer and should not get 11 days of backlog dropped on him in one morning. The soak verdict: five posts landed on Aug 21, 24, 26, 28 and 31, all Monday/Wednesday/Friday, every prior post packeted, liveness green, and the ledger showed exactly one unsent packet. He would start with one email.&lt;/p&gt;

&lt;p&gt;The flip itself was five minutes and nine tool calls, shipped as coastal-realty-ops PR #50 (&lt;code&gt;17394b3&lt;/code&gt;): &lt;code&gt;packet.env&lt;/code&gt; &lt;code&gt;PACKET_TO&lt;/code&gt; set to &lt;code&gt;ezekiel@intentsolutions.io&lt;/code&gt; with me on CC. The file is sourced per run, so no restart, effective at the next 05:15 sweep. That commit also banked 5 lines of &lt;code&gt;decisions.jsonl&lt;/code&gt; and 3 lines of &lt;code&gt;topics-queue.jsonl&lt;/code&gt; the producer had accumulated during the soak.&lt;/p&gt;

&lt;p&gt;The health check is what found the bug. &lt;code&gt;scripts/journal/mandy-posting-packet.sh&lt;/code&gt; had three clean no-op exits (no ledger, no packets due, no digest week) and all three returned 0 without touching &lt;code&gt;mandy-posting-packet.ok&lt;/code&gt;. The estate dead-man sweep reads a fresh &lt;code&gt;.beat&lt;/code&gt; with a stale &lt;code&gt;.ok&lt;/code&gt; as running-but-failing. So a perfectly healthy pipeline with nothing due for two days would page. It was already visible in the wild: &lt;code&gt;.ok&lt;/code&gt; stuck at Aug 29 (the Aug 28 post's packet fired that morning) while &lt;code&gt;.beat&lt;/code&gt; kept advancing.&lt;/p&gt;

&lt;p&gt;The commit message for comehomealabama PR #8 (&lt;code&gt;d87bada&lt;/code&gt;) carries the rule in one line: a clean no-op IS a successful run. Change was +5/-3 in one shell script, verified with &lt;code&gt;shellcheck -S warning&lt;/code&gt;, &lt;code&gt;bash -n&lt;/code&gt;, and a live &lt;code&gt;--sweep&lt;/code&gt; against the current ledger that logged "no packets due" and refreshed &lt;code&gt;.ok&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tempting shortcut is to touch &lt;code&gt;.ok&lt;/code&gt; at the top of the script and stop thinking about it. That reports healthy before doing any work, which is precisely the failure the dead-man exists to catch. The marker belongs on every path that legitimately completes, no-ops included, and on no path that does not. Quiet and dead have to be distinguishable, and the only place that distinction can live is in the script that knows which one it is.&lt;/p&gt;

&lt;p&gt;The part I keep coming back to: nothing was on fire. The two-day quiet window that would have false-paged had not happened yet. It got found because Claude Fable 5 checked the system before trusting it with a person's inbox.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Retiring a carried patch in the Buzz fork.&lt;/strong&gt; &lt;code&gt;cb633a0c4&lt;/code&gt; plus PRs #30 and #31 emptied &lt;code&gt;CARRIED_PATCHES&lt;/code&gt; in &lt;code&gt;scripts/fork-gates/check-additive-only.sh&lt;/code&gt;, deleted the carried 311-line e2e spec &lt;code&gt;desktop/tests/e2e/manual-invite-join.spec.ts&lt;/code&gt;, replaced FORK.md's carried-patches exception with &lt;code&gt;None - empty by design&lt;/code&gt;, and filed a 131-line audit at &lt;code&gt;000-docs/009-AA-AUDR-fork-contract-breach-2026-08-16.md&lt;/code&gt;. PRs #26 and #27 had carried an invite-to-default-channel patch on fork main, the same class of fork-contract breach as the earlier PR #16 incident already documented in &lt;code&gt;000-docs/007&lt;/code&gt;. Production now runs the upstream published image (&lt;code&gt;ghcr.io/block/buzz@sha256:fe092cf9...&lt;/code&gt;), enrollment moved to an ops-side watcher in the private ops repo, and the real fix is tracked upstream as &lt;code&gt;block/buzz#4307&lt;/code&gt;. Merge-and-restore beat revert because the upstream sync supersedes the carry without rewriting history. Both &lt;code&gt;check-additive-only.sh&lt;/code&gt; and &lt;code&gt;check-must-survive.sh&lt;/code&gt; pass with &lt;code&gt;CARRIED_PATCHES&lt;/code&gt; empty, gate output pasted into the PR body. A large upstream sync (&lt;code&gt;91452d823&lt;/code&gt;) landed about 15 upstream commits the same day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A discovery that ended in deliberate non-adoption.&lt;/strong&gt; Starting 02:10, Claude Fable 5 ran a discovery on the third-party &lt;code&gt;no-mistakes&lt;/code&gt; tool against the Intent Solutions testing SOP. It is a Go git-proxy: you push to a &lt;code&gt;no-mistakes&lt;/code&gt; remote instead of origin and it runs intent, rebase, review, test, docs, lint, push, PR and CI in an isolated disposable worktree, with an LLM review stage that falls back across agents and a CI repair loop with guarded force-push. We did not adopt it. What came out was &lt;code&gt;worktree-run.sh&lt;/code&gt; built into &lt;code&gt;audit-harness&lt;/code&gt;, a verification of the read-only-test rule, and the non-adoption recorded as a decision instead of an unwritten "we looked at it once". Two incidental findings: &lt;code&gt;yamllint&lt;/code&gt; was not installed on this box, and the escape-scan expectation was inverted, since the test expects a non-zero exit (a REFUSE) when policy is being weakened.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A $0 calendar stack, decided in conversation, no commits.&lt;/strong&gt; The one item of the day with neither a shipped source nor an executable proof, recorded here as the exception it is. With a Buzz VPS bill due the next day I asked what was free, then &lt;code&gt;im so confused whata the most texhnically sound optiin that would be most respected by underground linux users as my teams set up&lt;/code&gt;. Answer: Radicale on the VPS that already exists. One Python process, and the team calendar is a directory of plain &lt;code&gt;.ics&lt;/code&gt; text files you can grep and diff, backed up by borg like any other directory. khal plus vdirsyncer for the terminal, Cal.com's free tier for outward booking. The part worth recording is the refusal. Fastmail was rejected as a mail viewer, because a calendar decision should not quietly turn into a second mail migration one month after the MXroute cutover.&lt;/p&gt;

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

&lt;p&gt;The session analyzer logged 19 failure-to-fix arcs and 2 course-corrections across four models (Claude Opus 5, Claude Sonnet 5, Claude Fable 5, GPT 5.6 Luna), over sessions spanning 1169 minutes of wall clock. GPT 5.6 Luna took &lt;code&gt;claude-code-plugins&lt;/code&gt; for 2 sessions, 187 turns, 361 minutes. Claude Fable 5 took &lt;code&gt;intent-eval-platform&lt;/code&gt; for 3 sessions, 27 turns, 8 errors and both course-corrections. Claude Opus 5 and Claude Fable 5 split the home layer across 3 sessions and 273 minutes with 9 errors. Claude Fable 5 did coastal-realty-ops in 5 minutes and 9 tool calls.&lt;/p&gt;

&lt;p&gt;The two ends of that range are the same instinct at different scales. GPT 5.6 Luna was told to finish the epics and spent six hours producing an audit that closed nothing, because closing them honestly was not on the menu. Claude Fable 5 was told to switch Ezekiel on, checked the pipeline's health first, and then did exactly what it was asked. Only one of the two delivered the literal request, and it delivered it last. Both started from the same place: find out whether the thing is true before writing down that it is.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/a-green-result-only-covers-what-it-ran/" rel="noopener noreferrer"&gt;A green result only covers what it ran&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/scope-the-guard-to-what-the-job-writes/" rel="noopener noreferrer"&gt;Scope the guard to what the job writes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/one-corrected-check-fifteen-repos/" rel="noopener noreferrer"&gt;One corrected check, fifteen repos&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 Claim Needs a Shipped Source and an Executable Proof",&lt;br&gt;
  "description": "Every claim needs a shipped source and an executable proof. What a six-hour audit that closed nothing found out about code that was already finished.",&lt;br&gt;
  "url": "&lt;a href="https://startaitools.com/posts/working-is-not-proven/" rel="noopener noreferrer"&gt;https://startaitools.com/posts/working-is-not-proven/&lt;/a&gt;",&lt;br&gt;
  "datePublished": "2026-08-31T10:00:00-06:00",&lt;br&gt;
  "dateModified": "2026-08-31T10:00:00-06:00",&lt;br&gt;
  "author": {&lt;br&gt;
    "@type": "Person",&lt;br&gt;
    "name": "Jeremy Longshore"&lt;br&gt;
  },&lt;br&gt;
  "publisher": {&lt;br&gt;
    "@type": "Organization",&lt;br&gt;
    "name": "Start AI Tools",&lt;br&gt;
    "url": "&lt;a href="https://startaitools.com" rel="noopener noreferrer"&gt;https://startaitools.com&lt;/a&gt;"&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cicd</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>One Corrected Check, Fifteen Repos</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Tue, 01 Sep 2026 10:21:25 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/one-corrected-check-fifteen-repos-51gk</link>
      <guid>https://dev.to/jeremy_longshore/one-corrected-check-fifteen-repos-51gk</guid>
      <description>&lt;p&gt;Two gates failed the same way on 2026-08-30, in systems that share no code.&lt;/p&gt;

&lt;p&gt;The first checked whether a set of run fields were non-null. A recorded discovery run could therefore declare 3,000 skills while carrying 19 rows, and the boundary would pass it, because 3,000 is not null and 19 is not null. Runs 6 through 11 all disagreed with their own row counts. Run 11 declared 3,069 against 3,678 actual rows.&lt;/p&gt;

&lt;p&gt;The second checked whether a marketplace submission description was exactly 500 characters. Which 500 characters was never asked. So 500 characters of filler passed, and 500 characters of filler is precisely the submission the gate was written to stop.&lt;/p&gt;

&lt;p&gt;A check measuring a proxy instead of the property is the house failure mode on this blog and has been for months. I am not going to pretend it was a discovery. What was actually expensive on this day was not diagnosing either gate. It was pushing one corrected gate through fifteen repos that carry it as a vendored, hash-pinned copy rather than importing it. That half is the post.&lt;/p&gt;

&lt;h2&gt;
  
  
  The evidence boundary that could not see its own run
&lt;/h2&gt;

&lt;p&gt;Epic 5, "Coherent Freshie Evidence," closed in &lt;code&gt;claude-code-plugins&lt;/code&gt; that day. The closure AAR is &lt;code&gt;000-docs/809-AA-AACR-epic-5-closure.md&lt;/code&gt;, 134 lines, filed against epic bead &lt;code&gt;claude-h05s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The AAR states the defect in one line: "The old boundary checked whether required run fields were non-null, not whether the header and its rows described the same run." The run-6 shape is the image that sticks. Three thousand declared skills, nineteen rows, green.&lt;/p&gt;

&lt;p&gt;Five invariants replaced it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;gate_run_completeness()&lt;/code&gt; compares the run header against same-run rows before any export work begins.&lt;/li&gt;
&lt;li&gt;The grade histogram, CSV row count, CSV hash, run tag, and immutable Dolt commit must identify one export, not adjacent runs that happen to be close.&lt;/li&gt;
&lt;li&gt;Behavioral-evaluation identity is &lt;code&gt;jrig_run_id&lt;/code&gt;, held separate from discovery-run identity.&lt;/li&gt;
&lt;li&gt;Evidence class and retention are validity conditions, not annotations. Three legacy proofs are now honestly classified E0. No public verified projection remains.&lt;/li&gt;
&lt;li&gt;Blocking CI installs a pinned Dolt binary immediately before an exact guarded runner, which must execute one real hermetic cycle with zero skips against scratch SQLite, Dolt, and filesystem state, then prove live-server refusal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nine commits landed that sequence, and read as a run they are a reviewer finding bypasses faster than they could be closed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make exit evidence fail closed
reject skipped and overwritten proofs
close generator and overwrite bypasses
require executed hermetic proof
bind proof method and install order
verify guarded cycle invocation
bind receipts and harden hermetic proof
publish reproducible run 14 receipts
enforce graded corpus parity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The independent boundary review returned PASS only "after reproducing and closing skipped tests, generator no-op, lifecycle replacement, aliased mutation, and post-verification binary-overwrite attacks." Five attacks. Each one maps onto a commit in that list. &lt;code&gt;reject skipped and overwritten proofs&lt;/code&gt; is the skipped-test attack. &lt;code&gt;close generator and overwrite bypasses&lt;/code&gt; is the generator no-op. &lt;code&gt;bind proof method and install order&lt;/code&gt; is what stops the binary being swapped after verification. The commit log is not a changelog here, it is an attack transcript with the reviewer's half missing.&lt;/p&gt;

&lt;p&gt;The first commit alone touched 8 files for +1515/-256, including &lt;code&gt;run-delta.py&lt;/code&gt; at +247/-50, &lt;code&gt;measure-epic-1-scorecard.mjs&lt;/code&gt; at +382, and four test files. All nine commit bodies were empty, which is worth one dry line: the sequence that produced the most legible story of the day carried no explanation with it at all.&lt;/p&gt;

&lt;p&gt;Final receipts. Run 14 declared 3,053 against 3,053 rows, delta 0. 3,630 compliance rows against 3,630 grade rows with matching SHA-256. Run 14 is bound to immutable Dolt commit &lt;code&gt;2ljhn79ge74uj1kd7q2chqgo9ne0tulb&lt;/code&gt;, grade CSV SHA-256 &lt;code&gt;72fbb289e8451d9a4bbe95cae0b9a1797588c0197589f94ddd1cde48241e4ef0&lt;/code&gt;, histogram A 1,872 / B 1,117 / C 479 / D 157 / F 5. &lt;code&gt;pnpm run measure:e1:check&lt;/code&gt; passed 39 measurement tests and the tracked artifact matched its exact regeneration from the Git index. PR #1387 merged as &lt;code&gt;78e3580c&lt;/code&gt; after 34 reporting checks with zero failures.&lt;/p&gt;

&lt;p&gt;The AAR's own first lesson is the one to keep:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A green test command is not proof that the governed body ran. Exact test count, zero skips, and a guarded method invocation are part of the boundary now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Its second lesson is quieter and I think better: "Zero E2/E3 claims is a safe state, not a 100% retention measurement." The scorecard now reports &lt;code&gt;retention_percent&lt;/code&gt; as &lt;code&gt;null&lt;/code&gt;. A tool with nothing to measure says nothing rather than reporting a flattering 100%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five hundred characters of anything
&lt;/h2&gt;

&lt;p&gt;The second gate is &lt;code&gt;scripts/gates/c43-omarchy-marketplace-presentation.sh&lt;/code&gt;, which guards marketplace submission copy across the Omarchy widget fleet. Here is what it checked:&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="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;$HAS_BAR_WIDGET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BAR_DESC_LENGTH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"500"&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;FINDINGS+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"barWidget description uses &lt;/span&gt;&lt;span class="nv"&gt;$BAR_DESC_LENGTH&lt;/span&gt;&lt;span class="s2"&gt;/500 characters"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Length equality, and nothing else. A submission had to fill its allowance exactly, and filling an allowance is trivially satisfied by padding.&lt;/p&gt;

&lt;p&gt;The comment written above the replacement checks is the whole day in five lines:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Length alone is not copy quality. A submission description must identify the product, explain what the user can see or do, and state a meaningful trust boundary. These checks deliberately reject generic 500-character filler while repo-specific contract tests pin the precise claims each plugin is allowed to make.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The new checks run as an embedded &lt;code&gt;python3&lt;/code&gt; heredoc inside the bash gate, each one appending to a findings list rather than exiting early, so a bad description gets told everything wrong with it at once. Four of them, excerpted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sentences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?&amp;lt;=[.!?])\s+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&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;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentences&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;findings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description needs at least four readable sentences&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sentences&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentences&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="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;findings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;opening sentence is too thin to establish the user outcome&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;surface_terms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;panel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;widget&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;rf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;surface_terms&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;findings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description never explains the visible bar, panel, pill, or widget&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two more term lists do the load-bearing work. An interaction list (&lt;code&gt;open&lt;/code&gt;, &lt;code&gt;click&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt;, &lt;code&gt;copy&lt;/code&gt;, &lt;code&gt;install&lt;/code&gt;, &lt;code&gt;focus&lt;/code&gt;, &lt;code&gt;refresh&lt;/code&gt;, &lt;code&gt;preview&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;scan&lt;/code&gt;, and about a dozen more) fails a description that "gives no concrete user interaction or visible behavior." A boundary list (&lt;code&gt;no&lt;/code&gt;, &lt;code&gt;never&lt;/code&gt;, &lt;code&gt;only&lt;/code&gt;, &lt;code&gt;without&lt;/code&gt;, &lt;code&gt;offline&lt;/code&gt;, &lt;code&gt;local&lt;/code&gt;, &lt;code&gt;private&lt;/code&gt;, &lt;code&gt;fixed&lt;/code&gt;) fails one that "gives no privacy, network, data, or write boundary." A description can be four fluent sentences about nothing and still fail both.&lt;/p&gt;

&lt;p&gt;Then there is a banned-phrase list inside the gate, nine entries: &lt;code&gt;cutting-edge&lt;/code&gt;, &lt;code&gt;game-changer&lt;/code&gt;, &lt;code&gt;game-changing&lt;/code&gt;, &lt;code&gt;revolutionary&lt;/code&gt;, &lt;code&gt;supercharge&lt;/code&gt;, &lt;code&gt;seamless&lt;/code&gt;, &lt;code&gt;robust solution&lt;/code&gt;, &lt;code&gt;unlock your&lt;/code&gt;, &lt;code&gt;take your productivity to the next level&lt;/code&gt;. I run the same instrument against this blog's prose from a JSON deny-list, and the overlap is not coincidence. Both lists exist because the same generator produces both kinds of copy.&lt;/p&gt;

&lt;p&gt;Plus one cross-field check with the best failure message in the set: &lt;code&gt;manifest and barWidget descriptions tell different product stories&lt;/code&gt;, which fires when the two description fields disagree about what the thing is.&lt;/p&gt;

&lt;p&gt;None of that is clever, and it is worth being honest about what it does not do. A length check and a shape check are the same class of instrument, and a determined author can pad four sentences as easily as one. The gate is not proving quality. It raises the floor from "any 500 bytes" to "500 bytes that name the product, show a visible surface, describe an interaction, and state a boundary," and its own comment says where the real work goes: repo-specific contract tests pin the precise claims each plugin is allowed to make.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that actually cost the day
&lt;/h2&gt;

&lt;p&gt;Downstream repos do not import this gate. Each one carries a vendored copy. The lane is declared at &lt;code&gt;scripts/gates/.lane-manifest&lt;/code&gt;, whose header reads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Vendored gate lane. Regenerate with scripts/sync-gate-lane.sh, never hand-edit.
# canonical: contributing-clanker@359a27cde21e60086f95a3ddee99c8920a3d7ca2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That header is quoted with its dash normalized to a comma, because the real file uses an em dash and this blog's own lint gate would quarantine the post for reproducing it.&lt;/p&gt;

&lt;p&gt;Below the header sit per-file SHA-256 hashes of every gate script. Alongside it, each repo carries &lt;code&gt;.harness-hash&lt;/code&gt; covering the wider audited surface: &lt;code&gt;contract.test.js&lt;/code&gt;, &lt;code&gt;run-plugin-gates.sh&lt;/code&gt;, &lt;code&gt;stryker.config.json&lt;/code&gt;, &lt;code&gt;tests/RTM.md&lt;/code&gt;, &lt;code&gt;tests/TESTING.md&lt;/code&gt;, and the rest.&lt;/p&gt;

&lt;p&gt;So the corrected conditional is not a one-line edit. The canonical pin moved from &lt;code&gt;contributing-clanker@359a27cd&lt;/code&gt; to &lt;code&gt;@81239c6e&lt;/code&gt;, and in every consuming repo four hashes had to move together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the lane manifest hash, in &lt;code&gt;.lane-manifest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;c43&lt;/code&gt; gate hash, in both &lt;code&gt;.lane-manifest&lt;/code&gt; and &lt;code&gt;.harness-hash&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run-plugin-gates.sh&lt;/code&gt;, because the gate list it dispatches changed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;contract.test.js&lt;/code&gt;, because the per-repo contract test that pins the allowed claims changed with the copy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The third and fourth entries are the ones that make this expensive. The gate file itself is one hash. But correcting the gate changed which checks run, so the runner's hash moved, and tightening the copy to satisfy the gate changed each repo's contract test, so that hash moved too. One upstream edit fans out into four hashes per repo, and any repo where they drift fails its own harness verification before it fails the gate. That is the design working, and it is also the bill.&lt;/p&gt;

&lt;p&gt;Here is the shape of a single downstream repo's day, using &lt;code&gt;omarchy-listening-post-entry&lt;/code&gt;, which took four commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix: complete Listening Post marketplace copy
test: pin Listening Post marketplace story
test: enforce marketplace presentation quality
chore: repin audit harness artifacts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read that in order and it is the whole propagation protocol in four steps. Rewrite the copy so the new gate passes. Pin the specific claims this plugin is allowed to make, in its own contract test. Take the corrected gate from the lane. Re-pin the harness hashes so the repo verifies against its new self. Every repo ran some subset of exactly that. The spread runs from four commits down to one: &lt;code&gt;omarchy-foundry-entry&lt;/code&gt; took a single &lt;code&gt;test:&lt;/code&gt; commit and no copy commit at all, which is what it looks like when only the gate underneath a repo moves.&lt;/p&gt;

&lt;p&gt;Fifteen entry repos took the change: bazaar, capture-conveyor, crew-chief, desk-transition, docket, flow-boundary, foundry, listening-post, loose-ends, mlb-booth, pit-wall, quiet-queue, wait-state, workspace-storyboard, x-files. Twelve of them needed a &lt;code&gt;fix: complete &amp;lt;Name&amp;gt; marketplace copy&lt;/code&gt;. The other three, desk-transition, foundry, and wait-state, needed only the proof and the re-pin. Counting the template and the canonical lane source itself, the fan-out ran to 48 commits across 17 repos. The whole day, including the freshie epic, came to 112 commits across 19 repos.&lt;/p&gt;

&lt;p&gt;The tradeoff is deliberate and I would still take it. Vendoring plus hash pinning means a downstream repo cannot silently run a gate that differs from canonical, and cannot quietly weaken one either. What it buys in tamper-evidence it charges in propagation, and the charge is not proportional to the size of the fix. A one-character change and a rewrite cost the same fifteen-repo sweep, because the sweep is the unit of work, not the edit. The implication is that batching discipline matters more than edit discipline on a lane like this one, though that follows from the design rather than from anything measured on this particular day: both corrected gates here lived in unrelated systems, so nothing rode the same sweep.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate that forced an honesty edit
&lt;/h2&gt;

&lt;p&gt;Twelve repos needed a copy commit, and four of them needed a second pass after it. Those four are the interesting ones, because the gate did not extract more words from them on the second pass, it extracted truer ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix: state MLB Booth data boundary honestly
fix: clarify Loose Ends queue priority
fix: make Bazaar marketplace copy precise
fix: tighten Pit Wall marketplace copy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template's own description went the same direction. One long run-on became shorter sentences. "real-shell screenshot evidence" was softened to "shell screenshot evidence." "plugin-specific SVG banner" became "product-specific SVG banner." A gate asking for four readable sentences and a stated trust boundary got four readable sentences, and the claims came out weaker and truer than they went in. That was not designed. It falls out of asking for a trust boundary at all, because you cannot state one without noticing where yours actually sits.&lt;/p&gt;

&lt;h2&gt;
  
  
  A watch that could only see page one
&lt;/h2&gt;

&lt;p&gt;Third thread, and it stays short because it is the same defect wearing different clothes. In &lt;code&gt;intent-os&lt;/code&gt;, bead &lt;code&gt;spine-lkb.12&lt;/code&gt; and PR #566 shipped &lt;code&gt;ops/plane-invite-watch/&lt;/code&gt;, a daily VPS timer that reconciles the Plane workspace invitation list against members and against its own known state, paging Buzz sys-incidents when an invitation is queued with no mail behind it, sits unclaimed past 7 days, or belongs to somebody who is already a member.&lt;/p&gt;

&lt;p&gt;Two details earn its place. Its &lt;code&gt;automations.md&lt;/code&gt; row is marked &lt;code&gt;NOT-YET-ARMED until deploy receipts&lt;/code&gt;, which is the same call as reporting &lt;code&gt;retention_percent&lt;/code&gt; as &lt;code&gt;null&lt;/code&gt;: a row describing a timer nobody has armed yet is a lie in a document people trust. And the review caught that both fetches read only the first page, because "a watch reading only page one would go blind past 100 rows," rated HIGH. Cursor and envelope pagination went in, hermetic drill 9/9 after the change, full &lt;code&gt;pnpm check&lt;/code&gt; green.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three sessions, one steer
&lt;/h2&gt;

&lt;p&gt;Three sessions ran concurrently, and the split is worth one line because it was not arbitrary. The fan-out work ran on Claude Opus 5 with Claude Opus 4.8 alongside it, 754 turns and 171 tool calls across twelve hours, because fifteen near-identical repos is exactly the job where a model holding a long invariant beats a fast one. The &lt;code&gt;intent-os&lt;/code&gt; watcher ran on Claude Fable 5, 443 turns and zero errors in about an hour.&lt;/p&gt;

&lt;p&gt;One steer is worth quoting exactly as typed, because it is the day's thesis arriving as a correction and it arrived before I had written any of the above:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;yes add the auto-stash guard that seems like a band daid whats root cause fix&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The model had proposed the thing that makes the symptom go away. The correction was not "that code is wrong," it was "that is the wrong layer." Same shape as the two gates: a check that satisfies the condition in front of it without touching the property underneath. Other steers that day were shorter and in the same register: "rm -rf the decoy dirs," "verify the card shows up on ezekiels board," "and what did u decide ?"&lt;/p&gt;

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

&lt;p&gt;Two gates that now measure the property instead of a stand-in for it, and one monitor that can see past its first page. That is the cheap half.&lt;/p&gt;

&lt;p&gt;The expensive half is the fifteen repos, and what it bought there was a fleet where no consuming repo can run a gate that quietly differs from canonical. The cost of that guarantee is that every correction, however small, is a fifteen-repo sweep with four hashes moving in lockstep per repo. Forty-eight commits to move one conditional is not overhead I would call waste. It is the price of the tamper-evidence, stated in full, which is the number that belongs next to the guarantee whenever the next lane gets vendored.&lt;/p&gt;

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

&lt;p&gt;An adversarial multi-seat council ran that evening against a proposed company-calendar stack for the estate, reviewing it through fault-tolerance, data-model and source-of-truth, and convention-over-configuration lenses. Separately, an external tool called "no-mistakes" (a Go git-proxy that runs an intent, review, test, docs, lint, push, PR, CI pipeline inside an isolated worktree) was evaluated against the in-house audit-harness.&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-skip-that-counted-as-a-pass/"&gt;The Skip That Counted as a Pass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/a-green-result-only-covers-what-it-ran/"&gt;A Green Result Only Covers What It Ran&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/scope-the-guard-to-what-the-job-writes/"&gt;Scope the Guard to What the Job Actually Writes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cicd</category>
      <category>qualitygates</category>
      <category>governance</category>
      <category>testing</category>
    </item>
    <item>
      <title>Scope the Guard to What the Job Actually Writes</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Mon, 31 Aug 2026 10:18:23 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/scope-the-guard-to-what-the-job-actually-writes-12k8</link>
      <guid>https://dev.to/jeremy_longshore/scope-the-guard-to-what-the-job-actually-writes-12k8</guid>
      <description>&lt;p&gt;Two systems mismeasured what was in front of them. One aborted loudly on dirt that could not touch it. One returned a 200 and assigned the card to nobody. Both fixes narrowed what a piece of code claimed authority over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 04:00 producer that aborted on dirt it would never touch
&lt;/h2&gt;

&lt;p&gt;The blog pipeline runs unattended every morning at 04:00, on the same working tree that every interactive Claude Code session uses. One bash function, &lt;code&gt;preflight_branch_normalize()&lt;/code&gt; in &lt;code&gt;scripts/blog/lib-cron-common.sh&lt;/code&gt;, is the guard that decides whether the run may proceed at all.&lt;/p&gt;

&lt;p&gt;It refused to run on ANY uncommitted tracked file. Full stop. A legitimate edit left unsaved overnight took down the entire cron job.&lt;/p&gt;

&lt;p&gt;This happened three times:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2026-08-13: persona files&lt;/li&gt;
&lt;li&gt;2026-08-18: a lost image-push race condition that left the tree diverged&lt;/li&gt;
&lt;li&gt;2026-08-29: uncommitted 68-insertion doc update to &lt;code&gt;000-docs/002-REF-omarchy-plugin-promotion-reference.md&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two of the three were the same cascade: the dirty-tree check FATAL'd, no post got produced, and the 05:00 posting packet had nothing to send to Ezekiel. The 08-18 abort came one step later in the same function, where an ff-only pull correctly refused a tree that a lost image-push race had diverged. That one was fixed at the push, not here, and the scoping change would not have saved it. The morning of the 29th the recovery was manual: commit the legitimate content, push, re-run backfill for the 28th by hand.&lt;/p&gt;

&lt;p&gt;The issue is mechanical: a human editor can legitimately leave work uncommitted while a nightly job wants to proceed. These are not in conflict. The job writes to four specific paths. Uncommitted changes anywhere else do not touch what the job produces.&lt;/p&gt;

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

&lt;p&gt;Commit &lt;code&gt;605835ec&lt;/code&gt;: &lt;code&gt;scripts/blog/lib-cron-common.sh&lt;/code&gt; (+28/-12). The preflight now FATALs only on uncommitted changes to the pipeline's own write-set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;content/posts/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.blog-staging/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.claude/skills/blog-backfill/methodology/decisions.jsonl&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;static/images/posts/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uncommitted changes anywhere else are logged and left exactly where they are. The run proceeds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not the obvious approaches
&lt;/h3&gt;

&lt;p&gt;Two alternatives were considered and rejected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-stash:&lt;/strong&gt; A band-aid. It moves someone's active mid-edit work out from under them, and then pops the change back to uncommitted. The same file re-triggers the abort the next night. Auto-stash also touches work that is not the pipeline's business to touch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A retry loop or nightly re-run:&lt;/strong&gt; The wrong tool for this shape of failure. A dirty tree is a standing condition, not a transient one. It stays dirty at 04:15, 04:30, any time you retry. Retries just multiply the failure alerts instead of fixing anything.&lt;/p&gt;

&lt;p&gt;Scoping is the real fix. The producer genuinely cannot collide with dirt outside its write-set, so it should stop caring about it. The hazard is preserved: a half-written post in &lt;code&gt;content/posts/&lt;/code&gt; or a mid-edit &lt;code&gt;decisions.jsonl&lt;/code&gt; still aborts, because building on top of those is genuinely unsafe. That distinction is the whole reason this works.&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;# Abridged from preflight_branch_normalize(); log strings shortened.&lt;/span&gt;
&lt;span class="c"&gt;# Dirt inside the write-set still aborts. Dirt outside it is logged and left alone.&lt;/span&gt;
&lt;span class="nv"&gt;_porcelain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&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 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="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&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;$_porcelain&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;_dangerous&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$_porcelain&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^.. (content/posts/|\.blog-staging/|static/images/posts/|\.claude/skills/blog-backfill/methodology/decisions\.jsonl)'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&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;$_dangerous&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;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"FATAL: uncommitted changes to the pipeline's own files on '&lt;/span&gt;&lt;span class="nv"&gt;$current_branch&lt;/span&gt;&lt;span class="s2"&gt;', refusing to proceed"&lt;/span&gt;
    _log &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"       These paths are what the producer writes; a half-finished post or edit here is unsafe to build on. Resolve and re-run:"&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$_dangerous&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;&amp;amp;1
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
  &lt;span class="k"&gt;fi
  &lt;/span&gt;&lt;span class="nv"&gt;_benign&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$_porcelain&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  _log &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"Pre-flight: &lt;/span&gt;&lt;span class="nv"&gt;$_benign&lt;/span&gt;&lt;span class="s2"&gt; uncommitted file(s) outside the pipeline write-set, ignoring, they will not be touched"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The verification: a harness over four cases on a throwaway repo. It exercises two of the four write-set paths directly; the other two share the same match arm.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Benign &lt;code&gt;000-docs&lt;/code&gt; edit: passes the dirty check, logged as "ignoring, will not be touched"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;content/posts/&lt;/code&gt; edit: FATAL&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;decisions.jsonl&lt;/code&gt; edit: FATAL&lt;/li&gt;
&lt;li&gt;Clean tree: passes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That morning's exact failure would now proceed untouched.&lt;/p&gt;

&lt;h2&gt;
  
  
  The alarm working is not the system working
&lt;/h2&gt;

&lt;p&gt;One more thing about how the morning started. The failure did not surface because someone noticed a missing post. It surfaced because a gap detector built ten days earlier caught the gap and paged with a loud "no post landed" subject instead of reporting healthy.&lt;/p&gt;

&lt;p&gt;That detector only existed for the third failure, and the reason it exists is the second one. On 2026-08-18 the producer aborted at 04:00 and the 05:00 heartbeat still called the pipeline healthy an hour later. The detector was built on 2026-08-19 precisely because detection had failed. So on 2026-08-29 it fired correctly, which is the system improving.&lt;/p&gt;

&lt;p&gt;It is still worth saying plainly that it could have gone on firing correctly indefinitely without anything getting better. Three runs failed inside seventeen days. The alarm got fixed after the second. The guard behind it stayed wrong through all three. An alarm that fires reliably on a recurring failure is a reason to go fix the cause, not evidence that the cause is handled.&lt;/p&gt;

&lt;h2&gt;
  
  
  The task board that returned HTTP 200 and assigned nobody
&lt;/h2&gt;

&lt;p&gt;Ezekiel gets the posting packet as an email at 05:00. For weeks, "done" meant "reply to the email with the URLs," and a 07:30 ingest job read those replies. But the ingest kept coming back empty.&lt;/p&gt;

&lt;p&gt;The problem with reply-as-completion: a missing reply is indistinguishable from a missing post.&lt;/p&gt;

&lt;p&gt;The fix (commit &lt;code&gt;add88e64&lt;/code&gt;): after the packet email sends and marks &lt;code&gt;packet_sent&lt;/code&gt;, the sweep also creates or updates one Plane card per post, assigned to Ezekiel. He drags it To Do to Done as he posts. A card has a state on a board. Email is the delivery; the card is the record.&lt;/p&gt;

&lt;p&gt;The failure direction matters: the card call runs after the email send and after &lt;code&gt;mark_sent&lt;/code&gt;, and it swallows every error. A Plane outage can never turn a delivered packet into a failed run.&lt;/p&gt;

&lt;h3&gt;
  
  
  The root cause
&lt;/h3&gt;

&lt;p&gt;Plane silently drops an assignee who is not a member of the destination project, as opposed to the workspace. The PATCH returns HTTP 200 even when the assignment fails. Ezekiel was a workspace member but had never been added to the CONTENT project, so every assign returned 200 and assigned nobody.&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;ensure_project_member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&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;uid&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="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Plane silently drops an assignee who is not a member of the PROJECT (not
    just the workspace). Idempotently add him so the assignment can actually
    stick. Returns True if he is (now) a member.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;member_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;member&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&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;/projects/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CONTENT_PROJECT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/members/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;member_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[])]:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&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;/projects/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CONTENT_PROJECT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/members/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;member&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="c1"&gt;# 200/201 = added; 400 typically means "already a member", also fine.
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is why nine Omarchy showcase cards created on 2026-08-25 all read &lt;code&gt;assignees: []&lt;/code&gt; even though the assign job logged "assigned 9". That is why his Plane board showed no work to do.&lt;/p&gt;

&lt;p&gt;I isolated it by assigning a known-good member instead: Jeremy, a workspace admin. That worked instantly. Assign Ezekiel and it silently no-ops. Same code path, same 200. The difference was project membership.&lt;/p&gt;

&lt;p&gt;I fixed it two ways. Added Ezekiel to the CONTENT project and back-assigned all 10 existing cards, the nine broken Omarchy cards plus the one for that day's post. Then &lt;code&gt;blog-plane-card.py&lt;/code&gt; now calls &lt;code&gt;ensure_project_member&lt;/code&gt; idempotent on every run, so this cannot silently recur.&lt;/p&gt;

&lt;p&gt;One more Plane API quirk: assignees must be set in their own dedicated PATCH. Plane ignores an &lt;code&gt;assignees&lt;/code&gt; field mixed into a create or update payload.&lt;/p&gt;

&lt;p&gt;Verification: card created for the live post (HTTP 201). Re-run updates instead of duplicates (still exactly 1 card). Assignment confirmed by read-back. All 10 content cards now read &lt;code&gt;assignees=[ezekiel]&lt;/code&gt;. Clean end-to-end run prints "updated card ... (HTTP 200)" with no error note.&lt;/p&gt;

&lt;h2&gt;
  
  
  The correction that shrank the design
&lt;/h2&gt;

&lt;p&gt;The Plane card did not start out as one line in an existing job. The first pass at it was a tracking subsystem: a new state file, an ingest reconciler, its own cron entry.&lt;/p&gt;

&lt;p&gt;The correction came in voice dictation, so the transcript caught it garbled: "please dont make it comicates alproach it with simixty also." Cleaned up, that is "don't make it complicated, approach it with simplicity."&lt;/p&gt;

&lt;p&gt;What survived the correction was one sentence: add one step to the 05:00 packet job, so when Ezekiel gets his email he also gets a Plane card. Nothing else changes. The email stays. No new cron entry, no reconciler, no new state file.&lt;/p&gt;

&lt;p&gt;That is what shipped. Commit &lt;code&gt;add88e64&lt;/code&gt; is 17 changed lines in &lt;code&gt;blog-posting-packet.sh&lt;/code&gt; plus a 194-line &lt;code&gt;blog-plane-card.py&lt;/code&gt;. The rejected design would have added a fourth moving part to a pipeline whose whole problem that morning was that its existing parts were too entangled with each other.&lt;/p&gt;

&lt;p&gt;Worth being precise about what the models did here, because it was four of them across one long day. &lt;code&gt;Claude Opus 4.8&lt;/code&gt; and &lt;code&gt;Claude Opus 5&lt;/code&gt; carried the blog pipeline thread, including the preflight diagnosis and the scoping fix. &lt;code&gt;Claude Sonnet 5&lt;/code&gt; picked up shorter turns in the same tree. &lt;code&gt;Claude Fable 5&lt;/code&gt; ran the parallel Buzz investigation, which is where most of the day's errors landed: 34 of them across 847 minutes, against production Postgres auth logs over SSH. Across every session the day logged 474 tool calls, 40 failure-to-fix arcs, and 3 course-corrections in a 1112 minute span.&lt;/p&gt;

&lt;p&gt;The three corrections are the part worth keeping. None of them were "that code is wrong." All three were scope corrections: fold this into what already exists, go verify the thing actually ran, make it smaller. The elaborate version got built competently on the first pass. What it did not get was a check on whether the problem deserved that much machinery, and on this day that check is the only thing that kept a task board from becoming a subsystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The through-line
&lt;/h2&gt;

&lt;p&gt;Both fixes narrow what a piece of code claims authority over. The preflight claimed authority over the whole working tree when it only writes four paths. The assign call treated a 200 as proof the assignment happened, when all the 200 actually confirmed was that the request had been accepted.&lt;/p&gt;

&lt;p&gt;The Plane fix did not literally remove code. It added a membership check and a second PATCH. What it narrowed was the claim: the assign call stopped treating an accepted request as a completed one. In both cases the code asserted something it did not govern, and the fix was to make the claim match the control.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Omarchy marketplace submission sweep.&lt;/strong&gt; Eleven widget entry repos plus the shared template: Capture Conveyor, Desk Transition, Docket, Flow Boundary, Crew Chief, Foundry, Workspace Storyboard, Wait State, Quiet Queue, Listening Post, Loose Ends. The commit subjects run to "marketplace-ready" and "production certified", which is the repos' own shorthand and worth deflating here: what was actually established is that each widget loaded in a fresh Omarchy shell on the Buzz rig, with render receipts bound to the raw shell logs and runtime evidence kept separate from visual evidence. Submission is a filing, not an approval. That was breadth rather than depth, and it is not what made the day interesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate C43, the Omarchy marketplace presentation guard.&lt;/strong&gt; Landed at 16:38 as 163 lines plus a 119-line bats suite, wired into CI, then tightened four more times the same day: 16:45, 17:41, 18:08, and 20:36. Each tightening closed something the previous version had let through. It checks that a manifest description uses the full 500-character allowance the catalog schema permits, that a bar widget description matches it rather than telling a different product story, and that the copy names the product, says what the user can see or do, and states a trust boundary. Requiring the full allowance is an unusual rule, and the reason given in the gate is blunt: every short description that escaped was generic. Five revisions in four hours is its own small lesson about writing gates, and it deserves its own post rather than a paragraph here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hermes trust boundaries hardened in &lt;code&gt;claude-code-plugins&lt;/code&gt; (PR 1383).&lt;/strong&gt; Split the contribute skill into read-only, prepare, and publish surfaces, dropped the automatic install-persistence hooks, and required explicit state and workspace paths. Merged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Buzz forensics, unresolved.&lt;/strong&gt; A separate thread that started as "save my automations and plan a clean reinstall" turned into reading production Postgres auth logs over SSH, per-pubkey auth successes and full connection lifecycles. It did not resolve into a shipped fix that day.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/every-safety-gate-has-a-failure-direction/" rel="noopener noreferrer"&gt;Every Safety Gate Has a Failure Direction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/a-green-result-only-covers-what-it-ran/"&gt;A Green Result Only Covers What It Ran&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/gate-the-statement-not-the-tool-name/" rel="noopener noreferrer"&gt;Gate the Statement, Not the Tool Name&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>debugging</category>
      <category>cicd</category>
    </item>
    <item>
      <title>A Path Is Not Proof of Identity</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Mon, 31 Aug 2026 10:18:20 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/a-path-is-not-proof-of-identity-1ad7</link>
      <guid>https://dev.to/jeremy_longshore/a-path-is-not-proof-of-identity-1ad7</guid>
      <description>&lt;p&gt;Five marketplace submissions rejected simultaneously for the same security defect class. Every one created local state under the default umask, checked permissions with &lt;code&gt;[[ -f ]]&lt;/code&gt;, then wrote to the name later. Between the check and the write, a same-UID attacker could plant a symlink at that path, and the open would follow it. The first remediation looked like the textbook answer: &lt;code&gt;umask 077&lt;/code&gt;, &lt;code&gt;stat -c %s&lt;/code&gt; for size, &lt;code&gt;timeout 2&lt;/code&gt; on jq, and &lt;code&gt;mktemp + mv&lt;/code&gt; for atomic writes. The reviewer rejected that too.&lt;/p&gt;

&lt;p&gt;The reason is this: &lt;code&gt;[[ -f ]]&lt;/code&gt; resolves the path, &lt;code&gt;stat&lt;/code&gt; resolves it again, and &lt;code&gt;write_session()&lt;/code&gt; resolves it a third time. Nothing binds those three calls to the same inode. A path is a name. A name is resolved fresh on every syscall. Checking a name and then acting on it is a race condition, specifically a TOCTOU (time-of-check-time-of-use) bug. You cannot fix that bug in a language whose only handle is a name.&lt;/p&gt;

&lt;h2&gt;
  
  
  The defect class: a symlink race in local state
&lt;/h2&gt;

&lt;p&gt;Five Omarchy plugin submissions hit this defect simultaneously (marketplace issues #2899 through #2903). Each plugin's shell helper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;created &lt;code&gt;~/.local/state/&amp;lt;plugin&amp;gt;/&lt;/code&gt; under the default umask, so it was group/world readable during creation&lt;/li&gt;
&lt;li&gt;wrote to a state file via &lt;code&gt;&amp;gt; "$file"&lt;/code&gt; or &lt;code&gt;&amp;gt;&amp;gt; "$file"&lt;/code&gt;, which follows a pre-existing symlink&lt;/li&gt;
&lt;li&gt;read the whole mutable file into jq with no regular-file check, no byte ceiling, and no timeout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A symlink planted at the state path redirects the write to any file the user owns. That is a plain symlink attack, and nothing in the helper was positioned to notice it. A FIFO or oversized file at the path hangs the jq that the QML side polls every five seconds.&lt;/p&gt;

&lt;p&gt;The contributing-clanker lane (the shared security gate suite) told itself those places were safe. It enforced gates on network input, on QML rendering, on command construction. It never modeled filesystem object identity. A gate lane's blind spot is exactly where threat lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round one: the rejection
&lt;/h2&gt;

&lt;p&gt;The first remediation shipped what looked like a complete answer. Quiet Queue's round-one attempt (commit 5c7a817):&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;umask &lt;/span&gt;077
&lt;span class="nv"&gt;root&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;XDG_STATE_HOME&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;/.local/state&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/omarchy-quiet-queue"&lt;/span&gt;
&lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;/session.json"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;session_max_bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4096
read_session&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;filter&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;default&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; size
  &lt;span class="k"&gt;if&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;$session&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session&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="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$default&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;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi
  &lt;/span&gt;&lt;span class="nv"&gt;size&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;stat&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; %s &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session&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;printf &lt;/span&gt;0&lt;span class="si"&gt;)&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; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$size&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^[0-9]+&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; size &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; session_max_bytes &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="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$default&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;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi
  &lt;/span&gt;&lt;span class="nb"&gt;timeout &lt;/span&gt;2 jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$filter&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session&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;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$default&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

write_session&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;tmp
  &lt;span class="nv"&gt;tmp&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;mktemp&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;/.session.XXXXXX"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$tmp&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;mv&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;$tmp&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That closes a descriptor and then reopens a mutable pathname. The &lt;code&gt;[[ -f ]]&lt;/code&gt; check, then &lt;code&gt;stat&lt;/code&gt;, then &lt;code&gt;jq&lt;/code&gt; are three separate path resolutions. Nothing binds them to the same inode. Between &lt;code&gt;stat&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt;, a same-UID competitor swaps the file for a symlink. The &lt;code&gt;write_session&lt;/code&gt; function creates a temp file inside the private directory, but &lt;code&gt;mktemp&lt;/code&gt; and &lt;code&gt;mv&lt;/code&gt; each re-resolve &lt;code&gt;$root&lt;/code&gt;. Rename &lt;code&gt;$root&lt;/code&gt; to &lt;code&gt;.parked&lt;/code&gt;, plant a symlink at &lt;code&gt;$root&lt;/code&gt; pointing anywhere, and both calls land inside the attacker's target. The reviewer said no.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not the obvious approach?
&lt;/h2&gt;

&lt;p&gt;The obvious move was to keep the helpers in bash and add more checks. Bash already powers every other plugin helper. The linting infrastructure already knew how to read it. Adding &lt;code&gt;[[ -f ]]&lt;/code&gt;, &lt;code&gt;stat&lt;/code&gt;, and &lt;code&gt;timeout&lt;/code&gt; is cheap.&lt;/p&gt;

&lt;p&gt;It lost because bash has no way to hold a file descriptor across operations. There is no &lt;code&gt;fstat&lt;/code&gt;, no &lt;code&gt;O_NOFOLLOW&lt;/code&gt;, no &lt;code&gt;O_DIRECTORY&lt;/code&gt;. Every check bash can express is a check on a name, not on an object. You cannot fix a TOCTOU bug in a language whose only handle is a name. Leaving bash meant a rewrite of six helpers, a tool orthogonal to the rest of the codebase, and an interpreter that immediately tripped an existing gate banning Perl shebangs as a non-guaranteed runtime (resolved below, in the same commit that taught C41 to see the new helpers). That cost is real. But it is the only honest fix.&lt;/p&gt;

&lt;p&gt;Every round-one control has a round-two replacement, and the difference is always the same one thing: whether the check and the use touch the same object.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Round one, resolved by name&lt;/th&gt;
&lt;th&gt;Round two, bound to a descriptor&lt;/th&gt;
&lt;th&gt;What changes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;[[ -f "$session" ]]&lt;/code&gt; then read&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;sysopen($fh, ...)&lt;/code&gt; then &lt;code&gt;stat($fh)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The thing checked is the thing read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mkdir -p&lt;/code&gt; plus &lt;code&gt;umask 077&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;sysopen(O_DIRECTORY, O_NOFOLLOW)&lt;/code&gt; then &lt;code&gt;chdir&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The parent cannot be swapped after the check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mktemp&lt;/code&gt; then &lt;code&gt;mv&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;sysopen(O_CREAT, O_EXCL, O_NOFOLLOW)&lt;/code&gt; then &lt;code&gt;rename&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;No window to adopt a file you did not create&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;stat -c %s&lt;/code&gt; then &lt;code&gt;jq&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;byte ceiling taken from &lt;code&gt;stat($fh)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The size checked is the size read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeout 2 jq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;O_NONBLOCK&lt;/code&gt; at open, then the &lt;code&gt;-f&lt;/code&gt; test on &lt;code&gt;stat($fh)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;A FIFO cannot stall the open, and the regular-file check rejects it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Descriptor-bound lifecycles
&lt;/h2&gt;

&lt;p&gt;Round two (commit 229d6d4) rewrote the runtime helpers from bash to Perl. The key move: hold the state directory open from the start and never let it go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;umask&lt;/span&gt; &lt;span class="mo"&gt;0077&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File::&lt;/span&gt;&lt;span class="nv"&gt;Spec&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;catdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;omarchy-quiet-queue&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;span class="nv"&gt;make_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mo"&gt;0700&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;sysopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;O_RDONLY&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;O_DIRECTORY&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;O_NOFOLLOW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unsafe state directory&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@ds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unsafe state directory&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;@ds&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="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$ds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="mo"&gt;0700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;chdir&lt;/span&gt; &lt;span class="nv"&gt;$dir&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cannot pin state directory&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;O_NOFOLLOW&lt;/code&gt; refuses a planted symlink at open time instead of after. &lt;code&gt;O_DIRECTORY&lt;/code&gt; means the kernel will not open this if it is not a directory. &lt;code&gt;O_RDONLY&lt;/code&gt; is the minimum. &lt;code&gt;stat($dir)&lt;/code&gt; on the open filehandle (the &lt;code&gt;$dir&lt;/code&gt; object you hold, not the name) proves you own it. &lt;code&gt;chdir $dir&lt;/code&gt; pins the parent so later relative opens like &lt;code&gt;session.json&lt;/code&gt; resolve inside the object you hold, not inside a path an attacker swapped.&lt;/p&gt;

&lt;p&gt;The read side stats the open descriptor, not the name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;read_session&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="k"&gt;until&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;owned&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;JSON::PP::&lt;/span&gt;&lt;span class="nv"&gt;false&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$fh&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="k"&gt;until&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;owned&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;JSON::PP::&lt;/span&gt;&lt;span class="nv"&gt;false&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nb"&gt;sysopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;O_RDONLY&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;O_NONBLOCK&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;O_NOFOLLOW&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@st&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@st&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="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$st&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$st&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$st&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;$max_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;close&lt;/span&gt; &lt;span class="nv"&gt;$fh&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="k"&gt;until&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;owned&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;JSON::PP::&lt;/span&gt;&lt;span class="nv"&gt;false&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="c1"&gt;# read from $fh...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;stat($fh)&lt;/code&gt; interrogates the object you actually hold. &lt;code&gt;O_NONBLOCK&lt;/code&gt; means a FIFO cannot stall the open, which a blocking &lt;code&gt;O_RDONLY&lt;/code&gt; on a FIFO would do until a writer showed up. It does not reject the FIFO by itself. The &lt;code&gt;-f _&lt;/code&gt; test against &lt;code&gt;stat($fh)&lt;/code&gt; on the next line does that. The &lt;code&gt;$st[4] == $&amp;lt;&lt;/code&gt; check verifies you own this inode. The byte ceiling is enforced against the object, not a name that could be swapped between the check and the enforcement.&lt;/p&gt;

&lt;p&gt;The write side uses &lt;code&gt;O_EXCL&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;open_temp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.session.%d.%08x&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="vg"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$fh&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="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;sysopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;O_WRONLY&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;O_CREAT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;O_EXCL&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;O_NOFOLLOW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mo"&gt;0600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cannot create private session temp&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;write_session&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;open_temp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;encode_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$offset&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="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$offset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;length&lt;/span&gt; &lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;syswrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$offset&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;session write failed&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$offset&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;sync&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;session fsync failed&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="nb"&gt;close&lt;/span&gt; &lt;span class="nv"&gt;$fh&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;session close failed&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="nb"&gt;rename&lt;/span&gt; &lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;session replace failed&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="mo"&gt;0600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$session&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;code&gt;O_EXCL&lt;/code&gt; means you created it or you failed. There is no window where you adopt someone else's file. &lt;code&gt;fsync&lt;/code&gt; guarantees the data hits disk. &lt;code&gt;rename&lt;/code&gt; is atomic. Every flag is load-bearing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proving it with an adversary
&lt;/h2&gt;

&lt;p&gt;This is the second time this bug class has come up here. &lt;a href="https://startaitools.com/posts/codeql-caught-the-race-i-dismissed/" rel="noopener noreferrer"&gt;CodeQL caught the race I dismissed&lt;/a&gt; covers the same shape in TypeScript, where the fix was a same-descriptor &lt;code&gt;openSync&lt;/code&gt;, &lt;code&gt;fstatSync&lt;/code&gt;, &lt;code&gt;writeSync&lt;/code&gt; chain. Different language, identical lesson.&lt;/p&gt;

&lt;p&gt;A unit test that asserts "the file has mode 0600 and valid JSON" does not catch this bug. The bash version would pass that assertion while remaining vulnerable. The test had to become an attacker.&lt;/p&gt;

&lt;p&gt;Tests acquired a fixture that races the helper in a tight loop:&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;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;victim&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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;parked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.parked`&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(;;)&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renameSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parked&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;symlinkSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;victim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dir&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;unlinkSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&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;renameSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&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="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;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parked&lt;/span&gt;&lt;span class="p"&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="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&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;renameSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&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;This racer swaps the parent directory itself. The helper opens a relative path inside the state directory; if that directory is suddenly a symlink to somewhere else, the relative open lands elsewhere. The suite asserts the Perl helper holds under it. The bash version would not, by construction: nothing in it survives losing the parent, because everything in it is a fresh path lookup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encoding the lesson so it cannot recur
&lt;/h2&gt;

&lt;p&gt;Two gates joined the contributing-clanker lane on the same day (commit a3ab4eb):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C41: Fail-closed mutable state lifecycle&lt;/strong&gt; (204 lines). It blocks any helper that persists mutable state without a descriptor-bound primitive, testing for &lt;code&gt;openat&lt;/code&gt;, &lt;code&gt;renameat&lt;/code&gt;, &lt;code&gt;O_NOFOLLOW&lt;/code&gt; or a declared secure-state helper. &lt;code&gt;mktemp + mv&lt;/code&gt; and pathname &lt;code&gt;-f&lt;/code&gt; checks stop counting as proof, which is the whole point: they were the round-one answer. It separately refuses the lane unless the test corpus carries hostile final-entry, temp-entry, parent-swap and FIFO coverage. The gate blocks, it is not advisory, and its own regression case proves a state helper that trusts mutable pathnames after &lt;code&gt;mktemp&lt;/code&gt; now fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C42: Bounded local recurring scans&lt;/strong&gt; (134 lines). It targets the second class in the same review: a scan on a 5 or 20 second timer that buffers or sorts local input before applying its cap. &lt;code&gt;find | sort -z | head -25&lt;/code&gt; looks safe because the final output is capped, but &lt;code&gt;sort&lt;/code&gt; has already enumerated the whole directory. C42 warns rather than blocks, so it flags the shape without failing a submission on it.&lt;/p&gt;

&lt;p&gt;Widget template commit 516ccd8 vendored both gates so new plugins inherit them. The &lt;code&gt;/omarchy-ship&lt;/code&gt; submission auditor now refuses CLEAN status without descriptor-bound lifecycle evidence and hostile parent-swap, temp-entry, final-entry, FIFO, and oversized-input proofs.&lt;/p&gt;

&lt;p&gt;Then the new gate had to be debugged against the code it had just forced into existence.&lt;/p&gt;

&lt;p&gt;Commit 6d924f3: C41 selected runtime files by &lt;code&gt;.sh&lt;/code&gt;/&lt;code&gt;.bash&lt;/code&gt; extension or by a shell shebang, which covered the extensionless bash helpers fine. Then the helpers stopped being shell. A &lt;code&gt;#!/usr/bin/perl&lt;/code&gt; first line matches neither test, so the newly rewritten helpers were invisible to the gate written to check them. The fix extended the shebang match to &lt;code&gt;#!/usr/bin/perl&lt;/code&gt;. The same commit had to settle a second collision. C35 (runtime-dependency, an older gate) banned Perl shebangs outright as an interpreter a stock Omarchy install does not guarantee, so the safe rewrite tripped a different gate. Perl was unbanned there because it is a base dependency on the Buzz image, but only with an absolute system shebang, never &lt;code&gt;env&lt;/code&gt;, so the session PATH cannot swap the interpreter.&lt;/p&gt;

&lt;p&gt;Commit c9c52ed: C41's redirect heuristic was &lt;code&gt;&amp;gt;&amp;gt;?\s*"?\$\w+&lt;/code&gt;, matching &lt;code&gt;&amp;gt; $file&lt;/code&gt; and &lt;code&gt;&amp;gt;&amp;gt; $file&lt;/code&gt;. It also matched Perl's fat comma &lt;code&gt;key =&amp;gt; $value&lt;/code&gt; as a shell redirection. A negative lookbehind fixed it: &lt;code&gt;(?&amp;lt;!=)&amp;gt;&amp;gt;?\s*"?\$\w+&lt;/code&gt;. Do not flag &lt;code&gt;=&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Commit 7d22a5c: That lookbehind was then replaced with a simpler rule. The heuristic was being ported to Perl, and porting a regex to a second language keeps its syntax assumptions. &lt;code&gt;@items &amp;gt; $limit&lt;/code&gt; is not a redirection either. The honest fix was to scope the heuristic: run the redirect check on shell helpers only. Perl lifecycle safety is established by the descriptor checks themselves, not by a regex that keeps collecting exceptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The audit that refused the claim
&lt;/h2&gt;

&lt;p&gt;The gate work has a mirror at the estate level, and it ran the same night. A gate that passes on a file it never opened and a green CI badge for a check that never ran are the same error: a name standing in for the thing itself. Late the same evening came a 168-line estate readiness audit (omarchy &lt;code&gt;000-docs/004-AA-AUDT-omarchy-estate-readiness-2026-08-29.md&lt;/code&gt;). It found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;16/16 worktrees clean, git fsck clean, 444/444 local tests pass across 16 repos, all hosted gates green&lt;/li&gt;
&lt;li&gt;but: CI proves static and unit tests, NOT a running Omarchy shell. No repo's GitHub workflow executes &lt;code&gt;rig-verify.sh&lt;/code&gt; or &lt;code&gt;rig-render.sh&lt;/code&gt;. A green hosted workflow does not prove a plugin loads. Current-source rig proof exists only for Desk Transition, Foundry, and Crew Chief. Widget Template has no proof receipt at all.&lt;/li&gt;
&lt;li&gt;9 live listings, but only Listening Post's validated commit matches its current head. The other eight reference older snapshots.&lt;/li&gt;
&lt;li&gt;None of the 16 mains has branch protection. 15/16 use mutable action tags. Six repos declare coverage thresholds but invoke raw &lt;code&gt;node --test&lt;/code&gt;, bypassing the threshold command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The audit explicitly refused a "best in class" or "fully production certified" claim. It prescribed the honest public status instead: "16 maintained Omarchy plugin repositories; 9 live marketplace listings; all local suites currently green; marketplace verification and production-render certification are tracked per exact commit."&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;claude-code-plugins ed4765e43: enforce marketplace compliance metric ratchets in CI&lt;/li&gt;
&lt;li&gt;intent-blueprint-docs b9297e0: model-neutral documentation platform; 29c2fd8 made package validation race-free (another race, same week)&lt;/li&gt;
&lt;li&gt;omarchy-desk-transition-entry 2e06d94: capture desk transition with active outputs&lt;/li&gt;
&lt;li&gt;omarchy-crew-chief-entry 0ef344e: harden process arguments, proven on the real rig, validator and QML-lint receipts both zero-error, local suite 25/25&lt;/li&gt;
&lt;li&gt;omarchy-workspace-storyboard-entry e597cdc: pin current Node 24 actions&lt;/li&gt;
&lt;li&gt;omarchy-widget-template 868d0f5: land governance scaffolding (editorconfig, gitattributes, issue and PR templates, dependabot, CODE_OF_CONDUCT, CONTRIBUTING, SECURITY)&lt;/li&gt;
&lt;li&gt;omarchy 6f2e2b7 and bfdabf5: refresh live marketplace metrics from scripts/refresh-metrics.sh&lt;/li&gt;
&lt;li&gt;github-profile 6630095 and 23f4930: swap in the cityscape avatar, remove dead embeds, drop a Projects badge GitHub already renders&lt;/li&gt;
&lt;li&gt;comehomealabama 4dea5f5: a journal post shipped through the sibling pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those touched a descriptor. The ones that did were the six helpers a reviewer had already sent back twice, and the gate that had to be taught to see them.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/gate-the-statement-not-the-tool-name/" rel="noopener noreferrer"&gt;Gate the Statement, Not the Tool Name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/every-safety-gate-has-a-failure-direction/" rel="noopener noreferrer"&gt;Every Safety Gate Has a Failure Direction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/honor-the-gate-when-the-verdict-is-inconvenient/" rel="noopener noreferrer"&gt;Honor the Gate When the Verdict Is Inconvenient&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>testing</category>
      <category>debugging</category>
      <category>devops</category>
    </item>
    <item>
      <title>Bind the Receipt to the Commit It Installed</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Sat, 29 Aug 2026 11:30:12 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/bind-the-receipt-to-the-commit-it-installed-110m</link>
      <guid>https://dev.to/jeremy_longshore/bind-the-receipt-to-the-commit-it-installed-110m</guid>
      <description>&lt;p&gt;An end to end lane that installs your plugin from GitHub is testing whatever GitHub happened to&lt;br&gt;
serve. That is usually your latest push. It is sometimes a push from twenty minutes ago, a cached&lt;br&gt;
object, or a branch you forgot you were on. The lane passes either way, and the receipt it writes&lt;br&gt;
looks identical either way.&lt;/p&gt;

&lt;p&gt;That is the gap I closed on the Foundry rig lane. The receipt now carries the commit hash of the&lt;br&gt;
artifact that was actually installed, and the harness refuses to write the file unless that hash&lt;br&gt;
equals local &lt;code&gt;HEAD&lt;/code&gt;. Test provenance is now checkable, not decorative.&lt;/p&gt;
&lt;h2&gt;
  
  
  How do you verify an E2E test installed the correct commit?
&lt;/h2&gt;

&lt;p&gt;Read &lt;code&gt;HEAD&lt;/code&gt; out of the installed tree on the rig, put it on the receipt line, parse that line on the&lt;br&gt;
local side with an anchored regex, and compare the captured hash against local &lt;code&gt;HEAD&lt;/code&gt;. The receipt&lt;br&gt;
must carry both commits and pass both checks before the proof file is written. A fixed string&lt;br&gt;
receipt proves only that &lt;code&gt;echo&lt;/code&gt; works.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Foundry is, so the test makes sense
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omarchy-foundry-entry&lt;/code&gt; is a new repo, created this day, twelve commits on first parent. It is an&lt;br&gt;
Omarchy plugin that generates a starter plugin tree for a small bar widget: manifest, QML entry&lt;br&gt;
point, a pure data &lt;code&gt;Model.js&lt;/code&gt;, an offline test, README, license, SVG banner.&lt;/p&gt;

&lt;p&gt;The README is blunt about the boundary. Foundry is "intentionally a scaffold and proof surface,&lt;br&gt;
not an autonomous shell agent, plugin store, or publisher," and it "never installs, enables,&lt;br&gt;
commits, pushes, sends telemetry, or files a marketplace issue." Runtime dependencies are &lt;code&gt;bash&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;jq&lt;/code&gt;. Node is development only. It runs the generated test suite and is never needed by the&lt;br&gt;
widget at runtime. Until a validation lane runs, Foundry reports its proof state as &lt;code&gt;UNPROVEN&lt;/code&gt;,&lt;br&gt;
which is not the same word as failing.&lt;/p&gt;

&lt;p&gt;The initial commit was 2,614 insertions across 32 files, including nine gate scripts under&lt;br&gt;
&lt;code&gt;scripts/gates/&lt;/code&gt; (&lt;code&gt;c28-voice-no-dashes&lt;/code&gt;, &lt;code&gt;c29-private-names&lt;/code&gt;, &lt;code&gt;c30-md-strikethrough&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;c31-omarchy-qml-security&lt;/code&gt;, &lt;code&gt;c34-omarchy-exec-injection&lt;/code&gt;, &lt;code&gt;c35-omarchy-runtime-dependency&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;c36-omarchy-qml-overflow&lt;/code&gt;, &lt;code&gt;c38-omarchy-ssrf-host-allowlist&lt;/code&gt;, &lt;code&gt;c40-omarchy-panel-design&lt;/code&gt;) plus a&lt;br&gt;
293 line &lt;code&gt;minimax-review.yml&lt;/code&gt;. The scaffold itself landed in &lt;code&gt;43e5b11&lt;/code&gt;: &lt;code&gt;bin/omarchy-foundry&lt;/code&gt; at&lt;br&gt;
+135, &lt;code&gt;tests/foundry.test.js&lt;/code&gt; at +72, &lt;code&gt;Panel.qml&lt;/code&gt; at +66/-124, &lt;code&gt;Model.js&lt;/code&gt; at +23/-32.&lt;/p&gt;
&lt;h2&gt;
  
  
  The receipt that could not fail
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;scripts/rig-e2e.sh&lt;/code&gt; arrived at +45 lines in &lt;code&gt;615e61b&lt;/code&gt;, got hardened to +44/-36 in &lt;code&gt;ae779f9&lt;/code&gt;, and&lt;br&gt;
grew the real runtime certification at +81/-31 in &lt;code&gt;8b009f5&lt;/code&gt;. Its whole job is to prove something&lt;br&gt;
&lt;code&gt;rig-render.sh&lt;/code&gt; cannot: &lt;code&gt;rig-render&lt;/code&gt; tests Foundry's own panel, &lt;code&gt;rig-e2e&lt;/code&gt; tests the artifact&lt;br&gt;
Foundry generates.&lt;/p&gt;

&lt;p&gt;The first two of those had no receipt line at all, just a PASS echo. &lt;code&gt;8b009f5&lt;/code&gt; introduced one,&lt;br&gt;
and for three commits it was a fixed string:&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"E2E_RECEIPT foundry=github generated=file-git node=shadowed hostile_id=refused shell=loaded"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the local side matched it against the same fixed string. Read that line as an assertion and it&lt;br&gt;
says nothing. &lt;code&gt;foundry=github&lt;/code&gt; is not a measurement of where the plugin came from. It is a literal&lt;br&gt;
I typed, reprinted back to me by a shell that would have printed it regardless. Every field on the&lt;br&gt;
line was load bearing except the two that described provenance, and those were decorative.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;9d6cfc8&lt;/code&gt; fixed it in +9/-3 on the harness and +15 on &lt;code&gt;bin/omarchy-foundry&lt;/code&gt;. The remote side now&lt;br&gt;
reads the installed tree's HEAD, the generated tree's HEAD, and puts both on the wire:&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;foundry_commit&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;$foundry&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;# ...&lt;/span&gt;
&lt;span class="nv"&gt;generated_commit&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;$generated&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"E2E_RECEIPT installed_foundry=&lt;/span&gt;&lt;span class="nv"&gt;$foundry_commit&lt;/span&gt;&lt;span class="s2"&gt; generated_tree=&lt;/span&gt;&lt;span class="nv"&gt;$generated_commit&lt;/span&gt;&lt;span class="s2"&gt; node=shadowed hostile_id=refused shell=loaded"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The local side stopped comparing strings and started parsing:&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="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LINE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^E2E_RECEIPT&lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nv"&gt;installed_foundry&lt;/span&gt;&lt;span class="o"&gt;=([&lt;/span&gt;0-9a-f]&lt;span class="o"&gt;{&lt;/span&gt;40&lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nv"&gt;generated_tree&lt;/span&gt;&lt;span class="o"&gt;=([&lt;/span&gt;0-9a-f]&lt;span class="o"&gt;{&lt;/span&gt;40&lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nv"&gt;node&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;shadowed&lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nv"&gt;hostile_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;refused&lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nv"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;loaded&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &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;"rig-e2e: missing or malformed receipt line"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;INSTALLED_COMMIT&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;BASH_REMATCH&lt;/span&gt;&lt;span class="p"&gt;[1]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;GENERATED_COMMIT&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;BASH_REMATCH&lt;/span&gt;&lt;span class="p"&gt;[2]&lt;/span&gt;&lt;span class="k"&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;$INSTALLED_COMMIT&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;$COMMIT&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="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"rig-e2e: installed GitHub artifact (&lt;/span&gt;&lt;span class="nv"&gt;$INSTALLED_COMMIT&lt;/span&gt;&lt;span class="s2"&gt;) does not match local commit (&lt;/span&gt;&lt;span class="nv"&gt;$COMMIT&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The anchored regex matters as much as the equality check. A receipt that can be matched loosely is&lt;br&gt;
a receipt that can be matched by a partial line, and the failure mode of a partial line is a pass.&lt;/p&gt;

&lt;p&gt;Only after both checks does &lt;code&gt;jq&lt;/code&gt; write &lt;code&gt;.rig-e2e-proof.json&lt;/code&gt;. Here is what landed:&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;"commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9d6cfc8316b4e58695057027bdd16cb0a891c5ff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"installedFoundryCommit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9d6cfc8316b4e58695057027bdd16cb0a891c5ff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"generatedTreeCommit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0d4a667e408a4aac56ce91c9ef490fe348dacfe3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rig"&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-ops-buzz/omarchy-rig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"foundryOrigin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"generatedOrigin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"file-git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shadowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hostileId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"refused"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"generatedShell"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"loaded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"completedAt"&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-28T04:13:20Z"&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;Two fields with the same forty characters. That repetition is the entire assertion, and it is&lt;br&gt;
visible in the artifact instead of buried in the harness. A reader can check it without reading&lt;br&gt;
the script. Being honest about the sequence: the first receipt landed in &lt;code&gt;f7be14d&lt;/code&gt; without an&lt;br&gt;
&lt;code&gt;installedFoundryCommit&lt;/code&gt; field at all, and the version above was refreshed into place three commits&lt;br&gt;
later in &lt;code&gt;1ccaa75&lt;/code&gt;. The proof got the field before the proof was correct.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.rig-proof.json&lt;/code&gt; sits alongside it, written by a different script for a different reason.&lt;br&gt;
&lt;code&gt;scripts/rig-verify.sh&lt;/code&gt; does its own round trip to the rig and records&lt;br&gt;
&lt;code&gt;omarchyPluginValidate: 0&lt;/code&gt;, &lt;code&gt;qmllintErrors: 0&lt;/code&gt;, and fingerprint &lt;code&gt;913620eb&lt;/code&gt;. Its header explains&lt;br&gt;
why it has to exist: gates C32 and C33 in the shared runner (not among the nine in this repo) call &lt;code&gt;gate_skip&lt;/code&gt; when &lt;code&gt;omarchy-plugin-validate&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;qmllint&lt;/code&gt; are not on the local box, and they never are, because they live on the rig. The gate&lt;br&gt;
runner counts SKIP as pass, so the submission lane "happily printed verdict PASS, 0 BLOCK for a&lt;br&gt;
plugin that had never run on Omarchy at all." That is the same failure the E2E receipt had, one&lt;br&gt;
layer down. (&lt;code&gt;rig-render.sh&lt;/code&gt; is a third lane again: it screenshots the panel and writes&lt;br&gt;
&lt;code&gt;preview.png&lt;/code&gt;.)&lt;/p&gt;
&lt;h2&gt;
  
  
  What the lane actually does on the rig
&lt;/h2&gt;

&lt;p&gt;It SSHes to a real Omarchy rig (&lt;code&gt;intent-ops-buzz&lt;/code&gt;, container &lt;code&gt;omarchy-rig&lt;/code&gt;) and runs a chain where&lt;br&gt;
each step's failure is a real exit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Installs the plugin from its GitHub URL, not from the local working tree.&lt;/li&gt;
&lt;li&gt;Reads the installed commit and compares it to local HEAD.&lt;/li&gt;
&lt;li&gt;Generates a starter plugin and runs its offline tests, &lt;code&gt;omarchy-plugin-validate&lt;/code&gt;, and &lt;code&gt;qmllint&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Git commits the generated tree and installs that via &lt;code&gt;file://&lt;/code&gt;, then confirms it reports
enabled in &lt;code&gt;omarchy plugin list --json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Shadows Node and boots the real Quickshell session headless under sway.&lt;/li&gt;
&lt;li&gt;Greps the shell log for load errors, filtering known headless noise.&lt;/li&gt;
&lt;li&gt;Screenshots with &lt;code&gt;grim&lt;/code&gt; and asserts the PNG is at least 4000 bytes.&lt;/li&gt;
&lt;li&gt;Asserts a hostile plugin id is refused.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 5 is the one I like. The README claims Node is development only. That claim is cheap to write&lt;br&gt;
and easy to be wrong about, because a machine that has Node installed will never tell you when&lt;br&gt;
something quietly reached for it. So the lane makes the claim expensive:&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 stock graphical session does not need Node. Put a failing node first on the&lt;/span&gt;
&lt;span class="c"&gt;# path and prove the generated plugin still loads in a real shell.&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /tmp/foundry-nonode
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'#!/bin/sh\nexit 127\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/tmp/foundry-nonode/node
&lt;span class="nb"&gt;chmod &lt;/span&gt;755 /tmp/foundry-nonode/node
&lt;span class="c"&gt;# ... conditional headless sway launch, then pkill any running qs ...&lt;/span&gt;
&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/foundry-nonode:/root/omarchy/bin:/usr/bin:/bin qs &lt;span class="nt"&gt;-p&lt;/span&gt; /root/omarchy/shell &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/tmp/foundry-generated-qs.log 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fake &lt;code&gt;node&lt;/code&gt; that exits 127, first on PATH, and then a real shell session on top of it. If the&lt;br&gt;
widget touches Node at runtime, the session tells you. The hostile id (&lt;code&gt;io.github.e2e.bad;dispatch&lt;/code&gt;)&lt;br&gt;
gets the same treatment: the test passes only when the create call fails.&lt;/p&gt;

&lt;p&gt;Step 6 deserves an honest note. The noise filter is the one place where this lane can quietly stop&lt;br&gt;
failing. &lt;code&gt;c033583&lt;/code&gt; is a single changed line that added &lt;code&gt;pw_loop_new&lt;/code&gt; and &lt;code&gt;pw.loop&lt;/code&gt; to the exclude&lt;br&gt;
list and made that second grep case insensitive, because pipewire on a headless rig emits errors&lt;br&gt;
that have nothing to do with the plugin. That is a correct fix and also a widening of the blind&lt;br&gt;
spot. Every entry in that exclude list is a category of real error the lane will now swallow, and&lt;br&gt;
the list only ever grows. I would rather write that down than pretend the filter is free.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;926835f&lt;/code&gt; on the same day is 0 insertions and 0 deletions: a mode change restoring the executable&lt;br&gt;
bit on the harness. A test that cannot execute is not a failing test, it is an absent one.&lt;/p&gt;

&lt;p&gt;The obvious alternatives all lose for the same reason. Installing from the local working tree is&lt;br&gt;
the easiest lane to write and it tests the wrong artifact: nobody installs your working tree.&lt;br&gt;
Trusting the git ref you just pushed proves what you intended to publish, not what the remote&lt;br&gt;
served back. And comparing the receipt against a fixed string, which is what this lane did for&lt;br&gt;
three commits, proves that &lt;code&gt;echo&lt;/code&gt; works. Only reading HEAD out of the installed tree and comparing&lt;br&gt;
it locally closes the loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The badge that was allowed to be wrong
&lt;/h2&gt;

&lt;p&gt;The day's other decision was on the GitHub profile README, and it went the other way for the same&lt;br&gt;
reason.&lt;/p&gt;

&lt;p&gt;Session one: seven stargazer badges rendering broken. The obvious guess is that repos went private&lt;br&gt;
or got renamed, so that got checked first. All seven were public with stars (2,679 / 0 / 37 / 5 /&lt;br&gt;
12 / 1 / 27), which eliminated the repo hypothesis and pointed at the URL. Root cause was a raw&lt;br&gt;
star emoji in the shields.io query string. Unencoded it returns HTTP 400 and zero bytes. As&lt;br&gt;
&lt;code&gt;%E2%AD%90&lt;/code&gt; it returns HTTP 200 and renders. One character, seven badges. Two hero counts were also&lt;br&gt;
understating, so they were bumped to 3k+ and 150+ (stars read 2.5k+ against 3,016 actual,&lt;br&gt;
projects read 125+ against 151), and every&lt;br&gt;
badge in the file got re-fetched afterward, not just the changed ones: 27 OK, 0 broken.&lt;/p&gt;

&lt;p&gt;Session two, the ask was to make both hero badges dynamic. Only one of them became dynamic.&lt;/p&gt;

&lt;p&gt;Stars has a shields built in account level endpoint, &lt;code&gt;github/stars/jeremylongshore?affiliations=OWNER&lt;/code&gt;,&lt;br&gt;
served from shields' own authenticated GitHub tokens. Six consecutive fetches, six returned 3.1k.&lt;br&gt;
That is a different number from session one's 3,016 for two reasons: the non-fork count had&lt;br&gt;
ticked to 3,017 by then, and the account level endpoint also counts forks, which takes it to&lt;br&gt;
3,076.&lt;br&gt;
Projects has no built in equivalent. The only route is the generic &lt;code&gt;dynamic/json&lt;/code&gt; badge pointed at&lt;br&gt;
&lt;code&gt;api.github.com&lt;/code&gt;, which proxies the unauthenticated GitHub API: 60 requests per hour, shared across&lt;br&gt;
everyone on the internet using it. Five consecutive fetches of that exact URL returned&lt;br&gt;
&lt;code&gt;invalid / 151 / 151 / 151 / invalid&lt;/code&gt;. Two of five failed.&lt;/p&gt;

&lt;p&gt;So Projects stayed hardcoded at 150+ against an actual 151. &lt;code&gt;ce4d1b3&lt;/code&gt;, one line changed, and the&lt;br&gt;
commit message argues the case under a heading that says which of the two went live and why the&lt;br&gt;
other did not.&lt;/p&gt;

&lt;p&gt;The transferable part is the shape of the two wrongnesses. A hardcoded badge rounded down is wrong&lt;br&gt;
in a bounded, known direction, and it drifts slowly. A badge that renders the word "invalid" two&lt;br&gt;
times in five is wrong in an unbounded direction on the most viewed page you own, and it fails&lt;br&gt;
loudest in front of strangers. "Make it live" sounds like a preference. It is a request to add a&lt;br&gt;
dependency, and the answer to it is a measurement, not an opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  The version number that refused to move
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;intent-outreach v0.2.0&lt;/strong&gt;, &lt;code&gt;1b5b444d&lt;/code&gt;, merged as PR #34. A 2026-08-19 consistency audit had found&lt;br&gt;
the changelog two months stale. The release backfilled it, bumped 0.1.0 to 0.2.0 across&lt;br&gt;
&lt;code&gt;package.json&lt;/code&gt;, both plugin manifests, and the MCP server identity, regenerated the bundle so the&lt;br&gt;
CI freshness check holds, added a missing doc index entry, and corrected a README architecture&lt;br&gt;
diagram that omitted the &lt;code&gt;list_connectors&lt;/code&gt; MCP tool. Verified with a clean typecheck, 244/244&lt;br&gt;
vitest, and a passing offline eval gate.&lt;/p&gt;

&lt;p&gt;The decision there is the same refusal in a different costume: it cut a fresh 0.2.0 rather than&lt;br&gt;
amending the untagged 0.1.0, and gave 0.1.0 a retroactive tag at &lt;code&gt;ee6a2149&lt;/code&gt;, the real end of day&lt;br&gt;
June 16 commit. Reasoning from the commit body: 0.1.0's content shipped June 16, and rewriting its&lt;br&gt;
section to absorb two more months would falsify the release history. Version numbers are a claim&lt;br&gt;
about when something happened.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;intent-outreach&lt;/strong&gt; also merged PR #33 three minutes earlier, unrelated to the release: it gated&lt;br&gt;
OpenAI (gpt-4o) into &lt;code&gt;SUPPORTED_PROVIDERS&lt;/code&gt; through the eval harness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;omarchy-desk-transition-entry&lt;/strong&gt;: &lt;code&gt;9383567&lt;/code&gt; covered the monitor commands (&lt;code&gt;tests/helper.test.js&lt;/code&gt;&lt;br&gt;
+72), and &lt;code&gt;02c8814&lt;/code&gt; made the transition scenes previewable (&lt;code&gt;Panel.qml&lt;/code&gt; +155/-20, plus render and&lt;br&gt;
preview PNGs).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;omarchy&lt;/strong&gt;: &lt;code&gt;455e292&lt;/code&gt; started tracking submitted plugins in the README (+20/-5), and &lt;code&gt;496fcb2&lt;/code&gt;&lt;br&gt;
refreshed the live marketplace table (+10/-10).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;claude-code-plugins&lt;/strong&gt;: &lt;code&gt;9b57c6502&lt;/code&gt; gated exports before Dolt identity setup in&lt;br&gt;
&lt;code&gt;freshie/scripts/dolt-sync.py&lt;/code&gt; (+6/-1).&lt;/p&gt;

&lt;h2&gt;
  
  
  On the models
&lt;/h2&gt;

&lt;p&gt;Worth naming only because the split was clean. Claude Opus 5 ran both github-profile badge&lt;br&gt;
sessions, including the hypothesis test that eliminated repo visibility before anyone touched the&lt;br&gt;
URL. Claude Fable 5 ran the intent-outreach release. Claude Sonnet 5 was also in the day's roster.&lt;/p&gt;

&lt;p&gt;Zero course corrections in the transcript, which is not a boast. It means the day had one real&lt;br&gt;
investigation in it, the badge one, and the rest was building things that worked. The recorded&lt;br&gt;
failures on the dev box number nine in the digest, and the ones with a legible cause were shell&lt;br&gt;
alias papercuts (&lt;code&gt;command not found: eza&lt;/code&gt;, &lt;code&gt;command not found: bat&lt;/code&gt;). The rest were bare&lt;br&gt;
exit codes, a Python traceback, a Reddit fetch the harness could not make, and the harness&lt;br&gt;
refusing a &lt;code&gt;sleep 45&lt;/code&gt;. None of that is a story, which is why it gets a sentence rather than a section.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/a-green-result-only-covers-what-it-ran/"&gt;A Green Result Only Covers What It Ran&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-skip-that-counted-as-a-pass/"&gt;The Skip That Counted as a Pass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-green-badge-came-back-through-a-hyphen/"&gt;The Green Badge Came Back Through a Hyphen&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": "Bind the Receipt to the Commit It Installed",&lt;br&gt;
  "description": "An E2E test receipt that carries the installed commit hash makes provenance checkable. Six commits on one lane, three of them asserting a literal string.",&lt;br&gt;
  "author": {"@type": "Person", "name": "Jeremy Longshore"},&lt;br&gt;
  "datePublished": "2026-08-27T10:00:00-06:00",&lt;br&gt;
  "url": "&lt;a href="https://startaitools.com/posts/the-commit-the-test-actually-installed/" rel="noopener noreferrer"&gt;https://startaitools.com/posts/the-commit-the-test-actually-installed/&lt;/a&gt;",&lt;br&gt;
  "inLanguage": "en-US",&lt;br&gt;
  "wordCount": 2246&lt;br&gt;
}&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cicd</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>A Ratchet Is Only as Strong as Its Re-Baseline Rule</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Fri, 28 Aug 2026 11:30:14 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/a-ratchet-is-only-as-strong-as-its-re-baseline-rule-1d1l</link>
      <guid>https://dev.to/jeremy_longshore/a-ratchet-is-only-as-strong-as-its-re-baseline-rule-1d1l</guid>
      <description>&lt;p&gt;The claude-code-plugins marketplace carries thousands of skill and agent markdown files, contributed over a long stretch by a lot of different hands. A schema validator, &lt;code&gt;scripts/validate-skills-schema.py&lt;/code&gt;, grades them at a strict marketplace tier where a missing required field is an ERROR, not a warning. The corpus fails that grading in bulk. It always has.&lt;/p&gt;

&lt;p&gt;That leaves two bad options and one good one. Fail CI on the whole corpus and nothing merges again. Ignore the findings and the debt compounds quietly. Or ratchet: pin what exists today, fail on anything new.&lt;/p&gt;

&lt;p&gt;I built the ratchet on 2026-08-26, across 424 commits on the mainline of that repo. It took eight iterations, and only two of them were about the debt itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you ratchet compliance debt without blocking merges?
&lt;/h2&gt;

&lt;p&gt;You pin the current violation set as a baseline and fail only on what is new. Existing debt is tolerated; a new (path, rule, field) triple fails the gate. That stops silent growth without blocking every merge. The other half, and the harder one, is making the pinned baseline itself impossible to grow without a reviewed, single-file change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The compliance ratchet mechanism
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;scripts/check-marketplace-compliance-baseline.py&lt;/code&gt;. Its docstring states the whole contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fail closed when marketplace compliance debt grows beyond the pinned baseline.

Blueprint 727 E6.3, phase R1: compare the validator's triple-keyed marketplace
findings with ``scripts/.marketplace-compliance-baseline.json``. Existing baseline
debt is tolerated; a new (path, rule, field) triple fails the gate.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pinned artifact is &lt;code&gt;scripts/.marketplace-compliance-baseline.json&lt;/code&gt;. The final capture of the day, &lt;code&gt;ef7b666f2&lt;/code&gt; at 23:05, held schema_version 4.1.0, 2,132 pinned violation triples, and a rule_inventory of 19 rule ids.&lt;/p&gt;

&lt;p&gt;A pinned entry is exactly this shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins/ai-agency/hyperflow/agents/accessibility-reviewer.md :: E-MISSING-REQUIRED-FIELD :: author
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Path, rule, field. Three keys, one line, sorted. Nothing clever, and the lack of cleverness is the point: a diff on that file is human readable, so a reviewer can see what someone is asking to forgive.&lt;/p&gt;

&lt;p&gt;The file also carries a corpus block and a separate quality reading, and the two must not be confused with each other:&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="nl"&gt;"corpus_definition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resolveCorpus('graded')"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"corpus"&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;"agent_files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;357&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command_files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;373&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"plugin_dirs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;593&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"skill_files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3628&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;In the final capture &lt;code&gt;grade_A_plus_B&lt;/code&gt; is 2979 and &lt;code&gt;grade_A_plus_B_pct&lt;/code&gt; is 82.1114. That percentage is 2979 over the 3628 graded skill files. It is the share of graded files scoring A or B. It is not a ratio involving the 2132 errors, and it does not move in lockstep with them: one file can carry several violation triples, and a file can score a B while still contributing to the pinned set. Two quantities, two denominators, one artifact. The percentage moved during the day, from 81.6428 in the first capture to 82.1114 in the last, which is a second and independent signal that the docs work was landing. I am labouring this because the post's own argument is that a number is untrustworthy until you can prove what it measures, and I would rather be tedious than do the thing I am complaining about.&lt;/p&gt;

&lt;p&gt;The debt is concentrated rather than scattered, which is what makes paying it down tractable at all. These are the top 6 of the 19 rule ids in the final capture, so they do not sum to 2132:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Pinned count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;E-MISSING-REQUIRED-SECTION&lt;/td&gt;
&lt;td&gt;840&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-MISSING-REQUIRED-FIELD&lt;/td&gt;
&lt;td&gt;805&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-FRONTMATTER-9c196f479e69&lt;/td&gt;
&lt;td&gt;222&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-TIER2-TOOL-SAFETY-5d322e66e4de&lt;/td&gt;
&lt;td&gt;185&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-TIER2-ORCHESTRATION-BOUNDS-31b9cdf7bcb8&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-REFERENCE-ESCAPES-SKILL-DIRECTORY&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two rules account for 1,645 of the 2,132. That is a writing project, not an engineering project, and I will come back to it. Only two rows moved all day. E-MISSING-REQUIRED-SECTION went from 956 in the first capture down to 840. E-MISSING-REQUIRED-FIELD jumped from 580 to 805 at the +237 capture and then held flat for the rest of the night. The other four rows in the table never moved at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight iterations, each closing the hole the last one left
&lt;/h2&gt;

&lt;p&gt;Grouped by what each one addresses, not by when it landed. The real mainline order follows the walkthrough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;166a1fad5&lt;/code&gt; ci: add marketplace baseline capture workflow.&lt;/strong&gt; A new &lt;code&gt;.github/workflows/capture-marketplace-compliance-baseline.yml&lt;/code&gt;, 59 lines. Something has to produce the baseline before anything can compare against it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. &lt;code&gt;cf7410df0&lt;/code&gt; feat(ci): ratchet marketplace compliance debt.&lt;/strong&gt; The check script itself at 80 lines, &lt;code&gt;tests/test_marketplace_compliance_ratchet.py&lt;/code&gt; at 51 lines, and 7 lines wiring the job into &lt;code&gt;validate-plugins.yml&lt;/code&gt;. At this point the ratchet works, in the sense that it does what the docstring says.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. &lt;code&gt;d809b9a34&lt;/code&gt; fix(ci): ratchet full marketplace compliance corpus.&lt;/strong&gt; The ratchet was only seeing part of the corpus. The fix was inside the validator, &lt;code&gt;validate-skills-schema.py&lt;/code&gt;, at +61/-33, plus +28/-1 of baseline tests and two lines in &lt;code&gt;validate-plugins.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. &lt;code&gt;cc7e49683&lt;/code&gt; feat(ci): isolate marketplace compliance ratchet.&lt;/strong&gt; The ratchet was sharing a job with the legacy checks, so its verdict was buried in their output. Pulled apart in &lt;code&gt;validate-plugins.yml&lt;/code&gt; at +22/-13, with CLAUDE.md updated in the same commit at +1/-1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. &lt;code&gt;22d621efa&lt;/code&gt; fix(ci): detect untracked compliance baseline.&lt;/strong&gt; +3/-2. A baseline file that was never &lt;code&gt;git add&lt;/code&gt;ed still let the workflow report success. The gate was comparing against a file that, from the repository's point of view, did not exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. &lt;code&gt;d7d233297&lt;/code&gt; fix(ci): pin marketplace baseline contract metadata.&lt;/strong&gt; +39 lines to the check script, +16 to its tests. The &lt;code&gt;metadata_drift()&lt;/code&gt; docstring is the heart of the whole day:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Return baseline-contract changes that require a conscious re-baseline.

Triple comparison alone cannot distinguish an intentional validator-rule
change from legacy debt. The emitted schema version and rule inventory are
therefore part of the pinned contract: either changing them must fail the
ratchet until the dedicated baseline-capture transaction has been reviewed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comparing sets of violations is not enough, because you can shrink the set by changing what counts as a violation. A ratchet built only on triples treats "we fixed 300 files" and "we stopped checking for that" as the same event. So &lt;code&gt;schema_version&lt;/code&gt; and the 19 rule ids became part of the pinned contract. Move either one and the gate fails until a human has looked at the re-baseline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. &lt;code&gt;242d8e051&lt;/code&gt; fix(ci): forbid unauthorized baseline growth.&lt;/strong&gt; The E6.6 rule, implemented in &lt;code&gt;baseline_growth_error()&lt;/code&gt;. Baseline growth is legal only when the pull request touches exactly one file, &lt;code&gt;scripts/.marketplace-compliance-baseline.json&lt;/code&gt;, and the head branch is prefixed &lt;code&gt;automation/compliance-baseline-&lt;/code&gt;. Anything else is a violation. The commit touched &lt;code&gt;.github/CODEOWNERS&lt;/code&gt; (+1), &lt;code&gt;validate-plugins.yml&lt;/code&gt; (+12), the check script (+68/-1), and the tests (+25). The CODEOWNERS line is one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/scripts/.marketplace-compliance-baseline.json @jeremylongshore @blueandyellow44
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That routes any change to the pinned file to two named owners. It requests review; whether review is mandatory depends on branch protection, which is configuration and not code. The claim I am willing to make from the repository alone is the E6.6 one: a growing baseline is rejected outright unless it arrives as a single-file change on an &lt;code&gt;automation/compliance-baseline-&lt;/code&gt; branch. That rule lives in the script, so it holds regardless of settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. &lt;code&gt;f53930446&lt;/code&gt; fix(ci): run marketplace ratchet before legacy checks.&lt;/strong&gt; Ordering, +13/-7 in &lt;code&gt;validate-plugins.yml&lt;/code&gt;. A gate that runs after the noisy checks gets read after everyone has stopped reading.&lt;/p&gt;

&lt;p&gt;Sort those by what they actually address and the shape of the day comes out. Three of the eight (5, 6, 7) exist to make the pinned file un-quietly-editable. Two more (4 and 8) exist to make its verdict legible: where the result is reported, and in what order. Iteration 1 builds the file, and only 2 and 3 are about the violation set itself. A quarter of the day's work on a compliance ratchet was about compliance.&lt;/p&gt;

&lt;h3&gt;
  
  
  The order the mainline actually saw them
&lt;/h3&gt;

&lt;p&gt;The grouping above is thematic. This is &lt;code&gt;git log --first-parent --reverse&lt;/code&gt;, with the capture commits interleaved, all times normalized to the automation host's fixed UTC-6. The mainline is linear: the eight ratchet commits are direct single-parent pushes with committer equal to author, and only the captures are squash-merges, which is why those carry a GitHub committer.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time (-0600)&lt;/th&gt;
&lt;th&gt;Commit&lt;/th&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;20:36&lt;/td&gt;
&lt;td&gt;&lt;code&gt;166a1fad5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;add capture workflow (walkthrough 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:39&lt;/td&gt;
&lt;td&gt;&lt;code&gt;22d621efa&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;detect untracked baseline (walkthrough 5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:43&lt;/td&gt;
&lt;td&gt;&lt;code&gt;885890505&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;capture: 2011&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:45&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cf7410df0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ratchet compliance debt (walkthrough 2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:51&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d809b9a34&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ratchet full corpus (walkthrough 3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:53&lt;/td&gt;
&lt;td&gt;&lt;code&gt;19e4af810&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;capture: 2248&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:57&lt;/td&gt;
&lt;td&gt;&lt;code&gt;f53930446&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;run ratchet before legacy checks (walkthrough 8)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:04&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cc7e49683&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;isolate the ratchet (walkthrough 4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:08&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d7d233297&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;pin contract metadata (walkthrough 6)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:11&lt;/td&gt;
&lt;td&gt;&lt;code&gt;242d8e051&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;forbid unauthorized growth (walkthrough 7)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:24&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eb281e0d6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;capture: 2231&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:29&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eaeb0e5b9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;capture: 2216&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three things in that column that the thematic grouping hides. The untracked-baseline detection landed second, before the check script it protects existed at all. The ordering fix landed before the isolation it was ordering. And the causal claim survives intact: the +237 capture sits directly on top of the corpus widening, and pinning the contract metadata came three commits later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why comparing violation counts proves nothing
&lt;/h2&gt;

&lt;p&gt;Twenty one captures changed the baseline file that day, one per capture pull request, numbered #1346 through #1367 (#1363 was dependabot). The first four:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capture commit&lt;/th&gt;
&lt;th&gt;Time (-0600)&lt;/th&gt;
&lt;th&gt;Pinned entries&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;885890505&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;20:43&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;first capture, 12 rule ids&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;19e4af810&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;20:53&lt;/td&gt;
&lt;td&gt;2248&lt;/td&gt;
&lt;td&gt;+237, 19 rule ids&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;eb281e0d6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;21:24&lt;/td&gt;
&lt;td&gt;2231&lt;/td&gt;
&lt;td&gt;-17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;eaeb0e5b9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;21:29&lt;/td&gt;
&lt;td&gt;2216&lt;/td&gt;
&lt;td&gt;-15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The remaining seventeen took it down in steps: sixteen captures removed exactly five each, reaching 2136, and the last one removed four, ending at 2132 in &lt;code&gt;ef7b666f2&lt;/code&gt; at 23:05. Five off, sixteen times running, is what a docs push landing one vendor at a time looks like from the ratchet's side.&lt;/p&gt;

&lt;p&gt;The day started at 2011 and ended at 2132. Net, the debt grew by 121, after peaking at 2248 and giving back 116.&lt;/p&gt;

&lt;p&gt;It grew because of iteration 3. Widening what the validator inspected made 237 pre-existing problems visible for the first time. No file got worse and no contributor added anything.&lt;/p&gt;

&lt;p&gt;The artifact says so directly, and this is the part I would not have believed without the file in front of me. The 2011 capture carried a rule_inventory of 12 rule ids. The 2248 capture carried 19. Seven ids appeared between those two captures: &lt;code&gt;E-INVALID-FIELD&lt;/code&gt;, three &lt;code&gt;E-AGENT-*&lt;/code&gt; ids, &lt;code&gt;E-FATAL-9a99b10dfdaf&lt;/code&gt;, and two &lt;code&gt;E-VALIDATOR-*&lt;/code&gt; ids.&lt;/p&gt;

&lt;p&gt;Those seven account for 12 of the 237. The other 225 are E-MISSING-REQUIRED-FIELD triples on files the validator had simply not been grading before, which is why that row jumps 580 to 805 in the same capture.&lt;/p&gt;

&lt;p&gt;So the number moved for two different reasons in one step: new rule categories, and old rule categories applied to new files. A count alone cannot separate those, and neither can a diff of the triples. The pinned rule inventory is what makes them distinguishable, which is &lt;code&gt;metadata_drift()&lt;/code&gt; in one sentence.&lt;/p&gt;

&lt;p&gt;Reading it back from the artifacts, the commit order tells the rest: the widening in iteration 3 lands before the metadata pin in iteration 6, and iteration 6 exists at all because triple comparison alone cannot separate the two cases its own docstring names. I cannot tell you what I was thinking when I saw the jump. I can tell you the fix arrived three commits later and that its docstring describes exactly the ambiguity the jump created.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;The fail-closed gate ended the day as its own top-level job in &lt;code&gt;.github/workflows/validate-plugins.yml&lt;/code&gt;:&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;marketplace-compliance-ratchet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;marketplace-compliance-ratchet&lt;/span&gt;
  &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
  &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is listed in the &lt;code&gt;ci-required&lt;/code&gt; aggregate job's &lt;code&gt;needs:&lt;/code&gt; array alongside validate, verify, test, and 19 others, for 23 entries in all, so it is a required check rather than an advisory one. It runs two steps: "Refuse unauthorized marketplace baseline growth" (pull_request only, calling the script with &lt;code&gt;--check-growth-only --base --head-ref&lt;/code&gt;) and "Reject marketplace compliance debt outside the pinned baseline", which is the plain full check.&lt;/p&gt;

&lt;p&gt;The comment above that job explains iteration 4 better than I did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Blueprint 727 E6.4: R1 needs an independently visible, always-reporting blocking
job.  It is listed in ci-required below rather than being folded into `validate`,
so a pre-existing failure in an unrelated validation lane cannot obscure the
compliance-ratchet result.  The validator emits the complete
skills/commands/agents/manifests corpus; observed runtime is about 70 seconds,
bounded here at two minutes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;About 70 seconds observed, bounded at two. That budget is what makes the isolation affordable: a lane this cheap can afford to report on its own rather than sharing a job with something slower.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unglamorous half
&lt;/h2&gt;

&lt;p&gt;The mainline carries 336 hand-written &lt;code&gt;docs(...)&lt;/code&gt; commits from that day, 150 of them across these 26 vendors, governing the example sections of their skills: vercel, salesforce, perplexity, mistral, retellai, lokalise, klingai, juicebox, instantly, ideogram, hootsuite, hex, granola, grammarly, glean, gamma, framer, fondo, flyio, flexport, fireflies, firecrawl, finta, fathom, anthropic, anima.&lt;/p&gt;

&lt;p&gt;That work is what chips at E-MISSING-REQUIRED-SECTION, and the row moved 956 down to 840, which is the whole 116 the baseline gave back after the peak. Every entry that came off the baseline that night came off this one rule.&lt;/p&gt;

&lt;p&gt;The timing explains why the pinned count and the commit count do not line up. Read from the commit timestamps: most of those vendor commits had landed before the first capture at 20:43, so they were already inside the 2011 and never showed as a decline at all. A smaller number landed between the 2248 and 2216 captures. The remainder landed after 21:29, and those are what the seventeen later captures were recording.&lt;/p&gt;

&lt;p&gt;The ratchet and the docs push are the same project seen from two ends. One stops the bleeding, the other closes the wound. Only one of them is automation. The other is a person reading a skill file, understanding what it does, and writing an example section that is true. There is no version of this where the 840 goes to zero because a script ran. It goes down because someone spends a Wednesday writing.&lt;/p&gt;

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

&lt;p&gt;The other thread that day was supply-chain evidence, six commits in dependency order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;880812321&lt;/code&gt; feat(supply-chain): generate pnpm CycloneDX publication sboms. &lt;code&gt;scripts/generate-publication-sbom.mjs&lt;/code&gt;, 129 lines, with a 28 line test file from the first commit.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;304d3028f&lt;/code&gt; feat(supply-chain): build SBOM-backed publication reports. &lt;code&gt;scripts/build-publication-report.mjs&lt;/code&gt;, 69 lines, plus 17 lines of tests.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;8111e5b12&lt;/code&gt; fix(release): bind CLI evidence to SBOM and package identity. &lt;code&gt;cli-publish.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;a838b4860&lt;/code&gt; feat(release): attach SBOMs to npm publication reports. &lt;code&gt;publish-all-packages.yml&lt;/code&gt; and &lt;code&gt;publish-changed-packages.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;3c1a53f68&lt;/code&gt; feat(mcp): attach SBOMs to registry publication evidence. &lt;code&gt;publish-mcp-registry.yml&lt;/code&gt;, &lt;code&gt;ci/emit-evidence/emit-evidence.ts&lt;/code&gt;, and a two line edit to &lt;code&gt;scripts/build-publication-report.mjs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cf5c14a71&lt;/code&gt; feat(evidence): require SBOM digests for every publication. The fail-closed clasp: &lt;code&gt;release.yml&lt;/code&gt;, &lt;code&gt;emit-evidence.ts&lt;/code&gt;, and both generators moved together.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That chain sits on top of &lt;code&gt;80763cac1&lt;/code&gt; feat(evidence): attest required contexts and publications, 9 files at +671/-27, which added &lt;code&gt;.github/workflows/emit-publication-evidence.yml&lt;/code&gt; (128 lines) and grew &lt;code&gt;emit-evidence.ts&lt;/code&gt; by +254/-17, a net of 237 lines.&lt;/p&gt;

&lt;p&gt;An SBOM you can attach but are not required to attach is the same shape of problem as a baseline anyone can re-pin. In both chains the last commit on the mainline is the one that removes the choice: &lt;code&gt;242d8e051&lt;/code&gt; for the ratchet, &lt;code&gt;cf5c14a71&lt;/code&gt; for the evidence. In the SBOM chain that ordering is the tell, because the first five commits each felt like they were already enough.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;00b71ba66&lt;/code&gt; added kernel coupling violation alerts (&lt;code&gt;kernel-vendor-hash.yml&lt;/code&gt;, +53/-4) and &lt;code&gt;a60a2da48&lt;/code&gt; stood up a strict v2 kernel shadow lane (&lt;code&gt;kernel-shadow-validation.mjs&lt;/code&gt;, +115/-33).&lt;/p&gt;

&lt;p&gt;cad-dxf-agent merged three pull requests: #192 repairing real-world persona fixtures, #193 resolving non-breaking frontend audit alerts, and #194 migrating the frontend to React Router 7, which was a security-driven major version bump rather than an upgrade anyone wanted. &lt;code&gt;285df17f4&lt;/code&gt; registered the cad-dxf-agent plugin in the marketplace.&lt;/p&gt;

&lt;p&gt;Six Omarchy submission repos each got presentation assets and a manual validation run. Two carried real fixes: &lt;code&gt;8aa49e3&lt;/code&gt; preserve unusual repository paths in scanner output, and &lt;code&gt;d07e6b4&lt;/code&gt; tolerate missing Hyprland session.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the day ran with the models
&lt;/h2&gt;

&lt;p&gt;The blog pipeline itself ran on Claude Opus 5 (348 assistant turns) with Claude Sonnet 5 (29 turns), for 377 turns and 207 tool calls with 4 tool errors, pushing the previous day's Tier 3 post through its gate agents. One coordinator message is worth quoting, because it is what a working gate sounds like from the inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Five gate agents ran on your draft. Code review PASS, global fact-check PASS,
but both consistency checkers and the skill-local fact-checker returned REVISE.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Opus 5 also ran a 180 turn session on the governed second brain, 24 &lt;code&gt;brain_search&lt;/code&gt; calls and 15 &lt;code&gt;brain_capture&lt;/code&gt; calls, running the memory-distiller. Claude Fable 5 ran two short sessions: a cad-dxf-agent skill check (15 turns, 7 tool calls, 5 errors, and the same instruction had to be issued twice before it stuck) and a read-only partner-roster query over the EULER MCP that also needed a second push:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Continue. Use only EULER, complete the read-only roster query, and return the
requested JSON now.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the part that belongs here because it is the same lesson as the rest of the day.&lt;/p&gt;

&lt;p&gt;There is no local transcript for the claude-code-plugins thread at all. Not a short one. None. The 424 mainline commits are the only surviving evidence of the largest piece of work I did that day. Earlier drafts said 435, because that count swept in the frozen feature branch and a handful of dependabot heads. Everything above about why iteration 6 followed iteration 5, and what iteration 3 exposed that made iteration 6 necessary, was reconstructed from commit ordering and diffs.&lt;/p&gt;

&lt;p&gt;This post also got its own numbers wrong on the first three drafts, because they were read off a feature branch frozen at 21:35 while origin/main went on to record seventeen more captures, and the only thing that caught it was a checker that went back to the mainline artifacts instead of trusting the draft.&lt;/p&gt;

&lt;p&gt;A day spent building gates that refuse to accept unwitnessed changes ended with its own best work unwitnessed. The commits are real and the diffs are real, but the reasoning that produced them survives only because it happened to be legible in the order the commits landed. That is luck, not a system.&lt;/p&gt;

&lt;p&gt;{"&lt;a class="mentioned-user" href="https://dev.to/context"&gt;@context&lt;/a&gt;":"&lt;a href="https://schema.org%22,%22@type%22:%22BlogPosting%22,%22headline%22:%22A" rel="noopener noreferrer"&gt;https://schema.org","@type":"BlogPosting","headline":"A&lt;/a&gt; Ratchet Is Only as Strong as Its Re-Baseline Rule","datePublished":"2026-08-26T08:00:00-05:00","dateModified":"2026-08-26T08:00:00-05:00","author":{"@type":"Person","name":"Jeremy Longshore"},"publisher":{"@type":"Organization","name":"Start AI Tools","url":"&lt;a href="https://startaitools.com%22%7D,%22url%22:%22https://startaitools.com/posts/the-ratchet-that-needed-a-ratchet/%22,%22image%22:%22https://startaitools.com/images/og-image.png%22,%22description%22:%22Pinning" rel="noopener noreferrer"&gt;https://startaitools.com"},"url":"https://startaitools.com/posts/the-ratchet-that-needed-a-ratchet/","image":"https://startaitools.com/images/og-image.png","description":"Pinning&lt;/a&gt; compliance violations in CI is the easy half. Eight iterations in one day to build a gate that refuses unauthorized baseline growth."}&lt;/p&gt;

&lt;h2&gt;
  
  
  Related posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/a-green-result-only-covers-what-it-ran/"&gt;A Green Result Only Covers What It Ran&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-gate-that-could-not-fail/"&gt;The Gate That Could Not Fail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/the-skip-that-counted-as-a-pass/"&gt;The Skip That Counted as a Pass&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cicd</category>
      <category>claudecode</category>
      <category>releaseengineering</category>
      <category>testing</category>
    </item>
    <item>
      <title>Every Verdict Carries the Scope It Actually Ran</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Thu, 27 Aug 2026 10:46:07 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/every-verdict-carries-the-scope-it-actually-ran-1ka3</link>
      <guid>https://dev.to/jeremy_longshore/every-verdict-carries-the-scope-it-actually-ran-1ka3</guid>
      <description>&lt;p&gt;The third review comment on the marketplace submission did not name a bypass. It named the class.&lt;/p&gt;

&lt;p&gt;Two rounds before it, a human reviewer had handed me two working payloads and I had fixed both. Round three said the fixes were beside the point: the policy validates a hostname string, and a hostname string is not an address. An ordinary attacker-controlled name can resolve to 127.0.0.1, to an RFC1918 range, or to link-local. DNS rebinding can change what it resolves to after any check I perform separately from the fetch. Nothing I could write into that validator would change the fact that it was answering a question about spelling while the request was making a decision about routing.&lt;/p&gt;

&lt;p&gt;The offline test suite was green at exactly the commit the reviewer's comment named. Local HEAD was &lt;code&gt;d26746cbbfdcd4282ef1a3faa9b303f14b3f3a3e&lt;/code&gt;, 83 tests, all passing. That green means the spellings the suite knows about get rejected. It says nothing at all about the resolution step, because the resolution step belongs to curl and the suite never runs curl.&lt;/p&gt;

&lt;p&gt;That is the same defect the &lt;code&gt;/omarchy-ship&lt;/code&gt; lane exists to refuse. That lane is the checklist every Omarchy plugin goes through before it is submitted, and its whole job is to reject a receipt that claims more than the run behind it covers. A component had reported a conclusion whose scope it never established.&lt;/p&gt;

&lt;p&gt;It happened four times that day. Once in the security fix. Once in a metrics gate that had never been observed failing. Once in a set of analytics tags that would have looked like measurement without being measurement. Once in nine pieces of social copy that read well and could not be found. The fixes had nothing in common mechanically. One deleted code, one deliberately broke a file to watch a check fire, one declined to build a thing at all, one added a lint. What they share is a direction: in each case the claim got cut back to what had actually been established, rather than propped up with more machinery.&lt;/p&gt;

&lt;h2&gt;
  
  
  The submission was never the obstacle
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omarchy-listening-post-entry&lt;/code&gt; is a bar plugin for Omarchy that reads RSS and news feeds. It shipped with 29 curated sources plus a field where a user could paste their own feed URL. The marketplace submission is &lt;a href="https://github.com/HANCORE-linux/omarchy-plugin-marketplace/issues/1229" rel="noopener noreferrer"&gt;&lt;code&gt;HANCORE-linux/omarchy-plugin-marketplace#1229&lt;/code&gt;&lt;/a&gt;, opened 2026-08-21, carrying the labels &lt;code&gt;submission&lt;/code&gt;, &lt;code&gt;validated&lt;/code&gt;, &lt;code&gt;needs-fixes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Automated validation passed on the first pass. Public and reachable. One valid manifest. README and license present. Quattro compatibility green at &lt;code&gt;3759cfe&lt;/code&gt;. The automated security baseline passed too.&lt;/p&gt;

&lt;p&gt;So the listing pipeline had nothing to say. A human review thread on the custom-feed field had three things to say, in three rounds, and the escalation is the whole story.&lt;/p&gt;

&lt;h3&gt;
  
  
  Round one: the hostname was not the hostname
&lt;/h3&gt;

&lt;p&gt;Reviewer &lt;code&gt;ryanrhughes&lt;/code&gt; sent the first payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://user@127.0.0.1/feed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The private-host check read URL userinfo as part of the hostname. &lt;code&gt;user@127.0.0.1&lt;/code&gt; is not in any private range, because as a string it is not an address at all. The check said public. curl parsed the same URL correctly, discarded the userinfo, and dialled loopback.&lt;/p&gt;

&lt;p&gt;Fixed in &lt;code&gt;e8d00af&lt;/code&gt;. Two things changed, and the second one mattered more than the first. The check moved out of &lt;code&gt;Service.qml&lt;/code&gt; and into &lt;code&gt;Model.js&lt;/code&gt; so the offline suite could actually cover it, and the reported payload got pinned as a regression test. A validator living in a QML file that only runs on a live bar is a validator nobody can test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Round two: the address had more than one spelling
&lt;/h3&gt;

&lt;p&gt;Reviewer &lt;code&gt;HANCORE-linux&lt;/code&gt; sent two more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://127.1/feed
https://0177.0.0.1/feed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both reach loopback. The cause is &lt;a href="https://man7.org/linux/man-pages/man3/inet_addr.3.html" rel="noopener noreferrer"&gt;&lt;code&gt;inet_aton&lt;/code&gt;&lt;/a&gt;, which accepts one to four parts and reads each part in decimal, octal, or hex. &lt;code&gt;127.1&lt;/code&gt; is a two-part form where the second part fills the remaining 24 bits. &lt;code&gt;0177&lt;/code&gt; is octal for 127. Neither string starts with the text &lt;code&gt;127.0.0.&lt;/code&gt; that a naive range check looks for.&lt;/p&gt;

&lt;p&gt;The fix rejected every form the parser recognizes as an address, rather than trying to enumerate the notations. That felt like progress. It was progress on the same axis: I had gone from handling one spelling to handling all spellings, and the axis itself was wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Round three: the class, server-side request forgery
&lt;/h3&gt;

&lt;p&gt;On 2026-08-24 the same reviewer stopped supplying payloads. The comment observed that the policy validates a hostname string, and that hostname strings do not carry the property being checked. An attacker does not need a clever spelling. They need a domain they control with an A record pointing at 127.0.0.1. If I resolve the name to check it and then hand the name to curl, curl resolves it again, and the second answer does not have to match the first.&lt;/p&gt;

&lt;p&gt;The comment named two options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option one, resolve and pin.&lt;/strong&gt; Resolve the host myself. Reject every non-public result. Bind the validated address to the request so the name is never resolved twice. In curl terms that is an explicit &lt;a href="https://curl.se/libcurl/c/CURLOPT_RESOLVE.html" rel="noopener noreferrer"&gt;&lt;code&gt;--resolve host:port:addr&lt;/code&gt;&lt;/a&gt; pin, plus &lt;code&gt;--proto =https&lt;/code&gt;, plus &lt;code&gt;--max-redirs 0&lt;/code&gt;, with every redirect hop re-validated in &lt;code&gt;Model.js&lt;/code&gt; rather than followed by curl. This is the only option that keeps arbitrary custom feeds working.&lt;/p&gt;

&lt;p&gt;Sketched out, the safe fetch looks roughly like this, and the sketch is the argument against 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;# option one, in outline. every line here is a thing that can be&lt;/span&gt;
&lt;span class="c"&gt;# subtly wrong, and the whole point is that a subtle wrong is&lt;/span&gt;
&lt;span class="c"&gt;# indistinguishable from correct until somebody exploits it.&lt;/span&gt;
&lt;span class="nv"&gt;addr&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;resolve_a_record &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$host&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="c"&gt;# my resolver, not curl's&lt;/span&gt;
is_public &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1                 &lt;span class="c"&gt;# reject loopback, rfc1918, link-local&lt;/span&gt;
curl &lt;span class="nt"&gt;--resolve&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="s2"&gt;:443:&lt;/span&gt;&lt;span class="nv"&gt;$addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--proto&lt;/span&gt; &lt;span class="s1"&gt;'=https'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--max-redirs&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# and then: parse the Location header myself, re-run the whole&lt;/span&gt;
&lt;span class="c"&gt;# block for every hop, and get the hop budget right too.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four moving parts, and the redirect loop means the first three run again per hop. Every one of them has to hold under an attacker who controls the DNS answer and the redirect chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option two, remove arbitrary custom-feed hosts.&lt;/strong&gt; Ship the 29 curated sources. Drop user-supplied feed URLs entirely.&lt;/p&gt;

&lt;p&gt;I asked Jeremy which way to go. The steer came back in one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix listening post drop the custom feeds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why the smaller fix won
&lt;/h2&gt;

&lt;p&gt;I wanted to build option one. It is the interesting one. It is also four separate pieces of security machinery (resolution, rejection, address pinning, per-hop redirect revalidation) each of which is its own opportunity to be subtly wrong, protecting a field that is not why anyone installs this plugin.&lt;/p&gt;

&lt;p&gt;The pitch is 29 curated sources in your bar. The custom-feed box was a convenience nobody asked for. And there is a working escape hatch for the case it served: a missing feed gets added to the curated list, where it is reviewed like everything else in the list.&lt;/p&gt;

&lt;p&gt;The tradeoff is real and worth stating rather than hiding.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Resolve and pin&lt;/th&gt;
&lt;th&gt;Remove the surface&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arbitrary user feeds&lt;/td&gt;
&lt;td&gt;Kept&lt;/td&gt;
&lt;td&gt;Gone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New code paths to get right&lt;/td&gt;
&lt;td&gt;Four&lt;/td&gt;
&lt;td&gt;Zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode if I get it wrong&lt;/td&gt;
&lt;td&gt;Silent forgery from a shipped plugin&lt;/td&gt;
&lt;td&gt;None, the code does not exist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testable offline&lt;/td&gt;
&lt;td&gt;Partially, the resolution step is not&lt;/td&gt;
&lt;td&gt;Fully&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reviewer can verify by reading&lt;/td&gt;
&lt;td&gt;No, needs runtime reasoning&lt;/td&gt;
&lt;td&gt;Yes, the constants are visible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The bottom row is what decided it. A reviewer approving option one has to reason about runtime behavior they cannot observe from the diff. A reviewer approving option two reads a list of &lt;code&gt;https://&lt;/code&gt; string constants and is done.&lt;/p&gt;

&lt;p&gt;Commit &lt;code&gt;30ac415&lt;/code&gt; at 15:14: &lt;code&gt;fix(security): remove custom feed hosts, closing the request-forgery surface for good&lt;/code&gt;. Version 1.1.0.&lt;/p&gt;

&lt;p&gt;Removed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;extra-sources.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Service.extraSources()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;extrasFile&lt;/code&gt; reader&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;extrasPath&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Model.isPublicHost()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every source the plugin fetches is now a compile-time constant in &lt;code&gt;Model.SOURCES&lt;/code&gt;. Seven files changed, 83 insertions and 211 deletions, which is the honest summary of the change: &lt;code&gt;CHANGELOG.md&lt;/code&gt;, &lt;code&gt;Model.js&lt;/code&gt;, &lt;code&gt;tests/model.test.js&lt;/code&gt;, &lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;Service.qml&lt;/code&gt;, &lt;code&gt;manifest.json&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;. The two files carrying most of the churn are &lt;code&gt;Model.js&lt;/code&gt; and its test file, at 91 changed lines each.&lt;/p&gt;

&lt;h2&gt;
  
  
  The deletion had to be provable
&lt;/h2&gt;

&lt;p&gt;Deleting code is easy. Keeping it deleted is the actual engineering, because the next person to want a custom feed field will write &lt;code&gt;isPublicHost&lt;/code&gt; again, in good faith, and the suite will not care.&lt;/p&gt;

&lt;p&gt;So the eleven &lt;code&gt;isPublicHost&lt;/code&gt; tests were replaced with two tests that assert the absence.&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="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the custom-feed host allowlist is gone and must not come back by name&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPublicHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;every fetched source is a compile-time constant, none is user supplied&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SOURCES&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SOURCES&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;for &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;s&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SOURCES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;Plain &lt;code&gt;node:test&lt;/code&gt; with &lt;code&gt;assert&lt;/code&gt;, no framework. The first test name is doing work that the assertion cannot: &lt;code&gt;assert.equal(Model.isPublicHost, undefined)&lt;/code&gt; on its own tells a future reader that something is absent, and nothing about why. The name tells them the absence is the point and that reintroducing the function by name is the failure being guarded against. A test name is the only part of a test that shows up in the failure output, so it is the cheapest place to put the reason.&lt;/p&gt;

&lt;p&gt;Note the shape of the result. The suite got smaller and the guarantee got stronger. Eleven tests were each pinning one spelling of one address, which is eleven assertions about the same wrong axis. Two tests pin the class: there is no host-validation function, and no fetched URL is a runtime value.&lt;/p&gt;

&lt;p&gt;Here is the shape of what the suite lost and what it gained, because the raw number moving down is the confusing part:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tests about host validation&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What they assert&lt;/td&gt;
&lt;td&gt;this spelling is rejected&lt;/td&gt;
&lt;td&gt;the function does not exist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fails when a new notation appears&lt;/td&gt;
&lt;td&gt;only if someone adds a twelfth test&lt;/td&gt;
&lt;td&gt;not applicable, nothing parses hosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fails when the surface comes back&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;yes, immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total suite&lt;/td&gt;
&lt;td&gt;83&lt;/td&gt;
&lt;td&gt;74&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Model.js&lt;/code&gt; also carries a comment where the old call site used to be. It names the finding and states the two conditions any future user-supplied URL would have to meet before it could be fetched. That is not decoration. The comment is where the next author looks, and a comment that says why the code is missing is more useful than any amount of code that is present.&lt;/p&gt;

&lt;h3&gt;
  
  
  The deletion was scoped, not indiscriminate
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Model.safeUrl&lt;/code&gt; stayed. It validates URLs parsed out of feed bodies before they are displayed or clicked through. That is a different job. Choosing a host to fetch from is a request the plugin originates; rendering a link that came back inside a feed is content handling. Both need checking. Only one of them was the forgery surface.&lt;/p&gt;

&lt;p&gt;Deleting everything with &lt;code&gt;url&lt;/code&gt; in the name would have been the same failure in the other direction: an action whose scope was wider than the finding that motivated it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What was actually verified, and what was not
&lt;/h3&gt;

&lt;p&gt;Verified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offline suite: 74 tests, 74 pass, 0 fail. That is 83, minus the 11 &lt;code&gt;isPublicHost&lt;/code&gt; tests, plus the 2 absence guards.&lt;/li&gt;
&lt;li&gt;Vendored gate lane: PASS, 9 gates enforced, including &lt;code&gt;c38&lt;/code&gt; and &lt;code&gt;c31&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Zero em dashes and zero en dashes across the tree.&lt;/li&gt;
&lt;li&gt;No non-comment reference to extras or &lt;code&gt;isPublicHost&lt;/code&gt; remains in &lt;code&gt;Service.qml&lt;/code&gt; or &lt;code&gt;Model.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The finding closed too. Issue &lt;code&gt;#1229&lt;/code&gt; went to CLOSED at 23:23 UTC on 2026-08-25, carrying the labels &lt;code&gt;submission&lt;/code&gt;, &lt;code&gt;validated&lt;/code&gt;, &lt;code&gt;listed&lt;/code&gt;, and &lt;code&gt;approved-and-verified&lt;/code&gt;. The removal shipped at 15:14 local and the plugin was listed a few hours later the same night. Two rounds of validator patches never moved that label. Deleting the field did.&lt;/p&gt;

&lt;p&gt;Not verified, and this is the post's own instance of its thesis: the change was never re-verified on an Omarchy rig. Rig render and &lt;code&gt;omarchy-plugin-validate&lt;/code&gt; are unproven rather than passing.&lt;/p&gt;

&lt;p&gt;The reason written into the commit body at 15:14 is that the &lt;code&gt;omarchy-rig&lt;/code&gt; container was not present on this box, and at 15:14 that was true. It stopped being true about six hours later. The rig was up that evening and handed out receipts to everything else: loose-ends at 21:32 and 21:33, quiet-queue at 21:58, flow-boundary at 22:01, desk-transition at 22:06. Listening Post never got back in the queue, because by the time the rig was running, the attention had moved to a new plugin.&lt;/p&gt;

&lt;p&gt;So the plugin's newest rig receipt is still the one from 2026-08-22 at 10:29, three days older than the change it is supposed to cover. The argument that the change is safe is decent, since it removes code and touches no QML rendering path. An argument is not a run, and a receipt whose scope stops three days short of the change is the same defect as a green suite that never ran curl, this time with my name on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sibling one: corrupting the CI gate to see it fire
&lt;/h2&gt;

&lt;p&gt;The same morning, a new &lt;code&gt;omarchy&lt;/code&gt; umbrella repo went up (&lt;code&gt;60e3fff&lt;/code&gt; at 12:16, 821 insertions) with an org landing page whose README carries a generated metrics table. &lt;code&gt;scripts/refresh-metrics.sh&lt;/code&gt; regenerates it, &lt;code&gt;refresh-metrics.yml&lt;/code&gt; runs it, and a &lt;code&gt;--check&lt;/code&gt; lane on pull requests is supposed to fail when the committed block has drifted from what the script would produce.&lt;/p&gt;

&lt;p&gt;Supposed to. Nobody had watched it fail.&lt;/p&gt;

&lt;p&gt;Commit &lt;code&gt;c8bf8be&lt;/code&gt; at 12:32: &lt;code&gt;test(ci): hand-edit the generated metrics table to prove the staleness gate fires&lt;/code&gt;. The corruption was one table row, renamed from &lt;code&gt;**Bazaar**&lt;/code&gt; to &lt;code&gt;**Bazaar (hand edited)**&lt;/code&gt;. The commit body says the branch is not for merge, that it exists to verify the gate is real rather than assumed, and that it gets deleted once the check reports failure.&lt;/p&gt;

&lt;p&gt;A gate that has never failed has not been observed working. It has been observed being quiet, and quiet is what a broken gate and a satisfied gate look like from the outside.&lt;/p&gt;

&lt;p&gt;The gate's first observable state is the detail worth keeping. The workflow was created already broken in &lt;code&gt;60e3fff&lt;/code&gt; at 12:16: the continuation lines sat at column 0 from the start, so GitHub parsed the file into zero jobs and ran nothing (run &lt;code&gt;32882805663&lt;/code&gt;). &lt;code&gt;1395866&lt;/code&gt; at 12:18 repaired the block scalar. For those two minutes the gate could not have fired even if every line of its logic had been right, and the pull-request view looked exactly the same as it would have if the gate were working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sibling two: the UTM tags that were refused
&lt;/h2&gt;

&lt;p&gt;Nine outbound social packets were dispatched that day. Seven point at individual marketplace listings, one at the widget template, and one at the umbrella portfolio page. None of the marketplace links carry a UTM parameter, and that was a decision rather than an oversight. It is written up in &lt;code&gt;000-docs/003-RP-BASE-showcase-campaign-baseline.md&lt;/code&gt;, with the lane built in &lt;code&gt;89afdfa&lt;/code&gt; at 12:27 and &lt;code&gt;fe425f7&lt;/code&gt; at 12:29.&lt;/p&gt;

&lt;p&gt;The reasoning: analytics for &lt;code&gt;omarchyplugins.com&lt;/code&gt; belong to the marketplace. A &lt;code&gt;utm_source&lt;/code&gt; attached to a link into someone else's property is a parameter nobody on this side can ever read back. Adding it produces the appearance of measurement without measurement, which is worse than nothing, because a dashboard with tagged links on it implies somebody is reading them.&lt;/p&gt;

&lt;p&gt;Two signals are genuinely readable, and both were captured on the day.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The marketplace's own public stats endpoint.&lt;/strong&gt; Views, copies, and hearts per plugin. &lt;code&gt;copies&lt;/code&gt; is the closest thing exposed to an install, so that is the conversion metric.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub traffic on repos we own.&lt;/strong&gt; GitHub reports referrer hostnames natively, so &lt;code&gt;x.com&lt;/code&gt; and &lt;code&gt;linkedin.com&lt;/code&gt; arrive already separated with no tagging needed. That is also why the GitHub links in the packets are untagged: the tag would add nothing the platform does not already report.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The timing constraint is the part worth copying. GitHub traffic is a rolling 14-day window and cannot be backfilled. Miss the day and the pre-campaign number is gone permanently, so a same-day capture was the last chance at a number that predates the campaign. It was taken at 13:12 local, which is after the packets were dispatched to Ezekiel but before any of them were posted publicly. Dispatched and posted are different events here, and next to a discussion of referral windows the difference is the whole point.&lt;/p&gt;

&lt;p&gt;Marketplace snapshot &lt;code&gt;2026-08-25T18:12:41.735Z&lt;/code&gt;, across 1,366 listed plugins:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plugin&lt;/th&gt;
&lt;th&gt;Views&lt;/th&gt;
&lt;th&gt;Copies&lt;/th&gt;
&lt;th&gt;Hearts&lt;/th&gt;
&lt;th&gt;GitHub views 14d&lt;/th&gt;
&lt;th&gt;Uniques&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bazaar&lt;/td&gt;
&lt;td&gt;199&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pit Wall&lt;/td&gt;
&lt;td&gt;113&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wait State&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MLB Booth&lt;/td&gt;
&lt;td&gt;92&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X Files&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docket&lt;/td&gt;
&lt;td&gt;89&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crew Chief&lt;/td&gt;
&lt;td&gt;66&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listening Post&lt;/td&gt;
&lt;td&gt;none yet&lt;/td&gt;
&lt;td&gt;none yet&lt;/td&gt;
&lt;td&gt;none yet&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Widget Template&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two blank rows mean different things. Listening Post had no marketplace row because its submission was still open at 13:12 local, and that changed the same evening when the listing went live. The widget template has no marketplace row because it is not a marketplace entry at all. Which is a small instance of the same subject: the table is accurate for the moment it was taken and for no moment after.&lt;/p&gt;

&lt;p&gt;The baseline exists to answer two questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why are the two most-viewed listings the two with zero hearts?&lt;/strong&gt; Hearts do move: Pit Wall has 3, and four other listings have 1. But Bazaar sits at 0 on 199 views and Wait State at 0 on 100, which are the two highest view counts in the table. Nothing in either product asks anybody for a heart. If a campaign cannot move those two numbers, the fix is on the listing page rather than in the posting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does X or LinkedIn send more traffic here?&lt;/strong&gt; The audience is Arch and Hyprland users, which argues for X. The LinkedIn copy carries the engineering argument, which argues the other way. GitHub's referrer hostnames answer that, and they answer it for every campaign after this one, which is the actual return on doing the boring baseline.&lt;/p&gt;

&lt;p&gt;What they do not answer is which platform converts, because conversion is &lt;code&gt;copies&lt;/code&gt; and &lt;code&gt;copies&lt;/code&gt; lives on the marketplace, which exposes no referrer dimension at all. The instrument is narrower than the question. Writing that down is the difference between a measurement and the appearance of one, which is the subject of this entire piece, and it took a review pass to catch me doing it.&lt;/p&gt;

&lt;p&gt;Listening Post got no packet at all. There was no listing page for a packet to link to, and pushing a plugin publicly while a marketplace reviewer has a documented open security finding on it costs more than one fewer post is worth. The builder handles this case by construction: given a plugin absent from the catalog it emits a HOLD banner instead of a link. Fail-closed, so the human never has to remember the rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sibling three: copy that read well and could not be found
&lt;/h2&gt;

&lt;p&gt;Nine showcase packets (an X post plus two LinkedIn variants each) had already been generated and emailed to Ezekiel earlier that day. Then somebody read them.&lt;/p&gt;

&lt;p&gt;Four of the nine X posts never said the word Omarchy anywhere: wait-state, x-files, docket, crew-chief. None of the nine carried a single hashtag. Omarchy was trending on X at the time.&lt;/p&gt;

&lt;p&gt;A post about an Omarchy plugin that never names Omarchy is invisible to every single person searching for one. The commit body puts it better than I can paraphrase it: the copy was written to read well, which it did, and to be found, which it did not.&lt;/p&gt;

&lt;p&gt;Commit &lt;code&gt;d37bc55&lt;/code&gt; at 13:58: &lt;code&gt;fix(packets): name Omarchy in every post and add the discovery terms the first pass threw away&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fix front-loads the term instead of appending a "for Omarchy" tag line at the end. Two reasons. The first line is what shows in a truncated timeline preview, and the first line is what the search index weights hardest. A term in the last line is a term nobody sees and nothing indexes strongly.&lt;/p&gt;

&lt;p&gt;The guard is a lint at the render step. The builder now refuses to render a packet when:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- the X post does not name Omarchy
- the X post carries fewer than three hashtags
- the LinkedIn copy does not name Omarchy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the commit body: this class of miss is exactly what a lint is for, invisible on a read-through and obvious to a checker. Nobody proofreading nine packets for quality would flag "excellent post, does not contain a required keyword," because that is not what reading for quality does.&lt;/p&gt;

&lt;p&gt;Verified after the fix: all nine X posts name Omarchy, all carry four hashtags, all land between 457 and 620 characters. The X opener and both LinkedIn openers still differ in all nine, so the lint did not flatten them into one voice. Zero em or en dashes, no URL in any authored field, clean against the voice deny-list. The nine corrected packets were re-sent to Ezekiel with the subject prefixed &lt;code&gt;CORRECTED, use this one&lt;/code&gt;, and the nine Plane issues were re-synced in place, updated rather than duplicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the packets go, and why they go into Plane
&lt;/h2&gt;

&lt;p&gt;Ezekiel does the actual social posting, remote, from emailed packets. The lane that builds them went in at &lt;code&gt;89afdfa&lt;/code&gt; (12:27): &lt;code&gt;scripts/build-showcase-packet.py&lt;/code&gt; at 180 lines, &lt;code&gt;scripts/campaign-baseline.py&lt;/code&gt; at 158, &lt;code&gt;showcase-packets.json&lt;/code&gt; at 106, plus the baseline doc.&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;87b04a8&lt;/code&gt; at 12:57: &lt;code&gt;feat(plane): mirror the showcase packets into Plane so done is a state, not a report&lt;/code&gt;. That is &lt;code&gt;plane-sync-packets.py&lt;/code&gt; at 200 lines and &lt;code&gt;plane-assign-when-accepted.sh&lt;/code&gt; at 48. Jeremy's steer that drove it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;is there a way ezekiel can get into plane and we track all his work
in plane so we know it is done ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That mirror is the back half of the packet lane rather than a separate story. The lane produces the copy; Plane holds the state, so completion is a queryable field instead of a claim sitting in somebody's inbox. The nine packets went to &lt;code&gt;ezekiel@intentsolutions.io&lt;/code&gt;, CC Jeremy, ordered individual plugins first, then the widget template, then the portfolio page last, because a summary lands better once a few of the parts have already gone out.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model collaboration beat, and what it actually taught
&lt;/h2&gt;

&lt;p&gt;Claude Opus 5 ran the Omarchy thread that day: 1,112 transcript records in the main session, 116 in a second one, and 263 in this blog session. Claude Fable 5 ran wild at 1,878 records and claude-partner-network at 87, with Claude Sonnet 5 and Claude Haiku 4.5 in smaller volumes. Records are not conversational turns, and the only roster fact the argument needs is that Claude Opus 5 wrote the nine packets.&lt;/p&gt;

&lt;p&gt;The packet failure is a model-collaboration failure and an instructive one. Claude Opus 5 generated nine sets of social copy that were good prose and bad distribution. The brief asked for copy that read well. It never stated that the copy had to be findable. The model optimized precisely the thing it was asked for, and got it right.&lt;/p&gt;

&lt;p&gt;The fix is not a better prompt. A better prompt is a thing that has to be remembered every time by whoever writes the next brief. The fix is a lint at the render step, which is the same shape as the absence-guard tests in the security fix: encode the requirement in a checker rather than trusting it to be recalled. Both cases replace an instruction with a refusal.&lt;/p&gt;

&lt;p&gt;There is a human beat in the middle of this too. While the marketplace thread was open, Jeremy hit the session with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;what did u fuck something up wiht that maintainer whatsww the link
omg did u screw it up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is what an open security finding on a public submission feels like from outside the terminal. The &lt;code&gt;needs-fixes&lt;/code&gt; label sat on a public issue for days, on a repo with the maintainer's name on the thread. No amount of "the fix is straightforward" makes that read as calm.&lt;/p&gt;

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

&lt;p&gt;Breadth, not depth. None of this carries the argument above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;omarchy-loose-ends-entry&lt;/strong&gt;: a new plugin built end to end the same day, a Git work queue. Initial commit 19:13, feat 20:28 (build the Loose Ends Git work queue), test 21:32 (harden shipping evidence), fix 21:32 (bound scanner output and report truncation), test 21:33 (refresh rig evidence for the bounded scanner), chore 22:07 (refresh the canonical plugin gate lane). Jeremy's steer was &lt;code&gt;build loose ends next&lt;/code&gt;. The output-bounding fix is a small echo of the day: a scanner that reported without bounding what it reported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other Omarchy entries&lt;/strong&gt;: quiet-queue got an owner-aware quiet queue plus a rig render receipt, flow-boundary a local flow boundary ledger plus rig render, desk-transition safe desk transition scenes plus rig render, and workspace-storyboard and capture-conveyor both took work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cad-dxf-agent&lt;/strong&gt; (renamed cad-ai-agent): a full 7-layer testing SOP retrofit. audit-harness v0.1.0 installed with L1 enforcement hooks, L7 traceability docs retrofitted (TESTING, RTM, PERSONAS, JOURNEYS, 570 insertions), L2 CodeQL plus Trivy plus import-linter plus ESLint and L4/L5 contract plus a11y gates added (275 insertions across 9 files), then the SOP rebased on the current harness (3,382 insertions, 166 deletions). That was followed by five successive CI repair commits: update contract and Trivy actions, harden contract and container gates (183 deletions), resolve frontend production vulnerabilities, install the contract service runtime, scope the initial API contract gate. Adding five gates cost five repair commits to get green. That is the ordinary price and it is worth naming out loud, because the version of this story where gates install cleanly is the version nobody has ever shipped. Also relicensed MIT to Apache-2.0, added a &lt;code&gt;cad-analyze&lt;/code&gt; CLI and a Claude Code plugin, and merged 7 dependabot updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;claude-code-plugins&lt;/strong&gt;: governance editor and dependency policies (#1322), external-sync quarantine of the walkie-talkie mirror (#1320), modernization catalog and freshness blocker repairs (#1319).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;contributing-clanker&lt;/strong&gt;: three gate-scoping fixes, excluding developer scripts from the runtime gate, batching ignored-file gate filtering, and excluding ignored dependencies from gate scans.&lt;/li&gt;
&lt;li&gt;Ko-fi added alongside existing funding sources across about fourteen repos. intent-os regenerated its mission-control status pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The rule: compare what it asserts against what it ran
&lt;/h2&gt;

&lt;p&gt;Four times in one day, something was set to report a conclusion whose scope it had never established. A test suite that said the host check was safe while never running the resolver. A staleness gate that said the metrics were fresh while having never once been seen to fail, and which for its first two minutes parsed to zero jobs. Nine posts that claimed a subject they never contained the word for. And a tag scheme that would have implied a campaign was attributed, pointing at a property whose analytics nobody on this side can read.&lt;/p&gt;

&lt;p&gt;The diagnostic that held across all four is a pair of lists. What does the thing assert, and what did it actually run? The suite asserted safety and ran string comparison. The gate asserted freshness and ran nothing observable. The copy asserted a subject and contained no instance of the word. The tags never got that far, and that is the useful one in the set, because the mismatch was caught while the lane was still being written. Nothing was dropped, because nothing was ever attached. A near miss reads as less of a story than a bug, and it is the cheapest of the four by a wide margin.&lt;/p&gt;

&lt;p&gt;The fixes shared no mechanism at all. One removed a feature. One broke a generated table on purpose and watched the check fail. One declined to build the tagging. One added a word, four hashtags, and a lint at the render step. What they share is direction. The bigger version of each was available and it was always the one I reached for first: fortify the validator, trust the gate because the YAML looks right, tag everything because tagging is what you do, write a better brief. Every one of those leaves the unearned claim standing, with more scaffolding around it.&lt;/p&gt;

&lt;p&gt;Fixing the spelling is not fixing the class. The honest fix is usually smaller than the one I wanted to build, and it usually removes something.&lt;/p&gt;

&lt;p&gt;Which brings it back to the rig. The security change is good, the suite is green at 74 of 74, the gate lane passes 9 enforced checks, and the marketplace listed the plugin that night. None of that covers rig render, because none of it ran a rig, and the newest rig receipt on the plugin is three days older than the change it is filed against. That is the whole finding, sitting in my own repo, on the day I wrote it up.&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": "Every Verdict Carries the Scope It Actually Ran",&lt;br&gt;
  "description": "A verdict covers only what it ran. Four same-day cases, including a request-forgery class closed by deleting the feature it lived in.",&lt;br&gt;
  "datePublished": "2026-08-25T08:00:00-05:00",&lt;br&gt;
  "author": { "@type": "Person", "name": "Jeremy Longshore" },&lt;br&gt;
  "url": "&lt;a href="https://startaitools.com/posts/a-green-result-only-covers-what-it-ran/" rel="noopener noreferrer"&gt;https://startaitools.com/posts/a-green-result-only-covers-what-it-ran/&lt;/a&gt;",&lt;br&gt;
  "isPartOf": { "@type": "Blog", "name": "Start AI Tools", "url": "&lt;a href="https://startaitools.com" rel="noopener noreferrer"&gt;https://startaitools.com&lt;/a&gt;" }&lt;br&gt;
}&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-gate-that-could-not-fail/"&gt;Make the Guard Prove It Can Fail&lt;/a&gt;: four gates in one day whose verdicts were decoupled from the thing they claimed to measure, which is the direct ancestor of corrupting the metrics table on purpose.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/the-lane-that-reviewed-nothing/"&gt;Every Check Should Report What It Did Not Look At&lt;/a&gt;: the lane-level version of the same finding, where the scope of a review is part of its output.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/blog/the-green-badge-came-back-through-a-hyphen/"&gt;Refusing to Classify Beats Matching Harder&lt;/a&gt;: a status classifier that refuses wording it cannot positively recognize, and the hyphen that walked past a negation guard.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>testing</category>
      <category>cicd</category>
      <category>devops</category>
    </item>
    <item>
      <title>Refusing to Classify Beats Matching Harder</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Wed, 26 Aug 2026 10:26:32 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/refusing-to-classify-beats-matching-harder-4i45</link>
      <guid>https://dev.to/jeremy_longshore/refusing-to-classify-beats-matching-harder-4i45</guid>
      <description>&lt;p&gt;Mission Control is the internal governance dashboard over the Intent Solutions estate. One of its views composes the decision log into a page: one row per governance record, each row carrying a status of ratified, pending, deferred, superseded, or unknown. The composer that produces those rows is &lt;code&gt;ops/decisions-view/compose.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The house law for that view is parse-or-UNKNOWN. If the composer cannot read a record's status off the documented convention, the row lands on unknown and says so loudly. Nothing is inferred.&lt;/p&gt;

&lt;p&gt;The composer's classifier, the &lt;code&gt;classify_status&lt;/code&gt; function, violated that law on its first settlement review, and then violated it again after the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The original bug: substring matching in the status classifier
&lt;/h2&gt;

&lt;p&gt;Here is what the classifier looked like before any of this started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;STATUS_TOKENS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SUPERSEDED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;superseded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PENDING&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DEFER&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deferred&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RATIFIED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ratified&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DECIDED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ratified&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;classify_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_raw&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status_raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;STATUS_TOKENS&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;token&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;if token in upper&lt;/code&gt; is a substring containment test. &lt;code&gt;RATIFIED&lt;/code&gt; is a substring of &lt;code&gt;UNRATIFIED&lt;/code&gt;. &lt;code&gt;DECIDED&lt;/code&gt; is a substring of &lt;code&gt;UNDECIDED&lt;/code&gt;. &lt;code&gt;RATIFIED&lt;/code&gt; is also a substring of &lt;code&gt;NOT YET RATIFIED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So three real classes of governance record (&lt;code&gt;UNDECIDED&lt;/code&gt;, &lt;code&gt;UNRATIFIED DRAFT&lt;/code&gt;, &lt;code&gt;NOT YET RATIFIED&lt;/code&gt;) all classified as ratified and rendered the calm green badge. The page reported the exact opposite of what the record said. An independent code review found it during the B7.6 settlement walk and filed it CRITICAL, which is the correct severity: a dashboard that says settled over an unsettled record is worse than a dashboard that is down, because nobody goes and reads the record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 1: word boundaries plus a negation refusal
&lt;/h2&gt;

&lt;p&gt;The round-1 fix was two changes, not one.&lt;/p&gt;

&lt;p&gt;First, the tokens became compiled patterns anchored at word boundaries, so containment stopped being the matching rule.&lt;/p&gt;

&lt;p&gt;Second, and this is the part that carries the argument, a negation check ran &lt;em&gt;before&lt;/em&gt; any positive match and refused classification outright.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;NEGATED_STATUS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(NOT|NEVER|NO|NON|WITHOUT|UN(?:RATIFIED|DECIDED|APPROVED|SETTLED))\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;STATUS_TOKENS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\bSUPERSEDED\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;superseded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\bPENDING\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\bDEFER&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deferred&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\bRATIFIED\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ratified&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\bDECIDED\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ratified&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;classify_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_raw&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Returns (status, None) on a classified token, or (None, reason).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status_raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&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;NEGATED_STATUS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Status wording contains a negation token ...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;STATUS_TOKENS&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;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Status text matches no documented mapping token &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(SUPERSEDED/PENDING/DEFER/RATIFIED/DECIDED)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the return type changed from a bare status to a &lt;code&gt;(status, reason)&lt;/code&gt; pair. A refusal now has to explain itself, which means the unknown row on the page carries the specific reason it landed there rather than a shrug.&lt;/p&gt;

&lt;p&gt;The stated rationale in the commit body was negation refusal over negation classification: UNKNOWN is the only safe landing for wording the mapping does not positively recognize. Two fixtures went in with it (D908 and D909, by their decision IDs) and drills 2, 6, and 7 were extended to cover them.&lt;/p&gt;

&lt;p&gt;Three more defects rode along in the same commit, all in the renderer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rows missing a required file or title string now hit a clean rc=2 refusal. They used to raise a KeyError traceback, which is a refusal too, just an ugly one that looks like a crash instead of a decision.&lt;/li&gt;
&lt;li&gt;The summary can no longer disagree with the rows beneath it. &lt;code&gt;entries_total&lt;/code&gt;, the sum of &lt;code&gt;status_counts&lt;/code&gt;, and the escalation &lt;code&gt;entries_pending&lt;/code&gt; are all cross-checked against what actually rendered. A summary that is computed independently of the rows will eventually drift from them.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;esc()&lt;/code&gt; escapes backslashes first, so a backslash in the input cannot re-arm a special character that a later escape step introduces. Escaping order is not a style question.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That shipped, and the settlement review re-ran against it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 2: the badge came back through a hyphen
&lt;/h2&gt;

&lt;p&gt;The round-2 review demonstrated a bypass on the same day: &lt;code&gt;UN-RATIFIED&lt;/code&gt; and &lt;code&gt;UN DECIDED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Walk it through the round-1 code. &lt;code&gt;NEGATED_STATUS&lt;/code&gt; looks for &lt;code&gt;UNRATIFIED&lt;/code&gt; as one word. &lt;code&gt;UN-RATIFIED&lt;/code&gt; is not that word. The hyphen is a word boundary, so the negation pattern misses. Then &lt;code&gt;STATUS_TOKENS&lt;/code&gt; runs &lt;code&gt;\bRATIFIED\b&lt;/code&gt; against &lt;code&gt;UN-RATIFIED&lt;/code&gt;, and the boundary between &lt;code&gt;UN-&lt;/code&gt; and &lt;code&gt;RATIFIED&lt;/code&gt; is a real word boundary, so &lt;code&gt;RATIFIED&lt;/code&gt; matches positively.&lt;/p&gt;

&lt;p&gt;The green badge came back, and it came back through a negation pattern that only recognized the fused single-word form. Word boundaries are a wall between whole words. They are not a wall between a prefix and the word it negates, and a negation guard whose token list only spells the attached form inherits that gap for free.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why word boundaries do not block prefixes
&lt;/h3&gt;

&lt;p&gt;A word boundary is a transition between a word character and a non-word character. A hyphen is a non-word character and a space is a non-word character, so &lt;code&gt;UN-RATIFIED&lt;/code&gt; and &lt;code&gt;UN RATIFIED&lt;/code&gt; both carry a real boundary between the prefix and the token. That means two things at once. The negation pattern, if it only knows &lt;code&gt;UNRATIFIED&lt;/code&gt; as a single word, does not match. The positive pattern &lt;code&gt;\bRATIFIED\b&lt;/code&gt; then matches cleanly against the right half. Word boundaries are not a defense against a prefix, because the prefix is on the other side of the boundary. The only thing that covers the separated form is a pattern that names the separation.&lt;/p&gt;

&lt;p&gt;The round-2 fix widened the negation pattern to recognize the detached prefix form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;NEGATED_STATUS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(NOT|NEVER|NO|NON|WITHOUT)\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;|\bUN[-\s]?(?:RATIFIED|DECIDED|APPROVED|SETTLED|PENDING|DEFERRED|&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SUPERSEDED)\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;UN[-\s]?&lt;/code&gt; covers &lt;code&gt;UNRATIFIED&lt;/code&gt;, &lt;code&gt;UN-RATIFIED&lt;/code&gt;, and &lt;code&gt;UN RATIFIED&lt;/code&gt; in one alternation, and the token list behind it grew to cover the states that round 1 had not enumerated (&lt;code&gt;PENDING&lt;/code&gt;, &lt;code&gt;DEFERRED&lt;/code&gt;, &lt;code&gt;SUPERSEDED&lt;/code&gt;). Two more fixtures went in, numbered by ledger position and decision ID: 110/D910 for the hyphenated form and 111/D911 for the spaced form, and the fixture ledger reached 11 entries with the drill counts now derived from the ledger instead of hardcoded next to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just fix the regex harder: refusal ordering against pattern breadth
&lt;/h2&gt;

&lt;p&gt;This is the obvious objection and it deserves a straight answer, because the round-2 fix &lt;em&gt;is&lt;/em&gt; a better regex. So what distinguishes it from the round-1 fix, which was also a better regex?&lt;/p&gt;

&lt;p&gt;The ordering. Both rounds kept the same structural property: the refusal check runs first and returns unconditionally, and the positive matcher never gets to vote on a string that the negation guard has claimed. Round 1 established that structure. Round 2 only widened the pattern feeding it.&lt;/p&gt;

&lt;p&gt;That matters because the failure mode is asymmetric. If the negation pattern is too narrow, a record gets classified wrongly and shows a confident green badge. If the negation pattern is too broad, a record that could have been read lands on unknown with a stated reason, and a human goes and reads it. One of those is a silent lie and the other is visible extra work. &lt;a href="https://startaitools.com/posts/every-safety-gate-has-a-failure-direction/" rel="noopener noreferrer"&gt;Every Safety Gate Has a Failure Direction&lt;/a&gt; works the same asymmetry through a set of pull-request gates.&lt;/p&gt;

&lt;p&gt;So the choice was an explicit &lt;code&gt;UN[-\s]?TOKEN&lt;/code&gt; prefix rather than a standalone &lt;code&gt;\bUN\b&lt;/code&gt; negator. A bare &lt;code&gt;UN&lt;/code&gt; negator would have been broader still, but it swallows unrelated words that happen to contain or abut &lt;code&gt;UN&lt;/code&gt;, and breadth is only free up to the point where it starts refusing records that are perfectly readable. The prefix form covers the demonstrated bypass without reaching past it.&lt;/p&gt;

&lt;p&gt;So the precise claim is narrower than "stop using regex" and more useful. Match as hard as you like on the refusal condition, and widen it the moment a bypass is demonstrated. Do not widen the acceptance condition to compensate, and never let it run first. Round 1 and round 2 are both better regexes. What makes them fixes rather than patches is that both of them added breadth on the side where being wrong costs a human ten minutes, not on the side where being wrong prints a false green badge. That ordering is the durable property. The pattern behind it will keep needing edits, and that is fine, because a too narrow refusal fails loudly the next time somebody writes a new negation and a review catches it. &lt;a href="https://startaitools.com/posts/the-refusal-nobody-heard/" rel="noopener noreferrer"&gt;The Refusal Nobody Heard&lt;/a&gt; is the failure mode on the other side of that bet: a guard that refused correctly and had nothing wired to listen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification, and what did not change
&lt;/h2&gt;

&lt;p&gt;The classifier was probed against every reproduction the round-2 reviewer supplied (&lt;code&gt;UN-RATIFIED DRAFT&lt;/code&gt;, &lt;code&gt;UN RATIFIED&lt;/code&gt;, &lt;code&gt;Un-Ratified&lt;/code&gt;, &lt;code&gt;UN-DECIDED&lt;/code&gt;), all resolving to unknown with the negation reason attached. It was also probed against the adversarial cases that must &lt;em&gt;not&lt;/em&gt; trip the guard: &lt;code&gt;RE-RATIFIED&lt;/code&gt; and &lt;code&gt;NOTWITHSTANDING&lt;/code&gt; kept their prior classifications, along with all five live modern records. &lt;code&gt;run-proof.sh&lt;/code&gt; ran green with the extended drill.&lt;/p&gt;

&lt;p&gt;Live truth was unchanged through the whole episode: 66 records at 3 ratified, 1 deferred, 0 superseded, 1 pending, 61 unknown, escalation unknown. That is the honest framing from the round-1 commit body, and it is worth repeating. The fix changes what a hostile future record could do to the page. It does not change what today's page says. Nobody had actually filed an &lt;code&gt;UN-RATIFIED&lt;/code&gt; record yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The evidence bundle got refused too
&lt;/h2&gt;

&lt;p&gt;The round-2 audit returned &lt;code&gt;EVIDENCE_INCOMPLETE&lt;/code&gt; on a second and completely unrelated ground. The rollback receipt in the evidence bundle named the prior commit, while the bundle README described a future re-rehearsal as already done.&lt;/p&gt;

&lt;p&gt;The receipt was rewritten as a ledger of executed rehearsals only. Three entries, each with a recorded tree hash, no future-tense claims. A stale seven-entry fixture count in the slice README got corrected in the same pass.&lt;/p&gt;

&lt;p&gt;This is the same defect class as the classifier, one layer up. A document that asserts a rehearsal happened because it was scheduled to happen is inferring past a fact it does not have, exactly like a classifier reporting ratified because &lt;code&gt;RATIFIED&lt;/code&gt; appeared somewhere in the string.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same lesson, from the other direction
&lt;/h2&gt;

&lt;p&gt;The founder-view hardening landed the same day, under &lt;code&gt;spine-bxp.8&lt;/code&gt;, and it carries the sharper version of the point.&lt;/p&gt;

&lt;p&gt;The schema &lt;code&gt;founder-portfolio-view.v0&lt;/code&gt; went 1.0.0 to 1.1.0. The coverage-present rule now requires a present, nonzero &lt;code&gt;populations.governed&lt;/code&gt; as a standalone law, rather than one enforced only transitively through the upstream contract, so an omission upstream can no longer smuggle a coverage claim through. The renderer picked up the backslash-first escaping law at value level across reasons, states, count keys, and &lt;code&gt;observed_at&lt;/code&gt;, plus structural validation that cleanly refuses non-dict sections, non-dict payloads, unknown section names, and missing envelope fields at rc=2 instead of a traceback.&lt;/p&gt;

&lt;p&gt;The interesting part is what the new drill found. The coverage-present branch had zero drill coverage. Exercising it for the first time exposed a latent CRITICAL: the upstream ownership state &lt;code&gt;governed&lt;/code&gt; was outside the view's section enum, which means the founder view would have hard FATALed on the exact day the estate actually became governed.&lt;/p&gt;

&lt;p&gt;That bug was scheduled to fire on success. Every test to date passed because the condition it depended on had never been true yet, and the day it became true is the day the dashboard goes down. Undrilled branches do not fail on the schedule you would pick.&lt;/p&gt;

&lt;p&gt;The fix widened the enum verbatim rather than mapping &lt;code&gt;governed&lt;/code&gt; to &lt;code&gt;ready&lt;/code&gt;, because the house law is that upstream state passes through verbatim. Same instinct as the negation guard: do not translate a value you do not own into one you do.&lt;/p&gt;

&lt;p&gt;Verification: &lt;code&gt;run-proof.sh&lt;/code&gt; green across 13 drill groups, &lt;code&gt;schemas/validate.py&lt;/code&gt; green over 72 schemas with 119 valid and 144 invalid fixtures. The regenerated page surfaced the capability matrix as stale-loud at 126 hours, which is honest drift shown rather than suppressed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Settling the epic
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;decision-log/065&lt;/code&gt; (D216) closed the lifecycle. B7.1 through B7.6 closed with independent evidence. &lt;code&gt;spine-bxp.7&lt;/code&gt; was formally deferred and never closed, carrying a full re-entry authority chain, which is the difference between deciding not to do something and quietly dropping it. The guardian pass returned APPROVE, and the fact that it ran after the settlement rather than before it was recorded rather than smoothed over.&lt;/p&gt;

&lt;p&gt;The final integrated audit ran on merged main and returned EVIDENCE_COMPLETE on three dimensions: no false-green (every dark source renders dark), no disclosure drift (gate clean over 1622 files plus a manual sweep), and cross-view consistency (the B6 producers-absent story identical across views, populations consistent, all provenance lines resolving).&lt;/p&gt;

&lt;p&gt;One thing is owed and named in the CHANGELOG rather than buried: the &lt;code&gt;mc:matrix&lt;/code&gt; regen. The committed capability-matrix page trails its local state artifact by about two days. That is outside B7 scope and it is written down where the next person will hit it. A page that trails its own state artifact and says so is the document-layer version of the unknown badge, which is the entire point.&lt;/p&gt;

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

&lt;p&gt;One more instance of the same instinct, at a different layer. The claude-code-plugins marketplace finally enforced its own census deadline, a month after that deadline passed. Refusing to list a source that cannot pass the bar is the catalog-level version of refusing to classify a string the mapping cannot read. A whole-catalog quality census on 2026-07-08 put failing sources on a fix-or-removed clock with notify issues filed upstream and a deadline of 2026-07-22. On 2026-08-23, &lt;code&gt;census-watch --enforce&lt;/code&gt; re-validated every notified skill at upstream default-branch HEAD using &lt;code&gt;validate-skills-schema.py --marketplace&lt;/code&gt;. Clusters still failing had their &lt;code&gt;sources.yaml&lt;/code&gt; entries removed (dated NOTE comments left in place), their mirror directories under &lt;code&gt;plugins/&lt;/code&gt; deleted, and their catalog entries removed: 27 source entries across two clusters, &lt;code&gt;numman-ali/n-skills&lt;/code&gt; and &lt;code&gt;wondelai/skills&lt;/code&gt;, landing as 343 files changed and 72,206 deletions. Re-listing is explicitly welcome once the skills pass the validator.&lt;/p&gt;

&lt;p&gt;A cascade of template-stamped pack delistings followed the same procedure: Veeva, Wispr, StackBlitz, and duplicate placeholder skills pulled from the Together pack. Separately, &lt;code&gt;fix(freshie): make stub detection deterministic&lt;/code&gt; landed, and the Adobe pack's skill sections were completed rather than removed.&lt;/p&gt;

&lt;p&gt;Worth being precise about what is and is not interesting there. The line counts are large because deleting a mirrored catalog is mechanically large. What matters is that a deadline the marketplace published against itself a month and a half earlier was actually enforced against its own inventory, on a re-validation run, with the removal criteria unchanged from the announcement.&lt;/p&gt;

&lt;p&gt;Elsewhere: one journal post landed on comehomealabama. A self-updating profile card shipped to the GitHub profile repo and was reverted the same day. The previous day's post dual-published to tonsofskills.com/blog and went into the intent-solutions-landing field notes.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://startaitools.com/posts/every-safety-gate-has-a-failure-direction/" rel="noopener noreferrer"&gt;Every Safety Gate Has a Failure Direction&lt;/a&gt; works the same asymmetry through a set of shell gates on every pull request: which way a gate falls when it cannot tell is the whole design.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://startaitools.com/posts/disclosure-gate-reject-pii-at-source/" rel="noopener noreferrer"&gt;Reject PII at the Source: A Disclosure Gate at Intake&lt;/a&gt; applies refusal at the data boundary rather than attempting interpretation downstream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://startaitools.com/posts/software-supply-chain-security/" rel="noopener noreferrer"&gt;Software Supply Chain Security After Axios&lt;/a&gt; covers the harder version of the same problem: a source that clears every bar you set and is still hostile. The census only bounds the easy case, sources that cannot clear the bar at all.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>architecture</category>
      <category>python</category>
      <category>testing</category>
    </item>
    <item>
      <title>Every Check Should Report What It Did Not Look At</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Mon, 24 Aug 2026 11:30:12 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/every-check-should-report-what-it-did-not-look-at-2nn3</link>
      <guid>https://dev.to/jeremy_longshore/every-check-should-report-what-it-did-not-look-at-2nn3</guid>
      <description>&lt;p&gt;Yesterday I wrote about &lt;a href="https://dev.to/blog/the-skip-that-counted-as-a-pass/"&gt;the gate runner that counted SKIP as PASS&lt;/a&gt;, and the rig proof receipt that closed it. That is the setup, not today's subject. Today's subject is what happened next. The same defect shape surfaced twice more inside a single day, and the second time it was inside the tooling built to catch it.&lt;/p&gt;

&lt;p&gt;58 commits across 11 repos. The interesting part is that three of them are the same bug wearing different clothes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The review lane that could not review
&lt;/h2&gt;

&lt;p&gt;Seven plugin repos vendor a four lane MiniMax review workflow. Every lane carries the same guard.&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;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;review-correctness&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vars.ENABLE_MINIMAX_REVIEW == 'true'&lt;/span&gt;
    &lt;span class="c1"&gt;# three sibling lanes, same condition&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the repository variable is unset, or the API key is absent, the workflow conditional evaluates false and GitHub Actions skips the jobs. A skipped job renders as a grey tick. A reader scanning a pull request sees four ticks in the checks list and concludes the pull request was reviewed. Nothing ran. No model read a line of the diff.&lt;/p&gt;

&lt;p&gt;That is precisely the shape I had spent the week digging out of the &lt;a href="https://dev.to/blog/the-gate-that-could-not-fail/"&gt;gate runner&lt;/a&gt;, reintroduced in the workflow whose entire job is to catch bad diffs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a skipped GitHub Actions job show as passing
&lt;/h3&gt;

&lt;p&gt;Not literally, but in practice yes. A skipped job renders as a grey tick in the checks list rather than a red X, and a reader scanning the list reads absence of failure as success. GitHub reports the job's real state accurately. The failure is that a human, and a branch protection summary, treat grey and green the same way.&lt;/p&gt;

&lt;p&gt;The fix is a status job with no &lt;code&gt;if&lt;/code&gt; at all, so it always runs and always reports. When the lanes are off it emits a GitHub warning annotation, and the annotation says the thing plainly: green ticks on this PR do not mean it was reviewed. On a fork pull request it reports a notice instead of a warning, because a fork never receives the repository secret, so skipping there is by design rather than misconfiguration. A warning that fires on every external contribution is a warning people learn to ignore.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not just fail the build
&lt;/h3&gt;

&lt;p&gt;The obvious approach is to make the workflow fail when the lanes are disabled. No ambiguity, no annotation to read, a red X that nobody mistakes for a pass.&lt;/p&gt;

&lt;p&gt;I did not do that, and the reason is what the lanes are. They are advisory. A maintainer can merge a plugin fix without a model review, and the seven repos deliberately ship with the feature off until someone sets the variable and the key. Failing the build converts an optional feature into a mandatory one by side effect. The next person to hit a red X on a repo that never enabled reviews would not go enable reviews, they would delete the check, and then the disabled state becomes invisible again with an extra step of history behind it.&lt;/p&gt;

&lt;p&gt;The requirement was never that the lanes must run. It is that a disabled lane must not be mistakable for a passing one. An always running status job satisfies exactly that requirement and nothing more. Failing the build satisfies a stronger requirement I did not have and do not want.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix that shipped a merge conflict
&lt;/h2&gt;

&lt;p&gt;The commit that landed this is titled "stop a disabled review lane from rendering as a passing one." It shipped a merge conflict into &lt;code&gt;.github/workflows/minimax-review.yml&lt;/code&gt; and pushed it to main. Six of the seven entry repos carried three conflict markers each.&lt;/p&gt;

&lt;p&gt;The workflow no longer parsed. Every run died at 0s, while the gate lane and the test jobs reported success in the same checks list beside it.&lt;/p&gt;

&lt;p&gt;Root cause was a rebase where I assumed only the changelog conflicted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;--ours&lt;/span&gt; CHANGELOG.md
git add &lt;span class="nt"&gt;-A&lt;/span&gt;               &lt;span class="c"&gt;# staged the workflow WITH its conflict markers&lt;/span&gt;
git rebase &lt;span class="nt"&gt;--continue&lt;/span&gt;    &lt;span class="c"&gt;# committed them&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;git add -A&lt;/code&gt; does not care whether a file still contains &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt;. It stages what is on disk.&lt;/p&gt;

&lt;p&gt;The part worth writing down is not the rebase mistake. It is the verification. I checked the fix had landed by grepping for the string &lt;code&gt;Review lanes status&lt;/code&gt;, found a match, and reported the file present and correct. The string was there. It was inside a file that could not parse.&lt;/p&gt;

&lt;p&gt;That is a check narrower than the claim it makes. Which is the same defect the broken commit was fixing. The fix for skip renders as green shipped a workflow that renders as nothing at all.&lt;/p&gt;

&lt;p&gt;The second verification parses instead of greps.&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;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'^&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;\|^=======\|^&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;          &lt;span class="c"&gt;# expect 0&lt;/span&gt;
python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'import yaml,sys; yaml.safe_load(open(sys.argv[1]))'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
actionlint &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;0 conflict markers, &lt;code&gt;yaml.safe_load&lt;/code&gt; succeeds, &lt;code&gt;actionlint&lt;/code&gt; reports 0 issues across all six files. A grep answers "does this text appear." Only a parser answers "is this a workflow."&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent that reports the denominator
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;claude-code-plugins&lt;/code&gt; I added an agent called &lt;code&gt;omarchy-coverage-reporter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every other internal agent in that repo answers "is this correct." None of them answered "what did we actually look at." Five separate incidents in the days before had turned on that second question, so it got its own agent.&lt;/p&gt;

&lt;p&gt;It runs the gate lane, the rig checks and the offline tests, then reports the denominator: how many applicable checks exist, and how many executed. The core of it is splitting the single SKIP token into two verdicts that mean opposite things and were previously aggregated together.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NOT APPLICABLE&lt;/td&gt;
&lt;td&gt;Predicate false. No QML in this tree, so a QML gate has nothing to say.&lt;/td&gt;
&lt;td&gt;Counts as a pass.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UNPROVEN&lt;/td&gt;
&lt;td&gt;Predicate true, checker could not run. Tree has QML, qmllint was unresolvable.&lt;/td&gt;
&lt;td&gt;Never a pass.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INCONCLUSIVE&lt;/td&gt;
&lt;td&gt;Any UNPROVEN in the set.&lt;/td&gt;
&lt;td&gt;Neither pass nor fail. Nobody knows yet.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;INCONCLUSIVE is neither failure nor pass. It means nobody knows yet. That is the state the old runner had no way to express, which is why it kept reporting green: given only PASS, FAIL and SKIP, an unresolvable checker has to land somewhere, and SKIP was the least alarming bucket.&lt;/p&gt;

&lt;p&gt;The agent has no Write tool and no Edit tool. That constraint is deliberate and it is the design decision I would defend hardest. A reporter that can repair what it measures cannot be trusted about what it measured. If it can fix the qmllint resolution and then report full coverage, the report is a claim about a tree the reporter changed, and no reader can tell which findings were observations and which were consequences of its own edits. Repairs route to &lt;code&gt;omarchy-gate-author&lt;/code&gt;. Judgment routes to &lt;code&gt;omarchy-submission-auditor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I chose a new agent over extending the existing auditor because counting what ran and judging what it means are different jobs. The auditor had already demonstrated the failure mode of merging them: it produced a confident verdict over a corpus it never established. It was not wrong about the files it read. It was wrong about which files there were.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same principle in two smaller places
&lt;/h2&gt;

&lt;p&gt;Naming these is the point. One fix is a fix. Three places in one day, counting the coverage reporter, is a pattern.&lt;/p&gt;

&lt;p&gt;The changelog generator silently dropped any commit subject that was not a conventional commit. It now reports the count and lists examples. Running it surfaced exactly one skipped commit per affected repo, and each one was GitHub's auto generated "Initial commit." Correctly skipped, and now visibly so. The output did not change its behaviour, it changed what it admits.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;omarchy-crew-chief-entry&lt;/code&gt;, the spool reader is bounded to the newest 64 files at 4 KB each. It now emits a census line stating how many files exist, not how many it read.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sessions: 63 shown, +338 not shown (401 files, 713 KB)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under a deliberate 401 file, 713 KB flood, including one 500 KB garbage file, the reader returned 10 KB and the widget rendered 63 live sessions. Before the census line, the parser received well formed chunks, found nothing malformed, and concluded nothing was missing. It would have reported a complete fleet that was short 338 sessions. Every individual piece of that pipeline behaved correctly. The bound was correct, the parse was correct, the report was correct about its input. Nobody was carrying the number 401.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;contributing-clanker&lt;/code&gt; closed an SSRF that had escaped review twice. Listening Post guarded its curl call with a regex meant to allow only literal IPv4.&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="o"&gt;/^&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}){&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;   &lt;span class="c1"&gt;// four decimal parts and nothing else&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;curl resolves through &lt;code&gt;inet_aton&lt;/code&gt;, which accepts one to four parts, reads a leading &lt;code&gt;0&lt;/code&gt; as octal and &lt;code&gt;0x&lt;/code&gt; as hex. So &lt;code&gt;127.1&lt;/code&gt;, &lt;code&gt;0177.0.0.1&lt;/code&gt; and &lt;code&gt;0x7f.1&lt;/code&gt; all fail the regex, get treated as public hostnames, and reach loopback. New gate c38 flags that regex shape in any file that also touches the network, and the fix hint teaches the inversion (allowlist what you accept, then resolve and check the resolved address) rather than adding three more bad patterns to match, because enumerating bad forms is exactly what failed twice.&lt;/p&gt;

&lt;p&gt;The changelog security classifier matched on the pattern &lt;code&gt;'bound '&lt;/code&gt; with a trailing space. That matches "bound the spool read" and misses "bounded read," so a real security fix could file under Fixed and quietly leave the security section of a release note. This one is a plain false negative rather than an instance of the pattern above, since nothing new gets reported, the match just stopped being wrong. Verified both directions: "add a bounded read" now classifies as Security and did not before.&lt;/p&gt;

&lt;p&gt;Gate c37, the rig receipt fingerprint, widened to cover every shipped &lt;code&gt;.js&lt;/code&gt; rather than just the manifest and QML. These plugins keep parsing, host filters and state handling in a &lt;code&gt;Model.js&lt;/code&gt; that QML imports, so the receipt was certifying a tree whose entire behaviour could change underneath it.&lt;/p&gt;

&lt;p&gt;Gate c36 now requires a width constraint AND an overflow rule, not either. It had accepted a QML &lt;code&gt;Text&lt;/code&gt; as bounded if it declared any one of &lt;code&gt;width&lt;/code&gt;, &lt;code&gt;elide&lt;/code&gt; or &lt;code&gt;wrapMode&lt;/code&gt;. That is wrong on QML semantics: &lt;code&gt;elide&lt;/code&gt; with no width constraint is a no op, since elision is computed against element width. The gate's own fix hint already read "elide with a width" while the check accepted elide alone, so the enforcement was looser than the advice it printed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rig-render.sh&lt;/code&gt; landed in &lt;code&gt;omarchy-widget-template&lt;/code&gt;. It starts a headless sway on the wlroots backend, installs the plugin into the rig's Omarchy config, launches Quickshell, opens the panel through the plugin's own IPC target, and grabs the frame with grim. Every plugin in the family had been submitted having never been loaded. Static tools cannot see a contract error: Bazaar shipped a &lt;code&gt;PanelWindow&lt;/code&gt; where the first party popup is a &lt;code&gt;KeyboardPanel&lt;/code&gt;, passed all nine gates and qmllint, and only a running shell said &lt;code&gt;Cannot assign to non-existent property contentHeight&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;omarchy-bazaar-entry&lt;/code&gt; gained install, installed state and a kind filter. Measured before the change: Okomart 1,148 views and 286 installs, Plugin Manager 209 views and 95 installs at 45 percent conversion, Bazaar 82 views and 11 installs at 13 percent. Install shells out to the first party CLI with an argv array and no shell string, because the repository URL comes from a third party catalog and building a shell string out of it is the exec injection shape gate c34 exists to refuse. The installed state scan keys on the id inside each manifest, never the directory name, because Omarchy installs under the full plugin id while a hand clone is usually a short name, and the rig carried both &lt;code&gt;listening-post&lt;/code&gt; and &lt;code&gt;io.github.jeremylongshore.listening-post&lt;/code&gt; for the same plugin. Tests caught a version comparison bug: the first version treated a missing segment as smaller than everything, so &lt;code&gt;1.2.0&lt;/code&gt; read as newer than &lt;code&gt;1.2&lt;/code&gt;, and every up to date plugin on a two segment version would have shown a phantom update badge.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;omarchy-pit-wall-entry&lt;/code&gt; coloured the Formula 1 standings tables by team. Only the hue comes from the team. Saturation and lightness are fixed at the call site, so Ferrari reads as Ferrari without a hardcoded hex fighting whatever theme the user runs, and unknown or future teams fall through to a stable hue derived from the name instead of collapsing into a single default.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;omarchy-wait-state-entry&lt;/code&gt; shipped a PSI monitor.&lt;/p&gt;

&lt;p&gt;Per repo commit counts: omarchy-pit-wall-entry 8, omarchy-bazaar-entry 7, omarchy-crew-chief-entry 7, omarchy-x-files-entry 7, omarchy-listening-post-entry 6, omarchy-mlb-booth-entry 6, omarchy-docket-entry 6, omarchy-wait-state-entry 4, claude-code-plugins 4, omarchy-widget-template 2, contributing-clanker 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who did what
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;claude-code-plugins&lt;/code&gt; work ran across seven sessions in two different CLIs: 456 turns, 677 tool calls, 27 errors hit, spanning 1397 minutes. &lt;code&gt;Claude Opus 5&lt;/code&gt; ran the Claude Code side and carried the gate work and the coverage reporter design. &lt;code&gt;GPT-5.6 Sol&lt;/code&gt; ran the Codex side, where it built the Wait State plugin and traced a governed-brain startup failure to a config pointing at a cached plugin version 1.1.2 that no longer existed on disk, with only 1.2.0 installed.&lt;/p&gt;

&lt;p&gt;The part I did not plan is the one worth keeping. &lt;code&gt;GPT-5.6 Sol&lt;/code&gt; spent its later sessions running the coverage reporter role that &lt;code&gt;Claude Opus 5&lt;/code&gt; had authored earlier the same day, as an independent read-only audit, on a tree the authoring model had never seen. It stated the rule back before using it, that the denominator comes from the canonical lane and a skipped applicable check counts as unproven rather than pass, and then it returned a BLOCK on Wait State: install reality unproven, because the repository had no commits and no remote, so the documented clone URL could not be resolved. That is the UNPROVEN verdict doing exactly the job it was written for, on day one, in the hands of a model that did not write it. It also found the freshness checker could only discover canonical gates whose names were already in the local manifest, which is a coverage hole of precisely the kind the agent exists to name.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Claude Fable 5&lt;/code&gt; ran a short intent-os thread. &lt;code&gt;Claude Sonnet 5&lt;/code&gt; was on the blog pipeline thread.&lt;/p&gt;

&lt;p&gt;Zero operator course corrections that day, and that deserves one honest sentence rather than a victory lap. It was not a day of being redirected. It was a day of parallel repair on a defect shape that had already been named, which is the easiest kind of day to run unattended and tells you very little about how the system handles a novel problem.&lt;/p&gt;

&lt;p&gt;The 27 errors were real and mostly environmental. A &lt;code&gt;shellcheck&lt;/code&gt; lint job failed the L2 gate. The rig container answered &lt;code&gt;sh: line 4: python3: command not found&lt;/code&gt;. QML threw &lt;code&gt;TypeError: Property 'spoolTruncated' of object [object Object] is not a function&lt;/code&gt; while the census line was being wired in. A script call hit &lt;code&gt;bash: scripts/gen-changelog.sh: No such file or directory&lt;/code&gt;. The headless rig was missing &lt;code&gt;swaybg&lt;/code&gt;. Every one of those was loud. None of them is the category of failure this post is about, which is the quiet kind that reports success.&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": "Every Check Should Report What It Did Not Look At",&lt;br&gt;
  "description": "A status job that always runs reports which checks executed and which are unproven, so a skipped GitHub Actions job cannot read as a pass.",&lt;br&gt;
  "datePublished": "2026-08-22T08:00:00-05:00",&lt;br&gt;
  "author": { "@type": "Person", "name": "Jeremy Longshore" },&lt;br&gt;
  "url": "&lt;a href="https://startaitools.com/posts/the-lane-that-reviewed-nothing/" rel="noopener noreferrer"&gt;https://startaitools.com/posts/the-lane-that-reviewed-nothing/&lt;/a&gt;",&lt;br&gt;
  "isPartOf": { "@type": "Blog", "name": "Start AI Tools", "url": "&lt;a href="https://startaitools.com" rel="noopener noreferrer"&gt;https://startaitools.com&lt;/a&gt;" }&lt;br&gt;
}&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://dev.to/blog/the-skip-that-counted-as-a-pass/"&gt;What a Skipped Check Is Worth in CI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/we-told-the-auditors-to-refute-us/"&gt;We Told the Auditors to Refute Us&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/the-gate-that-could-not-fail/"&gt;The Gate That Could Not Fail&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>security</category>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>What a Skipped Check Is Worth in CI</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Sun, 23 Aug 2026 11:30:11 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/what-a-skipped-check-is-worth-in-ci-4l3</link>
      <guid>https://dev.to/jeremy_longshore/what-a-skipped-check-is-worth-in-ci-4l3</guid>
      <description>&lt;p&gt;A gate runner has three verdicts and only two of them are honest. PASS means the check ran and the code was fine. BLOCK means the check ran and the code was not. SKIP means nothing ran at all, and if your aggregator folds SKIP into the pass column, the summary line at the bottom of the run is not reporting on your code. It is reporting on your tooling install.&lt;/p&gt;

&lt;p&gt;That is what &lt;code&gt;gate-runner omarchy-submit&lt;/code&gt; was doing in &lt;code&gt;contributing-clanker&lt;/code&gt;. Two of the gates in the lane call &lt;code&gt;gate_skip&lt;/code&gt; when their binary is not resolvable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;c32&lt;/code&gt; shells out to &lt;code&gt;omarchy-plugin-validate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;c33&lt;/code&gt; shells out to &lt;code&gt;qmllint&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of those binaries live on the Omarchy rig. Neither exists on a dev box, and a dev box is where the lane actually runs. So the runner walked the whole set, hit two unresolvable binaries, skipped them, counted the skips as passes, and printed &lt;strong&gt;verdict PASS, 0 BLOCK&lt;/strong&gt; for plugins that had never run on Omarchy at all.&lt;/p&gt;

&lt;p&gt;They were being validated by hand every time instead. Which is exactly the "if someone remembers" failure the lane exists to end.&lt;/p&gt;

&lt;p&gt;An undesigned skip that greens the aggregate is worse than no gate, because it manufactures confidence.&lt;/p&gt;

&lt;p&gt;Seven repos vendor a copy of this lane (&lt;code&gt;omarchy-x-files-entry&lt;/code&gt;, &lt;code&gt;omarchy-listening-post-entry&lt;/code&gt;, &lt;code&gt;omarchy-docket-entry&lt;/code&gt;, &lt;code&gt;omarchy-mlb-booth-entry&lt;/code&gt;, &lt;code&gt;omarchy-crew-chief-entry&lt;/code&gt;, &lt;code&gt;omarchy-pit-wall-entry&lt;/code&gt;, and &lt;code&gt;omarchy-widget-template&lt;/code&gt;), so the fix had to be one that copies cleanly. About fifty commits landed across twelve repos on the day, and the plugin repos took between one and eight each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the gate cannot just do the check
&lt;/h2&gt;

&lt;p&gt;The obvious move is to make &lt;code&gt;c32&lt;/code&gt; and &lt;code&gt;c33&lt;/code&gt; reach the rig themselves. Run the container, run the validator, report what it says. No skip, no receipt, no new file format.&lt;/p&gt;

&lt;p&gt;The runner enforces a ten second wall clock per gate. A rig round trip does not fit in ten seconds, and raising the ceiling to fit it would mean every gate in the lane now waits on the slowest possible one. Gates that finish in fifty milliseconds would start sharing a budget with a container boot.&lt;/p&gt;

&lt;p&gt;So the check moves off the gate and the gate checks the evidence instead. The rig run happens once, deliberately, through &lt;code&gt;scripts/rig-verify.sh&lt;/code&gt;, and it leaves a receipt at &lt;code&gt;.rig-proof.json&lt;/code&gt;. The new gate &lt;code&gt;c37&lt;/code&gt; reads the receipt.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the receipt has to prove
&lt;/h2&gt;

&lt;p&gt;A receipt is only worth what it is coupled to. Four properties, each with a reason it exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It fingerprints the manifest and every &lt;code&gt;.qml&lt;/code&gt; file.&lt;/strong&gt; Those are precisely what the rig validates. Fingerprinting them means the receipt cannot certify code nobody ran. Change a file, the fingerprint moves, the receipt stops matching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It records failures rather than omitting them.&lt;/strong&gt; If the rig run fails, that goes in the receipt as a failure. A receipt that only ever recorded successes would make "the rig said no" and "the rig was never asked" the same observable state, which is the original bug wearing a different hat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It expires after fourteen days.&lt;/strong&gt; The rig tracks upstream Omarchy. A proof from six weeks ago is a proof about a platform that has since moved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It blocks only at submit time.&lt;/strong&gt; Gating every intermediate save on a rig round trip would teach people to work around the lane, and a lane people route around is not a lane.&lt;/p&gt;

&lt;p&gt;Verification, end to end against a real plugin entry: the lane BLOCKED with no receipt present, &lt;code&gt;scripts/rig-verify.sh&lt;/code&gt; produced one from an actual run inside the &lt;code&gt;omarchy-rig&lt;/code&gt; container, the lane then PASSED at eleven gates (the count before &lt;code&gt;c38&lt;/code&gt; landed later the same day), and editing a single &lt;code&gt;.qml&lt;/code&gt; file flipped it straight back to BLOCK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Widening the fingerprint the same day
&lt;/h2&gt;

&lt;p&gt;The first version of &lt;code&gt;c37&lt;/code&gt; fingerprinted the manifest and the QML. That scope was chosen to match what the rig's two tools read, and that was the wrong reason to choose it.&lt;/p&gt;

&lt;p&gt;The receipt does not claim "those two tools were happy." It claims &lt;strong&gt;this code was proven to run.&lt;/strong&gt; These plugins keep their parsing, host filtering, and state handling in a &lt;code&gt;Model.js&lt;/code&gt; that QML imports at load. Under the original scope, that entire file could change and the receipt would still match.&lt;/p&gt;

&lt;p&gt;Proven concretely: after the SSRF fix landed in Listening Post's &lt;code&gt;Model.js&lt;/code&gt;, &lt;code&gt;c37&lt;/code&gt; still returned PASS. The receipt was certifying a tree whose whole behaviour had changed underneath it.&lt;/p&gt;

&lt;p&gt;So the fingerprint now covers every shipped &lt;code&gt;.js&lt;/code&gt; too, including extension-less executables that previously sat below a &lt;code&gt;maxdepth&lt;/code&gt; of 2. The choice was widening the existing fingerprint function rather than adding a second receipt field, because this function and the one inside &lt;code&gt;rig-verify.sh&lt;/code&gt; have to agree byte for byte, and a single definition is the only way that stays true over time.&lt;/p&gt;

&lt;p&gt;The widened &lt;code&gt;c37&lt;/code&gt; BLOCKs the fixed Listening Post tree until &lt;code&gt;rig-verify.sh&lt;/code&gt; is re-run, and PASSes after. The coupling holds in both directions, which is the only version of that test worth running.&lt;/p&gt;

&lt;h2&gt;
  
  
  The clipped Text nobody could see
&lt;/h2&gt;

&lt;p&gt;Separate gate, same week, and it explains why "the tools are happy" is a weak claim.&lt;/p&gt;

&lt;p&gt;A QML &lt;code&gt;Text&lt;/code&gt; element with no &lt;code&gt;width&lt;/code&gt;, no &lt;code&gt;elide&lt;/code&gt;, and no &lt;code&gt;wrapMode&lt;/code&gt; lays out on a single line and gets clipped by whatever container holds it. The last words simply vanish.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight qml"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lays out on one line, container clips it, tail is gone&lt;/span&gt;
&lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The spend meter is your friend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;qmllint&lt;/code&gt; reports zero errors on that. Clipping is valid QML.&lt;/p&gt;

&lt;p&gt;I caught this three times by eye and never once by a test. The four plugin entries that existed at the time carry 240 offline tests between them and not one of them exercises a &lt;code&gt;.qml&lt;/code&gt; file. It reached a published marketplace &lt;code&gt;preview.png&lt;/code&gt; whose footer reads &lt;code&gt;The spend meter is y&lt;/code&gt;. Root cause was the widget template's own list row, so it is one defect copied into all four of them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;c36&lt;/code&gt; is the detector. The interesting part is not that it exists, it is how it decides.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rhyme: enumerating bad forms is the failure mode
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;c36&lt;/code&gt; shipped twice. The first version enumerated the shapes it knew about and missed the plain form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight qml"&gt;&lt;code&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;someProperty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is how an attacker-controlled GitHub author login reached a row with no width bound on it. The pattern list did not have that pattern.&lt;/p&gt;

&lt;p&gt;The second version stops matching shapes. It strips string literals and asks whether any identifier remains. If something computed is going into &lt;code&gt;text&lt;/code&gt;, the element needs a width constraint and an overflow rule, full stop.&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;# `value` is the right hand side of `text:`, captured, not the whole line.
# Strip the string literals out of it and see whether an identifier survives.
&lt;/span&gt;&lt;span class="n"&gt;residue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="s"&gt;[^&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\\]*(?:\\.[^&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\\]*)*&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;residue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="s"&gt;[^&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\\]*(?:\\.[^&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\\]*)*&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;residue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[A-Za-z_]\w*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;residue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A pure literal leaves an empty residue and is not flagged as computed. Anything&lt;br&gt;
with a surviving identifier is computed, so its length is not authored, so it&lt;br&gt;
needs a bound. There is a second shape underneath it for the case the first one&lt;br&gt;
does not cover: a string literal long enough to overrun a bar panel on its own,&lt;br&gt;
which the gate puts at more than 40 characters.&lt;/p&gt;

&lt;p&gt;Now hold that next to &lt;code&gt;c38&lt;/code&gt;, which landed the same day on a completely different problem.&lt;/p&gt;

&lt;p&gt;Listening Post guarded a &lt;code&gt;curl&lt;/code&gt; call with a host filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// four decimal parts, and nothing else&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\d{1,3}(\.\d{1,3}){3}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&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;curl does not resolve addresses that way. It resolves via &lt;code&gt;inet_aton&lt;/code&gt;, which accepts one to four parts, reads a leading &lt;code&gt;0&lt;/code&gt; as octal and a leading &lt;code&gt;0x&lt;/code&gt; as hex. So &lt;code&gt;127.1&lt;/code&gt;, &lt;code&gt;0177.0.0.1&lt;/code&gt; and &lt;code&gt;0x7f.1&lt;/code&gt; all sail past a filter that only knows one spelling of loopback, and all three reach loopback. That SSRF escaped human review twice on marketplace submission 1229.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;c38&lt;/code&gt; flags that regex shape in any file that also reaches the network. Its fix hint teaches the inversion, which is to allowlist the canonical form, rather than naming three more bad patterns, because enumerating bad forms is precisely what failed twice.&lt;/p&gt;

&lt;p&gt;Verified: &lt;code&gt;c38&lt;/code&gt; BLOCKs the pre-fix Listening Post tree at &lt;code&gt;Model.js:257&lt;/code&gt;, the exact line the maintainer cited, and PASSes the fixed tree.&lt;/p&gt;

&lt;p&gt;Two detectors, two different domains, same failure and same fix. Both broke the first time by listing the bad forms they had seen. Both got fixed by inverting to a structural rule about what a correct form has to contain.&lt;/p&gt;

&lt;p&gt;That is a denylist losing to an allowlist, which is not a new idea. What is worth noting is that neither of these started life looking like a security control. One was a layout rule and one was a host filter, and the denylist shape got in through the side door both times, because listing the bad cases you have already seen is simply the obvious way to write a check. The enumeration is the bug, and it does not announce itself as one.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;c36&lt;/code&gt; got tightened later the same day for a related reason. The original rule accepted "a width constraint OR an &lt;code&gt;elide&lt;/code&gt;", and &lt;code&gt;elide&lt;/code&gt; without a &lt;code&gt;width&lt;/code&gt; is a no-op in QML, so half the accepted forms did nothing. It now requires a width constraint AND an overflow rule. Blast radius was measured on a scratch copy before applying it: those same four entries and the template still pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  A detector living inside the tree it scans
&lt;/h2&gt;

&lt;p&gt;Candidate repos vendor the lane. That puts the detectors physically inside the tree they are scanning, and a detector's source necessarily contains examples of the pattern it hunts.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;c34&lt;/code&gt; flagged its own shell-injection example and failed a CI run on a repo whose plugin code was clean.&lt;/p&gt;

&lt;p&gt;The fix is one exclusion in the shared &lt;code&gt;gate_tree_files&lt;/code&gt; helper (gates no longer scan &lt;code&gt;scripts/gates/**&lt;/code&gt;) rather than a patch inside each gate. One exclusion in the shared enumerator covers every gate added later. Patching them one at a time would have covered exactly the gates that existed that afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  The chokepoint that was not one
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;precheck-hook.sh&lt;/code&gt; intercepts &lt;code&gt;gh&lt;/code&gt; commands before they run. It covered four of them: issue comment, pr create, pr ready, pr merge.&lt;/p&gt;

&lt;p&gt;A marketplace submission is filed with &lt;code&gt;gh issue create&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the one command that actually submits a plugin to the marketplace bypassed the chokepoint entirely, and running the gate lane before submitting was a choice rather than a gate. That was the last "if someone remembers" step in the chain.&lt;/p&gt;

&lt;p&gt;The new guard requires &lt;strong&gt;both&lt;/strong&gt; a lane run and &lt;code&gt;c37&lt;/code&gt;'s rig receipt, because per the whole first half of this post, a lane run on its own is not evidence. It resolves the plugin tree from the issue body's &lt;code&gt;### Repository URL&lt;/code&gt; line, maps the repo name to &lt;code&gt;~/000-projects/&amp;lt;name&amp;gt;&lt;/code&gt;, runs that repo's vendored &lt;code&gt;run-plugin-gates.sh&lt;/code&gt;, then runs &lt;code&gt;c37&lt;/code&gt; from the canonical lane, because &lt;code&gt;c37&lt;/code&gt; is not vendored into any plugin repo.&lt;/p&gt;

&lt;p&gt;Posture matches the hook's existing unmatched-candidate path: fail OPEN while the tree is unidentified (warn and allow), fail CLOSED once it is identified. You cannot block on a check you were unable to aim.&lt;/p&gt;

&lt;p&gt;Extending this hook beat adding a second one. Two chokepoints on a single action drift apart, and this hook already owns the log and the kill switch.&lt;/p&gt;

&lt;p&gt;Two incidental bugs surfaced while testing it, both the same root cause and both worth knowing. A bracket expression written inline in a &lt;code&gt;[[ =~ ]]&lt;/code&gt; test takes an escaped octal like &lt;code&gt;\047&lt;/code&gt; literally instead of as a quote character, which silently excluded digits from body-file paths. &lt;code&gt;grep -oE&lt;/code&gt; has the identical problem with the identical expression. Same shape of bug, two tools, one afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  The vendored copy that was intact but stale
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;run-plugin-gates.sh&lt;/code&gt; runs a manifest check that proves a vendored copy is intact. It cannot prove canonical has not moved on. Which is exactly the gap that let a stale &lt;code&gt;c36&lt;/code&gt; sit here reporting green.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scripts/check-lane-freshness.sh&lt;/code&gt; plus a CI step now fetches canonical and compares hashes. It is wired &lt;strong&gt;advisory&lt;/strong&gt; (&lt;code&gt;continue-on-error&lt;/code&gt;), not blocking, because it needs network and a GitHub blip must not fail an unrelated PR.&lt;/p&gt;

&lt;p&gt;That is one more case where the stricter option is the worse one. Blocking would be stricter and would be worse: a check that cries wolf is one people learn to ignore, which is how the original drift survived in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the lane sits now
&lt;/h2&gt;

&lt;p&gt;Canonical lane full suite: &lt;strong&gt;71 passed, 0 failed.&lt;/strong&gt; PR #73 merged, five files, +356/-3. Lane green on four of six plugin repos at the time of the &lt;code&gt;c38&lt;/code&gt; commit; the two findings in crew-chief and pit-wall were pre-existing and reported separately.&lt;/p&gt;

&lt;p&gt;What actually changed is narrower than the commit count suggests. The lane can now tell the difference between "checked and fine" and "could not check," it can prove the rig ran against the exact bytes being submitted, its two filter-shaped detectors ask structural questions instead of matching known-bad spellings, and the submission command is finally inside the chokepoint. Claude Opus 5 carried most of the implementation across the day.&lt;/p&gt;

&lt;p&gt;Also shipped: &lt;code&gt;claude-code-plugins&lt;/code&gt; dual-published a blog post to tonsofskills.com/blog and merged PR #1295 adding two internal Omarchy plugin agents; &lt;code&gt;omarchy-mlb-booth-entry&lt;/code&gt; and &lt;code&gt;omarchy-docket-entry&lt;/code&gt; moved API credentials to stdin for &lt;code&gt;jq&lt;/code&gt; and &lt;code&gt;curl&lt;/code&gt; instead of argv; &lt;code&gt;omarchy-x-files-entry&lt;/code&gt; corrected a stale test count and some deleted-CLI references in docs; &lt;code&gt;comehomealabama&lt;/code&gt; and &lt;code&gt;intent-solutions-landing&lt;/code&gt; each took one content commit.&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-gate-that-could-not-fail/"&gt;The Gate That Could Not Fail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/we-told-the-auditors-to-refute-us/"&gt;We Told the Auditors to Refute Us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/the-refusal-nobody-heard/" rel="noopener noreferrer"&gt;The Refusal Nobody Heard&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cicd</category>
      <category>security</category>
      <category>testing</category>
      <category>devops</category>
    </item>
    <item>
      <title>A Closed Epic Is a Claim, Not a Fact</title>
      <dc:creator>Jeremy Longshore</dc:creator>
      <pubDate>Sat, 22 Aug 2026 11:30:25 +0000</pubDate>
      <link>https://dev.to/jeremy_longshore/a-closed-epic-is-a-claim-not-a-fact-59f7</link>
      <guid>https://dev.to/jeremy_longshore/a-closed-epic-is-a-claim-not-a-fact-59f7</guid>
      <description>&lt;p&gt;Closing a bead is a claim. Merging a PR is a claim. Writing an after-action record that says&lt;br&gt;
the gate is wired and green is a claim about a claim. None of those are facts. The only way to&lt;br&gt;
turn a claim into a fact is to execute it again, later, with someone whose job is to prove it&lt;br&gt;
false.&lt;/p&gt;

&lt;p&gt;That is what happened to four epics I had already closed. Blueprint 727's Epics 1 through 4 went&lt;br&gt;
out across 2026-08-18 and 2026-08-19: 48 merged pull requests in the #1242 to #1289 span, four&lt;br&gt;
after-action records, four closed parent beads. Signed off. Done. The next morning the directive&lt;br&gt;
was one sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;go over the so-called completed epics and beads in detail and make sure the work is really done&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"So-called completed" is the whole brief. Not "confirm the work." Not "write a summary." The word&lt;br&gt;
is an accusation, and the right response to an accusation is an adversary, not a reviewer.&lt;/p&gt;

&lt;p&gt;So the audit was built as three parallel &lt;code&gt;Explore&lt;/code&gt; agents, one per epic cluster, each instructed&lt;br&gt;
to &lt;strong&gt;refute rather than confirm&lt;/strong&gt;. Execute every claimed gate. Read every bead back from the&lt;br&gt;
store. Check main's live CI, not the record's description of it. All of it pinned to a single&lt;br&gt;
verified state: main at &lt;code&gt;a9fb4a9f9&lt;/code&gt;, working tree clean, so nothing verified was uncommitted local&lt;br&gt;
work sitting on my box.&lt;/p&gt;

&lt;p&gt;They came back with 34 of 37 claims confirmed by execution and three actionable defect classes,&lt;br&gt;
which is the unit the record disposes on: A, B, and C. B covers both of the Epic 1 residual&lt;br&gt;
items, C covers the record drifts. This post is about the three, and then about what I did with&lt;br&gt;
them, because finding a defect is the cheap half. The&lt;br&gt;
expensive half is making that exact defect structurally unable to happen again: a found defect&lt;br&gt;
becomes a gate, and the gate becomes a template.&lt;/p&gt;
&lt;h2&gt;
  
  
  How do you audit an epic that is already closed?
&lt;/h2&gt;

&lt;p&gt;Brief the auditors to refute rather than confirm, and pin them to one verified state. Three&lt;br&gt;
parallel agents, one per epic cluster, re-executed every claimed gate against main at &lt;code&gt;a9fb4a9f9&lt;/code&gt;&lt;br&gt;
instead of reading the closure records. They confirmed 34 of 37 claims by execution and surfaced&lt;br&gt;
three actionable defect classes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Refute, not confirm, is a different instruction than it sounds
&lt;/h2&gt;

&lt;p&gt;The distinction matters more than it reads. An agent told to "verify the epic is complete" reads&lt;br&gt;
the closure record, sees the gate name, sees main is green, and confirms. Every one of those steps&lt;br&gt;
is a document lookup. The claim and the evidence for the claim come from the same author.&lt;/p&gt;

&lt;p&gt;An agent told to refute has to go somewhere else for its evidence. It runs &lt;code&gt;npm run&lt;br&gt;
validate:model-id-classifier&lt;/code&gt; itself and reads the exit code. It pulls the branch protection&lt;br&gt;
contexts off the API instead of off the README. It asks when a secret was created and compares that&lt;br&gt;
timestamp to when the record asserted the secret was working. That last one is what caught&lt;br&gt;
Finding B, and no amount of reading would ever have surfaced it.&lt;/p&gt;

&lt;p&gt;The three auditors got the same shape of brief and different scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Epic 4, 14 beads. Verdict 14/14 confirmed, 0 refuted. Every gate executed with exit 0 during the
audit: the gitleaks shape gate with its 10 documented exceptions and no blanket allows, the
safety ratchet with exact pinned counts, the MCP destructive-policy registry at 14/14 plugins
with both refusal tests passing, the denylist gate across the 52 first-party skills that carry a
denylist (not the full skill corpus, which is far larger and shows up again in Finding C), the dolt guard
suite 6/6, the python suite 55/55. The strongest single proof was that the push leg ran green on
a real push to main, verified at step-level conclusions rather than at the badge.&lt;/li&gt;
&lt;li&gt;Epics 1 and 2. Closure bodies confirmed. All 12 doc-governance and supply-chain gates exist, are
wired through &lt;code&gt;ci-required&lt;/code&gt;, and exited 0 live. Two defects in the Epic 1 residual.&lt;/li&gt;
&lt;li&gt;Epic 3, 10 claims. 9 confirmed, 1 refuted, and the refuted one was red at HEAD while CI had been
reporting green for two days.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I want the 34 in the record as loudly as the 3. A post where an audit only finds damage is a post&lt;br&gt;
that misrepresents the audit. The epics' bodies were real. The gates existed and had teeth. What&lt;br&gt;
the refutation directive bought was not a demolition, it was three specific things that the&lt;br&gt;
confirm-shaped version of this exercise would have walked straight past.&lt;/p&gt;
&lt;h2&gt;
  
  
  Finding A: a gate whose only drift detector reads untracked state
&lt;/h2&gt;

&lt;p&gt;Epic 3 shipped a model-id classifier gate. It keeps a committed exclusion list of bead handles that&lt;br&gt;
look like model identifiers but are not, so that a real unpinned model handle in the corpus goes&lt;br&gt;
red. The list at &lt;code&gt;schemas/canonical/v0/model-id-exclusions.json&lt;/code&gt; held 393 handles. The live census&lt;br&gt;
counted 394.&lt;/p&gt;

&lt;p&gt;The missing one was &lt;code&gt;claude-or1m&lt;/code&gt;. That is Epic 4's own epic bead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tap"&gt;&lt;code&gt;&lt;span class="gr"&gt;not ok&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; - the exclusion list stays regenerable from the live beads export
  error: 'live handle claude-or1m missing from the committed exclusion list'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Epic 4 broke Epic 3's gate simply by existing, and nothing caught it for two reasons that stacked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One: the only assertion that could detect drift self-skips in CI.&lt;/strong&gt; The census test reads&lt;br&gt;
&lt;code&gt;.beads/issues.jsonl&lt;/code&gt;, which is an untracked export. It is present on my box and absent on every CI&lt;br&gt;
checkout, so the test skipped, and a skip is not a failure. Main's green CI carried no signal at all&lt;br&gt;
for that gate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two: the gate script never ran.&lt;/strong&gt; &lt;code&gt;validate:model-id-classifier&lt;/code&gt; executed only the test file. It&lt;br&gt;
never invoked &lt;code&gt;scripts/classify-model-ids.mjs&lt;/code&gt;, which was a reporting tool that always exited 0.&lt;br&gt;
Two independent design choices, each defensible alone, that together produce a gate with no&lt;br&gt;
reachable path to red in the environment where it is supposed to run. That defect class is not new&lt;br&gt;
here. I wrote it up two days earlier in &lt;a href="https://dev.to/blog/the-gate-that-could-not-fail/"&gt;The Gate That Could Not Fail&lt;/a&gt;,&lt;br&gt;
which is the uncomfortable part: I had just published the shape of this bug and still shipped an&lt;br&gt;
instance of it. Knowing a failure mode is not a control. What follows is the control.&lt;/p&gt;

&lt;p&gt;This drift class recurs with &lt;strong&gt;every new epic bead&lt;/strong&gt; we create. So the fix targeted the class, not&lt;br&gt;
the instance. Pinning &lt;code&gt;claude-or1m&lt;/code&gt; would have taken thirty seconds and bought nothing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jeremylongshore/claude-code-plugins-plus-skills/pull/1291" rel="noopener noreferrer"&gt;PR #1291&lt;/a&gt; added a census that runs from tracked artifacts alone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// walk the tracked tree only, so this leg is identical on a CI checkout&lt;/span&gt;
&lt;span class="c1"&gt;// and on a dev box. no untracked export, no skip path.&lt;/span&gt;
&lt;span class="c1"&gt;// pinned is injectable, which is what makes the detection path testable.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unpinnedTrackedHandles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pinned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loadExclusions&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;protected_handles&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;missing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                       &lt;span class="c1"&gt;// prefix -&amp;gt; first "file:line" sighting&lt;/span&gt;
  &lt;span class="k"&gt;for &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;file&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;trackedTextFiles&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;         &lt;span class="c1"&gt;// git ls-files, text extensions only&lt;/span&gt;
    &lt;span class="nf"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="sr"&gt;/bead/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;             &lt;span class="c1"&gt;// bead-context lines only&lt;/span&gt;
      &lt;span class="k"&gt;for &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;token&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BEAD_ID_SCAN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;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;BEAD_ID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;MODEL_FAMILY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// claude-opus-5 etc&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;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                      &lt;span class="c1"&gt;// claude-7yz... in prose&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NOT_A_HANDLE&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;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;pinned&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;prefix&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// claude-code stoplist&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;missing&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;prefix&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;missing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;missing&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;The reason this works is a property of our own process rather than of the code: a new epic bead&lt;br&gt;
lands in a tracked after-action record almost immediately, as a line reading&lt;br&gt;
&lt;code&gt;Bead: `claude-&amp;lt;hash&amp;gt;.1`&lt;/code&gt;. The handle is in the tracked tree before it is anywhere else CI can&lt;br&gt;
see. So the census now has a real signal from a real file, and the drift goes red where it matters.&lt;/p&gt;

&lt;p&gt;The gate also grew the two-step shape its sibling gates already used:&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;"validate:model-id-classifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node --test scripts/classify-model-ids.test.mjs &amp;amp;&amp;amp; node scripts/classify-model-ids.mjs --check"&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;The reporting tool became a gate by gaining a &lt;code&gt;--check&lt;/code&gt; mode that exits non-zero and names the&lt;br&gt;
offender with a file and line:&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;node scripts/classify-model-ids.mjs --check&lt;/code&gt; against the pre-fix list exits 1 and prints a&lt;br&gt;
single &lt;code&gt;model-id-check: FAIL&lt;/code&gt; line to stderr. Paraphrased, because the real string carries&lt;br&gt;
punctuation this blog does not print, it says: handle &lt;code&gt;claude-or1m&lt;/code&gt;, referenced at&lt;br&gt;
&lt;code&gt;000-docs/791-AA-AACR-epic-4-safety-register.md:8&lt;/code&gt;, is missing from&lt;br&gt;
&lt;code&gt;schemas/canonical/v0/model-id-exclusions.json&lt;/code&gt;, regenerate from &lt;code&gt;.beads/issues.jsonl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The failure names the handle, the file, the line, the list it belongs in, and how to regenerate it.&lt;br&gt;
A gate that goes red without telling you which of 394 handles moved is a gate people learn to skip.&lt;/p&gt;

&lt;p&gt;Two design decisions inside that PR worth naming, because both had a plausible alternative that&lt;br&gt;
lost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;List invariants assert always, not conditionally.&lt;/strong&gt; Sorted and unique are properties of the&lt;br&gt;
committed file itself. They have no dependency on any export, so there is no defensible reason for&lt;br&gt;
them to sit behind a skip. Anything that can assert from the tracked tree should assert&lt;br&gt;
unconditionally. That is the general form of Finding A.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;KNOWN_HARNESSES&lt;/code&gt; moved to &lt;code&gt;scripts/lib/harness-lexicon.mjs&lt;/code&gt;.&lt;/strong&gt; Both the portability gate and the&lt;br&gt;
denylist gate needed the same lexicon. The cheap option was to have one gate import the other. I&lt;br&gt;
chose lib extraction instead, because two gate scripts should not share lifecycles: the moment one&lt;br&gt;
imports the other, changing gate A's internals can turn gate B red for reasons that have nothing to&lt;br&gt;
do with what gate B checks. A gate should depend on data, not on another gate.&lt;/p&gt;

&lt;p&gt;A Greptile review on that PR asked a good question: does the scan actually surface real handles, or&lt;br&gt;
does it only prove that a correct pin set passes? Fair, and the answer required a new test that&lt;br&gt;
runs the detection path under an &lt;strong&gt;empty&lt;/strong&gt; pin set and asserts real handles come back. A gate that&lt;br&gt;
has only ever been observed passing is a gate you are trusting on faith.&lt;/p&gt;

&lt;p&gt;The best moment in the whole PR: the tripwire caught its own author. The doc comment I wrote to&lt;br&gt;
explain the scan used &lt;code&gt;claude-xxxx.1&lt;/code&gt; as an illustrative example, and the scan flagged it. I had to&lt;br&gt;
reword my own documentation to get my own gate to pass. That is not embarrassing, that is the gate&lt;br&gt;
working on the first live input it ever saw.&lt;/p&gt;

&lt;p&gt;Evidence, run against the pre-fix list: &lt;code&gt;--check&lt;/code&gt; exits 1 naming &lt;code&gt;claude-or1m&lt;/code&gt; at&lt;br&gt;
&lt;code&gt;000-docs/791-AA-AACR-epic-4-safety-register.md:8&lt;/code&gt;. Simulated CI checkout with the JSONL removed,&lt;br&gt;
as recorded in #1291's verification at merge time: 5 pass, 1 skip, &lt;code&gt;--check&lt;/code&gt; PASS. The file has&lt;br&gt;
grown a case since.&lt;/p&gt;

&lt;p&gt;That one remaining skip is the old live-export parity leg, and it still skips without the untracked&lt;br&gt;
JSONL. I left it that way deliberately. The difference is that it is no longer the only detector:&lt;br&gt;
the tracked-tree census and the &lt;code&gt;--check&lt;/code&gt; step both run unconditionally on the same checkout, so&lt;br&gt;
the skip now sits behind a leg that cannot skip. A skip is acceptable when something else is&lt;br&gt;
carrying the signal. It was never acceptable as the whole gate.&lt;/p&gt;
&lt;h2&gt;
  
  
  Finding B: an OR on a credential is a quieter shade of green
&lt;/h2&gt;

&lt;p&gt;The Epic 1 residual shipped a daily npm stats refresh workflow. It had this in it:&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;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.BOT_PR_TOKEN || secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That reads like resilience. It is the opposite. &lt;code&gt;BOT_PR_TOKEN&lt;/code&gt; is a fine-grained PAT whose pull&lt;br&gt;
requests re-trigger required status checks. &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; cannot do that: PRs opened by&lt;br&gt;
&lt;code&gt;github-actions[bot]&lt;/code&gt; do not fire required status checks. That is documented behavior rather than house&lt;br&gt;
lore: GitHub's own &lt;a href="https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow" rel="noopener noreferrer"&gt;workflow triggering docs&lt;/a&gt;&lt;br&gt;
state that events raised with the default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; do not create a new workflow run. So the&lt;br&gt;
fallback path is the zero-checks path.&lt;/p&gt;

&lt;p&gt;Token expiry on the first branch does not fail. It silently relocates the pipeline onto a path&lt;br&gt;
where nothing is verified, and every run after that is green because nothing is looking. That&lt;br&gt;
fallback is precisely why the pre-fix scheduled runs had looked healthy.&lt;/p&gt;

&lt;p&gt;The auditor then asked the question I would not have thought to ask. When was the secret actually&lt;br&gt;
created? Answer: 87 seconds before the first green run, and that run was a manual dispatch. The&lt;br&gt;
Epic 1 closure record asserted the scheduled trigger was working under the real token at a moment&lt;br&gt;
when the real token had existed for under two minutes and had never been exercised by the schedule&lt;br&gt;
at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jeremylongshore/claude-code-plugins-plus-skills/pull/1292" rel="noopener noreferrer"&gt;PR #1292&lt;/a&gt;:&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="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Require BOT_PR_TOKEN (no silent fallback)&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;BOT_PR_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.BOT_PR_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;if [ -z "$BOT_PR_TOKEN" ]; then&lt;/span&gt;
      &lt;span class="s"&gt;echo "::error::BOT_PR_TOKEN is absent or empty (expired, revoked, or never set). [...]"&lt;/span&gt;
      &lt;span class="s"&gt;exit 1&lt;/span&gt;
    &lt;span class="s"&gt;fi&lt;/span&gt;
    &lt;span class="s"&gt;echo "BOT_PR_TOKEN present."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The secret binds through &lt;code&gt;env:&lt;/code&gt; and the test reads the shell variable, rather than expanding the&lt;br&gt;
secret expression directly into the script body. That is the small habit worth copying: a secret&lt;br&gt;
interpolated into &lt;code&gt;run:&lt;/code&gt; text becomes part of the script, and scripts get echoed in more places&lt;br&gt;
than people expect.&lt;/p&gt;

&lt;p&gt;Both token sites lost the fallback. The network fetch steps gained &lt;code&gt;timeout-minutes&lt;/code&gt;. And the proof&lt;br&gt;
that was missing got obtained during remediation rather than asserted: the 2026-08-20 00:27 UTC&lt;br&gt;
&lt;strong&gt;scheduled&lt;/strong&gt; run &lt;code&gt;32317409056&lt;/code&gt; completed success in 30.4 minutes and opened &lt;a href="https://github.com/jeremylongshore/claude-code-plugins-plus-skills/pull/1290" rel="noopener noreferrer"&gt;PR #1290&lt;/a&gt; authored by&lt;br&gt;
&lt;code&gt;jeremylongshore&lt;/code&gt; via the fine-grained PAT, with &lt;code&gt;ci-required&lt;/code&gt; reporting on it. That run fired at&lt;br&gt;
00:27 UTC on the pre-#1292 workflow, more than two hours before #1292 merged at 02:43 UTC, so its&lt;br&gt;
30.4 minutes ran without the timeout that section adds. Hold onto that number. That is one&lt;br&gt;
completed run on the real trigger. A manual dispatch is evidence of the code path. It is not&lt;br&gt;
evidence of the schedule.&lt;/p&gt;
&lt;h2&gt;
  
  
  The reversal: my corrective timeout broke a healthy pipeline
&lt;/h2&gt;

&lt;p&gt;Proving Finding B produced two corrections to the audit's own findings, which is the part of this&lt;br&gt;
day I would keep if I could only keep one.&lt;/p&gt;

&lt;p&gt;The original audit finding described a "~29 minute hang." That was a mischaracterization, and I&lt;br&gt;
wrote the fix against the mischaracterization.&lt;/p&gt;

&lt;p&gt;A healthy fetch legitimately takes 25 to 35 minutes. There are 423 candidate packages at four&lt;br&gt;
requests each, roughly 1,700 requests, run strictly serially (&lt;code&gt;concurrency = 1&lt;/code&gt;) with a 250ms&lt;br&gt;
inter-request sleep. That sleep is a &lt;strong&gt;ceiling&lt;/strong&gt; of 4 requests per second, not the achieved rate:&lt;br&gt;
the throttle alone accounts for about 7 minutes, and network round-trip time on the remaining&lt;br&gt;
1,700 calls is what fills the other 20-odd. Measured, the pipeline lands near 1 request per second&lt;br&gt;
end to end, and the last six green runs came in between 29 and 35 minutes. The run the auditor saw&lt;br&gt;
as stuck had actually been killed by the next dispatch's concurrency group, mid-normal-run.&lt;/p&gt;

&lt;p&gt;That distinction between the configured ceiling and the measured throughput is the whole reason the&lt;br&gt;
first fix was wrong. I read "4 req/s" off the code comment, did the division, got 7 minutes, and&lt;br&gt;
concluded a 10-minute timeout was generous.&lt;/p&gt;

&lt;p&gt;So the 10-minute &lt;code&gt;timeout-minutes&lt;/code&gt; merged in #1292 was calibrated against the incident instead of&lt;br&gt;
against measured healthy runtime, and it did exactly what a miscalibrated timeout does: it failed a&lt;br&gt;
healthy dispatch. &lt;a href="https://github.com/jeremylongshore/claude-code-plugins-plus-skills/pull/1293" rel="noopener noreferrer"&gt;PR #1293&lt;/a&gt; raised &lt;code&gt;timeout-minutes&lt;/code&gt; to 45, which still fails fast against the 6 hour job default&lt;br&gt;
while leaving the real distribution room to breathe.&lt;/p&gt;

&lt;p&gt;Same PR, second correction, found while reading the fetch code to figure out why it was serial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// the parameter is an options object. a positional 4 was accepted&lt;/span&gt;
&lt;span class="c1"&gt;// and silently discarded, so concurrency was always 1.&lt;/span&gt;
&lt;span class="c1"&gt;// signature: collectStats(pkgNames, { concurrency = 1, throttleMs = 250 } = {})&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;collectStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// before: the positional 4 was silently discarded&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;collectStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// after: the defaults are the real behavior, so say nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The behavior did not change. The honesty did. Code that claims a concurrency of 4 and runs 1 will&lt;br&gt;
eventually cause someone to reason about capacity from a number that was never true.&lt;/p&gt;

&lt;p&gt;And a third thing surfaced in the same window: the pipeline could open unmergeable pull requests&lt;br&gt;
by construction. The workflow hardcoded its PR title as a decorated string that predates our&lt;br&gt;
conventional-commit PR-title gate, so &lt;code&gt;commit-scope-check&lt;/code&gt; fails every PR the automation opens.&lt;br&gt;
This was observed live on #1290. Title generation now emits&lt;br&gt;
&lt;code&gt;chore(marketplace-site): refresh daily npm download stats&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Three findings on the corrective work for one finding on the original work. Fixing a defect is&lt;br&gt;
itself a change, and changes need the same skepticism the audit applied. Nobody audits the audit's&lt;br&gt;
remediation, which is exactly why it is a good place for defects to hide.&lt;/p&gt;
&lt;h2&gt;
  
  
  Finding C: dated records drift by design
&lt;/h2&gt;

&lt;p&gt;The third class is record drift, and unlike A and B it is not owned by one epic. It is the&lt;br&gt;
disposition bucket the audit record uses for everything that is wrong in a &lt;em&gt;record&lt;/em&gt; rather than in&lt;br&gt;
a &lt;em&gt;gate&lt;/em&gt;: two numbers in Epic 2's closure record, a counting basis in an earlier one, and the two&lt;br&gt;
observations Epic 4's auditor filed as designed-behavior rather than defects. One class, several&lt;br&gt;
instances, which is why the headline count is three classes and not three sentences. The&lt;br&gt;
disposition is the part worth transferring.&lt;/p&gt;

&lt;p&gt;After-action record 777 states 2 effective authority claimants and 12 canonical-table links. Live&lt;br&gt;
is 3 and 13, because Epic 4's register landed after 777 was written. The pinned test moved with&lt;br&gt;
reality. The dated record did not.&lt;/p&gt;

&lt;p&gt;Record 786's "2,700 first-party SKILL.md files" is a file-edit count across duplicated trees:&lt;br&gt;
roughly 1,456 are plugin skills and the rest are curated-mirror copies of the same skills. The&lt;br&gt;
earlier change from 1,454 to 2,700 was a counting-basis change (per-skill to per-file-copy), not a&lt;br&gt;
new round of discoveries. The withdrawal it describes still holds. The number needs a basis note it&lt;br&gt;
never had.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No source edits to dated records.&lt;/strong&gt; The correction mechanism is an addendum, which is what record&lt;br&gt;
802 is. A dated record is a statement of what was believed true on a date. Silently editing it&lt;br&gt;
destroys the only thing it was for. Pinned tests are the surface that must track reality; records&lt;br&gt;
are the surface that must not.&lt;/p&gt;

&lt;p&gt;No epic reopens either. The warden standard we run here: deliverables shipped and verified,&lt;br&gt;
corrections are records, not rework. Reopening four epics because three findings landed would have&lt;br&gt;
turned an audit leg that ran in well under two hours into a week of rework, and taught the team&lt;br&gt;
that closing anything is provisional.&lt;/p&gt;
&lt;h2&gt;
  
  
  The same principle, applied forward
&lt;/h2&gt;

&lt;p&gt;The audit half of this day was backward-looking. The other half was the same idea pointed at work&lt;br&gt;
that had not shipped yet, and it produced a cleaner demonstration of the ratchet: defect to gate to&lt;br&gt;
template.&lt;/p&gt;

&lt;p&gt;Six Omarchy bar-widget repos were built or hardened the same day. Counting only that day's commits:&lt;br&gt;
&lt;code&gt;omarchy-mlb-booth-entry&lt;/code&gt; went from initial commit to v1.0.0 in 11, &lt;code&gt;omarchy-pit-wall-entry&lt;/code&gt; took 9&lt;br&gt;
(of 13 in the repo's life), &lt;code&gt;omarchy-listening-post-entry&lt;/code&gt; 7, &lt;code&gt;omarchy-x-files-entry&lt;/code&gt; 6,&lt;br&gt;
&lt;code&gt;omarchy-crew-chief-entry&lt;/code&gt; 3. Four of those commits are review-panel remediation by name, including&lt;br&gt;
&lt;code&gt;fix: apply the four-reviewer panel findings before submission&lt;/code&gt; on MLB Booth and&lt;br&gt;
&lt;code&gt;fix: address four-reviewer panel findings (2 BLOCK security, 2 BLOCK correctness, taste, idiom)&lt;/code&gt;&lt;br&gt;
on Listening Post.&lt;/p&gt;

&lt;p&gt;The interesting part is not that a review panel found things. It is that the findings became&lt;br&gt;
permanent gates in &lt;code&gt;contributing-clanker&lt;/code&gt; the same day, which means the next person to write a&lt;br&gt;
widget cannot ship those defects at all.&lt;/p&gt;
&lt;h3&gt;
  
  
  c34: the &lt;code&gt;--exec&lt;/code&gt; command injection nobody would have guessed
&lt;/h3&gt;

&lt;p&gt;A four-agent security review of the Listening Post and X Files entries caught a remote code&lt;br&gt;
execution class that the existing gate c31 did not cover.&lt;/p&gt;

&lt;p&gt;Omarchy dispatches a notification click action by running the &lt;code&gt;--exec&lt;/code&gt; value through a login shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// excerpt from the Omarchy shell's Commons/Util.qml singleton, call shape only
execDetached(command)  -&amp;gt;  Quickshell.execDetached(["bash", "-lc", command])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this, in a poller that builds a notification from a feed item (the real line is&lt;br&gt;
&lt;code&gt;bin/listening-post-poll:154&lt;/code&gt; at &lt;code&gt;b8316bb&lt;/code&gt;, where the array was still named &lt;code&gt;args&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--exec&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="s2"&gt;xdg-open &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is command injection the instant a feed-derived or reply-derived URL carries a &lt;code&gt;;&lt;/code&gt;, a &lt;code&gt;$(...)&lt;/code&gt;, a&lt;br&gt;
backtick, a &lt;code&gt;|&lt;/code&gt;, or &lt;code&gt;${IFS}&lt;/code&gt;. The URL is attacker-influenced by definition; it came off a network&lt;br&gt;
feed.&lt;/p&gt;

&lt;p&gt;The hardened form single-quotes every interpolated segment:&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="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--exec&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="s2"&gt;xdg-open '&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gate c34 blocks the absence of that wrap: every double-quoted string literal immediately followed&lt;br&gt;
by a &lt;code&gt;+&lt;/code&gt; must end in a single quote, and every template-literal &lt;code&gt;${...}&lt;/code&gt; reaching such a call must&lt;br&gt;
be single-quote-wrapped.&lt;/p&gt;

&lt;p&gt;The design decision that mattered was file selection. &lt;strong&gt;I chose a shebang scan over an&lt;br&gt;
extension-only scan&lt;/strong&gt;, and the first cut proved why. Filtering by extension silently skipped the&lt;br&gt;
actual vulnerable file, because the real bug lived in &lt;code&gt;bin/&amp;lt;name&amp;gt;-poll&lt;/code&gt;, an extensionless node&lt;br&gt;
script. The gate false-passed. The historical regression caught exactly that, which is the whole&lt;br&gt;
argument for testing a gate against the real pre-fix commit rather than against synthetic cases&lt;br&gt;
only.&lt;/p&gt;

&lt;p&gt;Evidence: 7 synthetic unit cases green, c34 BLOCKs the real pre-fix commit &lt;code&gt;b8316bb&lt;/code&gt; that shipped&lt;br&gt;
the unquoted concat, c34 PASSes the hardened tree, harness 40/40, lane at 37 gates and 0 BLOCK.&lt;/p&gt;
&lt;h3&gt;
  
  
  c35: the runtime that exists on exactly one machine
&lt;/h3&gt;

&lt;p&gt;This class shipped &lt;strong&gt;twice&lt;/strong&gt; and would have reached real users.&lt;/p&gt;

&lt;p&gt;Two entries were built with a Node.js poller CLI spawned by the QML shell. Both worked on the dev&lt;br&gt;
rig. Both passed every other gate. The dev rig carries a system node at &lt;code&gt;/usr/bin/node&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A stock Omarchy install does not. Omarchy installs Node through mise, and mise's shims are exported&lt;br&gt;
only to an interactive shell, never onto the PATH of the graphical session that launches Quickshell. Verified&lt;br&gt;
against a real Omarchy tree: no PATH export in &lt;code&gt;uwsm/env&lt;/code&gt;, no profile hook, no &lt;code&gt;environment.d&lt;/code&gt;&lt;br&gt;
entry, and &lt;code&gt;omarchy-launch-shell&lt;/code&gt; execs &lt;code&gt;quickshell&lt;/code&gt; directly with no login shell and no &lt;code&gt;mise&lt;br&gt;
activate&lt;/code&gt;. Node is part of the optional dev environment, so a base user may have none at all.&lt;/p&gt;

&lt;p&gt;The user-visible result is the worst shape a defect can take. The plugin installs cleanly. It&lt;br&gt;
enables cleanly. It then silently never populates. Nothing errors, nothing logs, the widget is&lt;br&gt;
just always empty.&lt;/p&gt;

&lt;p&gt;The marketplace-validated pattern from MLB Booth and Pit Wall has no extra runtime at all: fetch&lt;br&gt;
with &lt;code&gt;curl&lt;/code&gt; from a QML &lt;code&gt;Process&lt;/code&gt;, parse in a plain-JS &lt;code&gt;Model.js&lt;/code&gt; on Quickshell's own engine,&lt;br&gt;
persist with &lt;code&gt;FileView { atomicWrites: true }&lt;/code&gt;. Every Omarchy box has a shell, &lt;code&gt;curl&lt;/code&gt;, and &lt;code&gt;jq&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Gate c35 blocks two shapes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BLOCK shape 1: a shipped executable whose shebang names an interpreter
               Omarchy does not guarantee
               #!/usr/bin/env node | deno | bun | python* | ruby | perl

BLOCK shape 2: a .qml spawning one as the first element of a Process
               command array (comments stripped before matching)
               command: ["node", root + "/bin/x-files-poll"]

PASS:          bash, sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scoping choices are where a gate earns or loses its keep. c35 applies only to trees with a&lt;br&gt;
&lt;code&gt;manifest.json&lt;/code&gt; declaring &lt;code&gt;entryPoints&lt;/code&gt;, and SKIPs otherwise, so it does not fire on repos that are&lt;br&gt;
not widgets. &lt;code&gt;tests/&lt;/code&gt;, &lt;code&gt;test/&lt;/code&gt;, &lt;code&gt;docs/&lt;/code&gt;, &lt;code&gt;*.md&lt;/code&gt; and &lt;code&gt;node_modules/&lt;/code&gt; are exempt, because a node unit&lt;br&gt;
suite never runs on the user's&lt;br&gt;
machine and blocking it would push authors to delete their tests to satisfy a gate.&lt;/p&gt;

&lt;p&gt;Evidence: 8 unit cases green, c35 BLOCKs both real pre-fix trees&lt;br&gt;
(&lt;code&gt;omarchy-listening-post-entry@fad97bf&lt;/code&gt;, &lt;code&gt;omarchy-x-files-entry@2829b83&lt;/code&gt;) and PASSes their node-free&lt;br&gt;
current versions, harness 52/52 (c35's 8 cases plus the regressions and fixtures that landed&lt;br&gt;
alongside them, which is why it is not simply 40 plus 8), &lt;code&gt;[C35] PASS&lt;/code&gt; on all five entries, lane at&lt;br&gt;
38 gates and 0 BLOCK.&lt;br&gt;
Both entries were then re-verified with &lt;code&gt;node&lt;/code&gt; shadowed by a stub that exits 127, which is the only&lt;br&gt;
honest way to simulate a machine that does not have it.&lt;/p&gt;

&lt;p&gt;Those two entries carry commits reading &lt;code&gt;fix!: remove the node runtime dependency, poll from QML&lt;br&gt;
instead&lt;/code&gt;. That is the same defect c35 now blocks. The fix and the gate landed the same day, and the&lt;br&gt;
ordering is the point: a fix without a gate is a fix for one repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  The last click: the template
&lt;/h3&gt;

&lt;p&gt;The final piece was &lt;code&gt;omarchy-widget-template&lt;/code&gt;, a skeleton carrying the architecture and security&lt;br&gt;
patterns that two shipped entries (Pit Wall and Crew Chief) earned the hard way. A new widget now&lt;br&gt;
starts from a state that already passes the pre-submit gates.&lt;/p&gt;

&lt;p&gt;That is the full ratchet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A defect is found in one repo.&lt;/li&gt;
&lt;li&gt;It becomes a gate, tested against the real pre-fix commit, so it cannot recur in any repo.&lt;/li&gt;
&lt;li&gt;It becomes a template default, so new work starts past it and the gate never has to fire.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 2 without step 3 means every new author meets the gate as a rejection. Step 3 without step 2&lt;br&gt;
means the pattern erodes the first time someone starts from something other than the template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tradeoffs
&lt;/h2&gt;

&lt;p&gt;None of this is free, and some of it is arguably not worth it depending on what you are running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit time is real time.&lt;/strong&gt; Three parallel auditors plus remediation plus the addendum record&lt;br&gt;
consumed most of a working day for work that was already shipped and already paying. If your&lt;br&gt;
closure records are load-bearing for nobody, this is pure cost. Ours are cited by later blueprints&lt;br&gt;
and read by people who were not there, which is what makes a false record expensive later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A gate is a permanent maintenance obligation.&lt;/strong&gt; c34 and c35 will need updating every time&lt;br&gt;
Omarchy's runtime story or Quickshell's dispatch changes. The census gate needs its stoplist tended&lt;br&gt;
as our bead vocabulary grows. Thirty-eight gates in a submission lane is thirty-eight things that&lt;br&gt;
can develop their own defects, and the census gate is exactly the proof that a gate can be broken&lt;br&gt;
and quiet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False positives cost author trust faster than false negatives cost users.&lt;/strong&gt; The c34 quote-wrap&lt;br&gt;
rule is a syntactic heuristic, not semantic analysis. It will eventually block a correct&lt;br&gt;
construction that happens not to match the shape. c35's &lt;code&gt;manifest.json&lt;/code&gt; scoping and &lt;code&gt;tests/&lt;/code&gt;&lt;br&gt;
exemption exist to shrink that surface, and they shrink detection too. Every scoping decision is a&lt;br&gt;
false-negative decision wearing different clothes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The warden standard is a real bet.&lt;/strong&gt; "Corrections are records, not rework" keeps a team moving,&lt;br&gt;
and it also means an epic can be marked complete while carrying a known correction. That works&lt;br&gt;
because the corrections are discoverable in the addendum. It stops working the moment addenda stop&lt;br&gt;
being read, and nothing in the system enforces that they are.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A template can encode a pattern before it is proven.&lt;/strong&gt; &lt;code&gt;omarchy-widget-template&lt;/code&gt; freezes what two&lt;br&gt;
shipped widgets earned. If either of those patterns turns out to be wrong at ten widgets instead of&lt;br&gt;
two, the template has been quietly propagating the mistake the entire time, and templates are much&lt;br&gt;
harder to un-propagate than gates are to change. I took that bet knowingly: the patterns in it are&lt;br&gt;
the ones that survived a four-agent security panel, not the ones that merely worked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adversarial agents are optimizers, and refutation is a target.&lt;/strong&gt; An agent told to refute will&lt;br&gt;
find something. Two of the three auditors reported honest observations that were designed behavior&lt;br&gt;
rather than defects (a PR-diff gate passing vacuously on push events, a self-disclosed&lt;br&gt;
&lt;code&gt;enforce_admins: false&lt;/code&gt; residual), and labeled them as such. That labeling discipline is what keeps&lt;br&gt;
"refute" from degrading into manufactured findings, and it is the thing I would watch closest if I&lt;br&gt;
scaled this pattern up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this sits in the broader picture
&lt;/h2&gt;

&lt;p&gt;Supply-chain review practice converged on the same idea from a different direction. The industry&lt;br&gt;
answer to "is this dependency safe" stopped being "read the attestation" and became "re-execute the&lt;br&gt;
build and compare," because a record produced by the party under review is not independent&lt;br&gt;
evidence. Reproducible builds, in-toto attestations, and provenance verification are all the same&lt;br&gt;
move: do not trust the claim, re-derive it.&lt;/p&gt;

&lt;p&gt;Marketplace review is behind that. Most plugin and extension marketplaces still review submissions&lt;br&gt;
by reading them, and most of the interesting defects in this day's work are invisible to reading.&lt;br&gt;
The &lt;code&gt;--exec&lt;/code&gt; injection reads as ordinary string concatenation. The absent runtime reads as a normal&lt;br&gt;
shebang. The census self-skip reads as a well-written test. All three are only visible by running&lt;br&gt;
something.&lt;/p&gt;

&lt;p&gt;The transferable version, for anyone running gates on their own work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every gate needs at least one leg that runs from tracked artifacts alone. If your only drift
detector reads untracked state, the gate is blind in the environment it was built for.&lt;/li&gt;
&lt;li&gt;A logical OR on a load-bearing credential converts expiry into silent degradation. If the
credential matters, its absence is red.&lt;/li&gt;
&lt;li&gt;A closure claim about scheduled automation needs one completed run on the real trigger.&lt;/li&gt;
&lt;li&gt;Calibrate timeouts against measured healthy runtime. The incident is the worst possible baseline
because it is by definition not the normal case.&lt;/li&gt;
&lt;li&gt;Test every new gate against the real commit that motivated it, not only against synthetic cases.
Synthetic cases pass on a gate that reads the wrong files.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Eight sessions on &lt;code&gt;claude-code-plugins&lt;/code&gt;, 463 turns, 1002 tool calls, 51 errors hit, 1429 minutes of&lt;br&gt;
span, run by Claude Fable 5 and Claude Opus 4.8 across the day. Claude Opus 5 ran a separate&lt;br&gt;
profile-card thread, Claude Sonnet 5, Claude Opus 4.8, Grok 4.5, and Claude Sonnet 4.6 covered&lt;br&gt;
other repos.&lt;/p&gt;

&lt;p&gt;The audit phase was the strongest argument I have seen for parallel agents doing something a single&lt;br&gt;
session cannot. Three auditors, three scopes, no shared context, reporting at 00:14, 00:15 and&lt;br&gt;
00:19. They had no way to launder one another's assumptions, which is most of the&lt;br&gt;
value: the Epic 3 auditor did not know that Epic 4's bead existed, so it had no reason to excuse&lt;br&gt;
the census failure as expected.&lt;/p&gt;

&lt;p&gt;One human course-correction that day, and it was on the widget work rather than the audit:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;hold on their is some confusino braves booth has nothing to do with crew cchief that is way&lt;br&gt;
jacked up think about that for a minute then fidx it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two widget repos had gotten cross-contaminated in the model's working picture, and the fix was not&lt;br&gt;
a code change so much as a re-partition of what belonged to which repo. Worth noting because the&lt;br&gt;
audit and remediation ran the whole way with no steer at all, and the one place a human had to&lt;br&gt;
intervene was where two similar-shaped projects sat side by side. That is where agent context&lt;br&gt;
bleeds, every time.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;intent-os&lt;/code&gt; took PRs #540 and #541 on mission control: an agent and cohort activity view composed so&lt;br&gt;
that a denied read emits nothing rather than an empty row, plus a settlement fix so nothing in the&lt;br&gt;
receipts ledger can be silently invisible. Same principle as everything above, applied to a&lt;br&gt;
dashboard: absent data has to look absent.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;contributing-clanker&lt;/code&gt; &lt;a href="https://github.com/jeremylongshore/contributing-clanker/pull/70" rel="noopener noreferrer"&gt;PR #70&lt;/a&gt; cleared all 21 open Dependabot alerts via &lt;code&gt;npm audit fix&lt;/code&gt; plus a&lt;br&gt;
puppeteer 25 major bump, which is the boring dependency work that has to land before the gate PRs&lt;br&gt;
(&lt;a href="https://github.com/jeremylongshore/contributing-clanker/pull/71" rel="noopener noreferrer"&gt;#71&lt;/a&gt;, &lt;a href="https://github.com/jeremylongshore/contributing-clanker/pull/72" rel="noopener noreferrer"&gt;#72&lt;/a&gt;) are reviewable without noise.&lt;/p&gt;

&lt;p&gt;A GitHub profile card generator got built in &lt;code&gt;github-profile&lt;/code&gt; with Claude Opus 5. The ImageMagick&lt;br&gt;
preview reported overlapping SVG &lt;code&gt;tspan&lt;/code&gt; columns that librsvg rendered correctly, so the preview&lt;br&gt;
tool was lying and a faithful renderer had to be found before any preview could be trusted. Your&lt;br&gt;
preview tool is also under test. It also caught its own accuracy bug, counting 103 "public sources"&lt;br&gt;
because the token could see private repositories, corrected to 85 to match the REST count.&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-gate-that-could-not-fail/"&gt;The Gate That Could Not Fail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/every-safety-gate-has-a-failure-direction/" rel="noopener noreferrer"&gt;Every Safety Gate Has a Failure Direction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://startaitools.com/posts/honor-the-gate-when-the-verdict-is-inconvenient/" rel="noopener noreferrer"&gt;Honor the Gate When the Verdict Is Inconvenient&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cicd</category>
      <category>testing</category>
      <category>aiagents</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
