<?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: Blake Yang</title>
    <description>The latest articles on DEV Community by Blake Yang (@datars_7274).</description>
    <link>https://dev.to/datars_7274</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%2F4061230%2F081cb59c-26d8-46fd-a592-ce04b6639b4b.png</url>
      <title>DEV Community: Blake Yang</title>
      <link>https://dev.to/datars_7274</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/datars_7274"/>
    <language>en</language>
    <item>
      <title>Score the Issue Before You Claim It: A Reproducibility Ledger for OSS Work</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Thu, 15 Oct 2026 11:11:56 +0000</pubDate>
      <link>https://dev.to/datars_7274/score-the-issue-before-you-claim-it-a-reproducibility-ledger-for-oss-work-31fc</link>
      <guid>https://dev.to/datars_7274/score-the-issue-before-you-claim-it-a-reproducibility-ledger-for-oss-work-31fc</guid>
      <description>&lt;p&gt;Liquid syntax error: Unknown tag 'endraw'&lt;/p&gt;
</description>
      <category>opensource</category>
      <category>ai</category>
      <category>github</category>
      <category>testing</category>
    </item>
    <item>
      <title>A Citation Check for OSS Patches Starts With a Minimized Public Fixture</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Mon, 12 Oct 2026 23:58:48 +0000</pubDate>
      <link>https://dev.to/datars_7274/a-citation-check-for-oss-patches-starts-with-a-minimized-public-fixture-33p6</link>
      <guid>https://dev.to/datars_7274/a-citation-check-for-oss-patches-starts-with-a-minimized-public-fixture-33p6</guid>
      <description>&lt;p&gt;A maintainer on a small library closed a pull request after the patch looked tidy and the model review sounded confident. The contributor had pasted a long log into chat, received praise, and opened the request without a public failing fixture. On a clean clone of the default branch, the reported command exited zero, so the patch had nothing to prove. That scene is a composite of common review failures, not a claim about one named project.&lt;/p&gt;

&lt;p&gt;The same pattern appears when a model reviews a diff before anyone proves the bug on the upstream default branch. Agreement then becomes a style comment about the patch, rather than evidence that the failure existed at all. A useful workflow freezes a public bundle first, then invites a model to comment only on fields inside that bundle. The bundle, not the model's tone, decides whether the patch is ready for a human maintainer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Freeze a public bundle the model is allowed to see
&lt;/h2&gt;

&lt;p&gt;A review bundle is a directory committed on a scratch branch, or attached to the issue, before any model sees the patch. It holds the failing command, the expected exit status, a fixture file, and a short note about the default-branch commit. It also holds a license check result and a test command copied from the repository's own documentation. Secrets, tokens, and private hostnames stay out of that directory so the packet can be shared with a model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fields that make the packet checkable
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The file &lt;code&gt;base_sha.txt&lt;/code&gt; records the upstream commit where the failure was observed, and later reruns must detach at that commit.&lt;/li&gt;
&lt;li&gt;The file &lt;code&gt;exit_status.txt&lt;/code&gt; stores the status of the failing command, and a clean default-branch run must reproduce that status.&lt;/li&gt;
&lt;li&gt;The file &lt;code&gt;fixture.sha256&lt;/code&gt; names the public input, so a review cannot swap in a quieter file after the model has spoken.&lt;/li&gt;
&lt;li&gt;The file &lt;code&gt;license_gate.txt&lt;/code&gt; records whether an SPDX identifier search succeeded, which is a gate and not a full legal review.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Build the bundle with a script that can be rerun
&lt;/h2&gt;

&lt;p&gt;The following shell script is an unexecuted proposal, not a recorded run from this account, and paths must be adapted. It writes the base commit, copies one fixture, captures status streams, probes for an SPDX line, and hashes the packet. A contributor should replace the sample CLI invocation with the command already documented by the upstream project. The hash file is the handle a later review uses to prove the packet did not drift between machines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# Proposal: unexecuted example. Adapt paths before use.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--show-toplevel&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;SHA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse HEAD&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;OUT&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;ROOT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.review-bundle"&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="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/fixture"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SHA&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/base_sha.txt"&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/repro/input.txt"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/fixture/input.txt"&lt;/span&gt;
&lt;span class="nb"&gt;sha256sum&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/fixture/input.txt"&lt;/span&gt; &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/fixture.sha256"&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; +e
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; project.cli &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/fixture/input.txt"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/stdout.txt"&lt;/span&gt; 2&amp;gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/stderr.txt"&lt;/span&gt;
&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/exit_status.txt"&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"SPDX-License-Identifier"&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;'*.py'&lt;/span&gt; &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/spdx.txt"&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"spdx-present"&lt;/span&gt; &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/license_gate.txt"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"spdx-missing"&lt;/span&gt; &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/license_gate.txt"&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;find &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'packet.sha256'&lt;/span&gt; &lt;span class="nt"&gt;-print0&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; | xargs &lt;span class="nt"&gt;-0&lt;/span&gt; &lt;span class="nb"&gt;sha256sum&lt;/span&gt; &lt;span class="o"&gt;&amp;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;OUT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/packet.sha256"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the script on a dirty worktree will mix unrelated edits into the story the packet tells the reviewer. A clean detached checkout of the recorded base commit is the honest place to capture the failing status. If that status is already zero, the contributor stops and does not ask a model to invent a bug. That stop is the point of the bundle, and it saves the maintainer from reviewing a speculative patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Climb three rungs before any model comment
&lt;/h2&gt;

&lt;p&gt;Rung one runs the failing command on a clean checkout of the recorded base commit and expects the frozen exit status. Rung two applies the patch on that same commit and expects the command to exit zero. Rung three runs the repository test command, not a new test invented for the patch alone. A model should not be asked to invent those commands after the fact, because that invites a moving target.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repeat the rungs on a second checkout
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin
git switch &lt;span class="nt"&gt;--detach&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .review-bundle/base_sha.txt&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
bash scripts/oss-review-bundle.sh
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .review-bundle/exit_status.txt&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt;
git apply &lt;span class="nt"&gt;--check&lt;/span&gt; patches/fix.diff
git apply patches/fix.diff
&lt;span class="c"&gt;# Proposal: after the patch, rerun the documented command and expect status 0.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first test line fails the workflow when the recorded status is not reproduced, which is the desired alarm. The apply check catches a patch that does not fit the recorded base commit, before anyone discusses coding style. After the patch applies, the same command should exit zero, and the repository test command should still pass. A model review that arrives before these three results exist is commentary, not evidence a maintainer can trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimize the fixture without deleting the failure
&lt;/h2&gt;

&lt;p&gt;A long log invites a model to summarize noise and then miss the line that actually fails the command. The contributor should cut the fixture in halves, rerun the failing command, and keep the half that still fails. Each cut is recorded by appending the new fixture hash to a short minimization log stored inside the bundle. When a cut makes the status become zero, that cut is discarded and the previous fixture remains the public input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps that keep the failure alive
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Copy the original fixture into the bundle and record its hash, its line count, and the failing exit status.&lt;/li&gt;
&lt;li&gt;Split that fixture into two halves and rerun the documented failing command against each half on the recorded commit.&lt;/li&gt;
&lt;li&gt;Keep the smallest half that still returns the frozen status, and append that hash to the minimization log.&lt;/li&gt;
&lt;li&gt;Stop when neither half fails, restore the previous fixture, and treat that file as the public input for review.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The log format below is a proposal with placeholder hashes, not measured output from a repository. A real run replaces those tokens with &lt;code&gt;sha256sum&lt;/code&gt; output and the exit status just observed. The discarded row stays in the log so a reviewer can see which cut destroyed the failure. That trail matters more than a shorter file that no longer fails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;step=0 lines=48 sha256=placeholder-original status=1 kept
step=1 lines=24 sha256=placeholder-half status=1 kept
step=2 lines=12 sha256=placeholder-quarter status=0 discarded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Score review comments by citation
&lt;/h2&gt;

&lt;p&gt;A model review earns trust only when each remark names a file that already sits inside the frozen bundle. A comment that calls the patch correct without naming &lt;code&gt;exit_status.txt&lt;/code&gt; or &lt;code&gt;fixture.sha256&lt;/code&gt; scores zero for evidence. A comment that cites a packet file and quotes a line can be checked by a human in one pass. This scoring habit resists fluent agreement that replaces a failed reproduction on the recorded base commit itself.&lt;/p&gt;

&lt;p&gt;The table below is a proposal for sorting comments, not a measured study from this account's history. Strong rows still require a human to open the cited file before the patch is allowed to move. Weak rows are corrections to the note, not reasons to merge the patch into the default branch. Empty rows are discarded even when the wording sounds confident, polite, and ready for a maintainer.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model comment pattern&lt;/th&gt;
&lt;th&gt;Packet citation&lt;/th&gt;
&lt;th&gt;Human action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fluent praise with no filename&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Discard the comment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cites &lt;code&gt;exit_status.txt&lt;/code&gt; but quotes the wrong digit&lt;/td&gt;
&lt;td&gt;Weak&lt;/td&gt;
&lt;td&gt;Open the file and correct the note&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cites &lt;code&gt;fixture.sha256&lt;/code&gt; and the minimization log&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;td&gt;Compare hashes, then read the diff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suggests a test command absent from the repo docs&lt;/td&gt;
&lt;td&gt;Out of packet&lt;/td&gt;
&lt;td&gt;Ignore until a human adds that command&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Proposal: unexecuted. Scores whether review lines cite packet files.
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;PACKET&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;base_sha.txt&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;exit_status.txt&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;fixture.sha256&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;license_gate.txt&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;packet.sha256&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model-review.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cited&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PACKET&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PACKET&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cited&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cited=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cited&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;missing=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;missing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;cited&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review cited no packet file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The checker is also an unexecuted proposal, and it only tests whether filenames appear in the review text. It cannot tell whether the model understood the exit status, so a human still opens every cited file. If the checker exits because no packet file was named, the review is rejected without a second pleading prompt. A second prompt that begs for agreement would only recreate the original failure mode this bundle is meant to stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use free model access only after the hash is frozen
&lt;/h2&gt;

&lt;p&gt;MonkeyCode is relevant here only as an optional place to run the citation pass and to repeat the bundle script. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The operator-supplied claim used here is that free model access and a free server option currently exist. The operator also describes the project as open source, which readers should confirm in the repository before they depend on it.&lt;/p&gt;

&lt;p&gt;This article does not state model names, token quotas, hardware sizes, or how long that access lasts. Readers should confirm current terms on the project page before relying on either option for a real review. A missing or changed offer does not break the ladder, because the packet can be reviewed by a person alone. Hosted help is a convenience after the hash exists, not a requirement for the reproduction or the patch.&lt;/p&gt;

&lt;p&gt;A free model pass is useful after the packet hash is frozen, because the model then has a closed set of files to cite. A free server rerun is useful when the contributor's laptop has extra packages that the upstream image does not install. Both steps stay optional, and the ladder still works with a local model or with a second container on the same desk. The packet hash, not the model's tone, remains the acceptance criterion for moving the patch toward a human reviewer.&lt;/p&gt;

&lt;p&gt;The prompt should ask for missing packet fields, mismatched hashes, and a license gate that printed &lt;code&gt;spdx-missing&lt;/code&gt;. It should not ask for a verdict that the patch is ready to merge, because that verdict is a human decision. Output belongs in &lt;code&gt;model-review.md&lt;/code&gt; beside the packet, so the filename checker can read it without extra parsing. The contributor then keeps only sentences that name a packet file before the maintainer sees the note.&lt;/p&gt;

&lt;p&gt;The contributor deletes any sentence that does not name a packet file before the maintainer sees the note. That deletion is a human edit, and the pull request should say the model text was filtered by the checker. A maintainer can then review the patch, the packet, and a short list of cited gaps without rereading praise. The model does not appear as an author of the commit, because authorship stays with the person who can answer questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations that should stay visible
&lt;/h2&gt;

&lt;p&gt;This workflow does not prove that a patch is correct, and it does not replace the maintainer's review or the project's legal process. A minimized fixture can drop the real bug if the contributor cuts the input until the failure disappears. License header searches miss files that use a different SPDX line, or a license that lives only in a top-level file. A model can still cite the right filename and misread the exit status, so a human must open the cited file.&lt;/p&gt;

&lt;p&gt;The free server option, where it is available, does not guarantee the same packages as the project's continuous integration image. A rerun that passes on a generic machine can still fail inside the upstream workflow file on the next push. Contributors should treat a green second machine as a portability hint, not as a substitute for the project's own checks. Quotas, model names, and how long free access lasts sit outside this article and must be read from current terms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip the bundle
&lt;/h2&gt;

&lt;p&gt;Skip this bundle when the repository forbids attached fixtures, or when the bug depends on private data that cannot be reduced. Skip it when the change is a documentation typo with no failing command, because a fake exit status would only add noise. Skip it when the contributor cannot read the test output well enough to reject a confident but wrong model comment. In those cases a short issue comment and a human review remain the honest path, and a model pass would not help.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the maintainer should be able to replay
&lt;/h2&gt;

&lt;p&gt;A maintainer should be able to detach at the recorded commit, rerun the bundle script, and see the same fixture hash. The patch should flip the frozen status, and the citation checker should show at least one packet file in the review note. If either hash differs, the conversation stops until the contributor publishes a new packet rather than explaining the drift in chat. That replay is the whole method, and it remains useful even if no hosted model or free server is used.&lt;/p&gt;

&lt;p&gt;Readers who still want a clean second machine for that replay can check whether MonkeyCode's free server option is open. They should require the same packet hash on that machine before they trust the rerun at all. The free model access, if currently offered, fits only the citation pass after the hash file already exists. Neither option is a merge approval, and the project page is the place to confirm what is available that day.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>git</category>
      <category>ai</category>
    </item>
    <item>
      <title>Separate the Evidence Commit From the OSS Fix Before Model Output Runs</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Sat, 10 Oct 2026 17:06:52 +0000</pubDate>
      <link>https://dev.to/datars_7274/separate-the-evidence-commit-from-the-oss-fix-before-model-output-runs-2mmc</link>
      <guid>https://dev.to/datars_7274/separate-the-evidence-commit-from-the-oss-fix-before-model-output-runs-2mmc</guid>
      <description>&lt;p&gt;A maintainer declined a parser pull request after the diff rewrote three files and never preserved the original failure. The contributor had pasted a repository link into a coding model, accepted the generated patch, and pushed one squashed commit. Local checks passed on that laptop, yet reviewers could not replay the reported bug from any commit on the branch. The project wanted a failing case stored in history before anyone discussed the shape of the repair.&lt;/p&gt;

&lt;p&gt;The scene above is a composite illustration, not a report from this account or a named maintainer. The rejection pattern still points to a missing contribution gate rather than a simple score of model quality. A careful open-source change records the failure in its own commit, then limits what a model may read and where its patch may run. The workflow below uses a red commit, a narrow packet, and a disposable runner, and it still works with no hosted model.&lt;/p&gt;

&lt;h2&gt;
  
  
  What reviewers can replay
&lt;/h2&gt;

&lt;p&gt;Maintainers usually gain confidence when a failure replays on a clean tree that does not depend on the author's shell profile. The first commit stores the command, the fixture, and a captured non-zero result before production code changes. The second commit may repair the defect, but it should not rewrite, weaken, or delete that recorded evidence. A reviewer can move between those commits and watch the same command change from failing to passing.&lt;/p&gt;

&lt;p&gt;This pattern fits a public issue, a license that permits sharing the selected files, and a command that fails for a known reason. It does not require write access on the upstream project, and it does not treat a model suggestion as already correct. Patch text stays untrusted until a clean runner executes it and a human compares the result with the red commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Land the evidence commit first
&lt;/h2&gt;

&lt;p&gt;The contributor clones the upstream project, opens a topic branch, and adds only reproduction assets. Those assets may be a focused test, a tiny fixture, or a shell script kept under a clearly named directory. Formatting sweeps, lockfile refreshes, and drive-by refactors remain outside the evidence commit on purpose. If the command cannot fail on a clean upstream checkout, work stops until the fixture is honest.&lt;/p&gt;

&lt;p&gt;The shell below is a proposed example, not a transcript from a real repository run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://example.invalid/org/cli.git
&lt;span class="nb"&gt;cd &lt;/span&gt;cli
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; issue-1842-quoted-flag
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; repro
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/quoted-flag.sh &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
#!/usr/bin/env bash
set -eu
# Proposed stand-in. Point this at the real project binary and fixture.
./bin/cli --config repro/quoted.toml run
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x repro/quoted-flag.sh
&lt;span class="nb"&gt;set&lt;/span&gt; +e
./repro/quoted-flag.sh &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/actual.txt 2&amp;gt; repro/stderr.txt
&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'exit=%s\nstderr_bytes=%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&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;wc&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &amp;lt; repro/stderr.txt&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/status.txt
git add repro
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"test: reproduce quoted flag drop from issue 1842"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The status note should record the exit code and the stderr size, not a dump of the local environment. Home-directory paths, access tokens, and internal hostnames do not belong in files that may later leave the laptop. A case that fails only inside one customized shell profile is not ready for a model or a maintainer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose a packet, then choose a runner
&lt;/h2&gt;

&lt;p&gt;A free model can read the reproduction and one suspected function, then propose an edit that leaves the evidence files untouched. That help is optional, and the boundary around execution matters more than the vendor behind the suggestion. Generated patch text should run first on a disposable runner, not beside developer credentials or private clones. A full-tree upload is unnecessary when the evidence commit already names the command and the fixture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The reproduction script and fixture may be sent when the license allows those files to be redistributed.&lt;/li&gt;
&lt;li&gt;A short status note may be sent after paths, tokens, and hostnames have been removed from the captured text.&lt;/li&gt;
&lt;li&gt;One suspected function may be sent, while an archive of the whole working tree should stay on the laptop.&lt;/li&gt;
&lt;li&gt;Environment files, keys, cookies, private logs, and unpublished vulnerability detail stay out of the packet.&lt;/li&gt;
&lt;li&gt;Unseen patch text should not run on a laptop that holds SSH keys, release tokens, or private clones.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Allowed default&lt;/th&gt;
&lt;th&gt;Stop if this is false&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Evidence is its own commit&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;The failure exists only in chat history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model sees a narrow packet&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;The only prompt is a full-tree paste&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First execution is disposable&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;The only runner holds personal credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reproduction files stay unchanged&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;The patch edits the evidence to force green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human edits the pull-request text&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;A model summary would be posted unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode is relevant only as one way to reach free model access and a free server for this bounded review step. The same checks remain valid in another editor, with another model, or with no hosted service in the loop. No model names, token quotas, hardware sizes, time limits, or permanent terms are stated here, because those details were not verified for this draft.&lt;/p&gt;

&lt;p&gt;The operator-supplied claim is limited to free model access for the review note and a free server option for the first patch execution. The contributor still owns redaction, the evidence commit, and the later decision to open a pull request. Readers who skip the product name still have the commit split, the runner sequence, and the rejection rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply the suggestion away from the laptop
&lt;/h2&gt;

&lt;p&gt;After the evidence commit exists, the contributor may ask for a minimal production change that makes the reproduction return zero. The reply is saved as patch text and is not executed on the laptop that holds SSH keys or browser sessions. A disposable free server, or any other clean virtual machine, receives a fresh clone and that patch file. The runner has no maintainer credentials, no personal tokens, and no extra repositories beyond the public topic branch.&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;# Proposed sequence for a clean runner. Do not target a production host.&lt;/span&gt;
git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 &lt;span class="nt"&gt;--branch&lt;/span&gt; issue-1842-quoted-flag https://example.invalid/you/cli.git
&lt;span class="nb"&gt;cd &lt;/span&gt;cli
git apply &lt;span class="nt"&gt;--check&lt;/span&gt; /tmp/model-fix.patch
git apply /tmp/model-fix.patch
&lt;span class="nb"&gt;set&lt;/span&gt; +e
./repro/quoted-flag.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"post-patch:&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
git diff &lt;span class="nt"&gt;--exit-code&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stop conditions
&lt;/h3&gt;

&lt;p&gt;Three observable results are enough to stop the trial before a pull request is opened at all. Each result is a reason to keep the evidence commit and to discard the current suggestion entirely. None of these results should be patched over by sending a larger private context to the model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The patch fails &lt;code&gt;git apply --check&lt;/code&gt;, so the next request stays narrow instead of adding private files for context.&lt;/li&gt;
&lt;li&gt;The reproduction command still fails, so the suggestion is discarded and the evidence commit remains authoritative.&lt;/li&gt;
&lt;li&gt;A non-empty diff under the reproduction path means the patch mixed repair with evidence and should be rejected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the same command passes and the reproduction diff is empty, a second commit may hold only the production change. The branch history then shows the miss first and the attempted repair second, which is easier to review than a squash. A model may draft the pull-request summary from those two diffs, but a human must edit every factual claim. The maintainer should be able to replay both commits without trusting the tool that wrote the second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the branch shape before upload
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Proposed checker
&lt;/h3&gt;

&lt;p&gt;The script below is a proposal for the fix commit, and it has not been executed against a real upstream project here. Path names, branch names, and the reproduction directory must be adapted before anyone relies on the result. A passing shape check still does not replace the reproduction command or the project's own test target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# Proposed shape check. Run while HEAD is the fix commit.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-eu&lt;/span&gt;
&lt;span class="nv"&gt;base&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;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;HEAD&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;
git diff &lt;span class="nt"&gt;--exit-code&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$base&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; repro
&lt;span class="k"&gt;if &lt;/span&gt;git diff &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$base&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;':!repro'&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"fix commit has no production change"&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="k"&gt;fi
if &lt;/span&gt;git diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$base&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;'(^|/)\.env$|id_rsa|credentials\.json'&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"sensitive-looking path in the fix diff"&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="k"&gt;fi
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"commit shape accepted; still rerun the reproduction command"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manual replay
&lt;/h3&gt;

&lt;p&gt;The numbered checks below are the human gate between a green runner and a public pull request. These steps remain proposed checks for the contributor, not measured results from an executed upstream trial. A skipped check leaves the branch unready, even when the shape script prints an acceptance line.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The contributor checks out the evidence commit on a clean tree and confirms a non-zero status.&lt;/li&gt;
&lt;li&gt;The contributor checks out the fix commit and confirms a zero status from the same command.&lt;/li&gt;
&lt;li&gt;The contributor confirms that the reproduction path did not change between the evidence commit and the fix.&lt;/li&gt;
&lt;li&gt;The contributor runs the repository's own targeted test and records that exact command in the pull request.&lt;/li&gt;
&lt;li&gt;The contributor searches the diff for home paths, tokens, and private hostnames before any upload.&lt;/li&gt;
&lt;li&gt;If a model remains in the loop, it may only hint at callers outside the suspected function, and project tests must confirm that hint.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Limits, and who should skip this
&lt;/h2&gt;

&lt;p&gt;This gate suits small, replayable defects in projects that accept external pull requests and can tolerate a failing test beside a fix. It is a poor fit for races that vanish on a clean runner and for failures that require private production data. Security reports that belong in a private disclosure channel should not be turned into a public reproduction commit. A free server is also the wrong place for customer logs, licensed corpora, or any tree the contributor may not upload.&lt;/p&gt;

&lt;p&gt;Model assistance stays optional here and is easy to overrate once the reproduction already looks clean. A free model can suggest a narrow edit, yet it cannot certify license fit, maintainer preference, or timing stability. If the failing command cannot be published, sending a richer private log to a hosted model is not an acceptable workaround. The honest alternatives are a purely local fix, a question to the maintainers, or no patch until the fixture is shareable.&lt;/p&gt;

&lt;p&gt;Teams that already require a paired regression test can adopt the commit split without subscribing to any hosted service. The disposable runner matters most when the patch text came from a model and has not been read line by line. Contributors who cannot isolate a public fixture should pause rather than widen the packet to force progress.&lt;/p&gt;

&lt;p&gt;A single open issue is a better trial than a batch of generated pull requests across unrelated repositories. The contributor can land the evidence commit locally, then use free model access only on the redacted packet and a free server only for the first apply. The resulting pull request should stay small enough that replay, not the drafting tool, carries the review.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>git</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>Freeze a Failing Oracle Before Any Model Touches an OSS Patch</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Fri, 09 Oct 2026 13:17:09 +0000</pubDate>
      <link>https://dev.to/datars_7274/freeze-a-failing-oracle-before-any-model-touches-an-oss-patch-2gkb</link>
      <guid>https://dev.to/datars_7274/freeze-a-failing-oracle-before-any-model-touches-an-oss-patch-2gkb</guid>
      <description>&lt;p&gt;A weekend contributor clones a small library, reproduces a parser bug, and asks a coding model to repair it before dinner. The model returns a tidy diff, a confident summary, and a test that already passes on the patched tree. The maintainer later discovers that the same test also passed on the unpatched tag, so the pull request never proved a fix. That pattern wastes review time, and a frozen oracle stops it before the branch leaves the fork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a passing test is not evidence
&lt;/h2&gt;

&lt;p&gt;An open-source review needs a failure that exists before the patch and disappears after the patch, under the same command. A generated test written after the edit can encode the new behavior without ever having failed. Reviewers then argue about intended behavior instead of comparing two captured runs from the same command. The workflow below treats those two runs as the contract that every later comment must respect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the loop in order
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Write the manifest with an argument list, both expected statuses, and two markers before any production edit.&lt;/li&gt;
&lt;li&gt;Capture the before side on the untouched checkout and stop if the status is already the success code.&lt;/li&gt;
&lt;li&gt;Apply the smallest patch that can clear the failure marker, whether a person or a model drafted the diff.&lt;/li&gt;
&lt;li&gt;Capture the after side, run the checker, and refuse the pull request text when the checker returns an error.&lt;/li&gt;
&lt;li&gt;Ask the model to compare the diff with those files, and leave the merge decision with a human reviewer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lay out the evidence before editing
&lt;/h2&gt;

&lt;p&gt;The contributor creates an evidence directory before touching production code, then records the failing command in a small manifest. That manifest names the command, the expected nonzero status, and a short marker that must appear in the failure output. A later checker refuses to bless a patch when either capture is missing or when the command string has changed. The point is narrow: prove this bug, on this command, before any model rewrites the story.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directory contract
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;evidence/
  manifest.json
  before/stdout.txt
  before/stderr.txt
  before/status.txt
  after/stdout.txt
  after/stderr.txt
  after/status.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Proposed manifest
&lt;/h3&gt;

&lt;p&gt;The sample below is a proposal for one pytest node, and it is not a result from a named upstream repository. Replace the argument list with the project's real test command before capturing either side of the oracle. Keep markers short and specific so a later reviewer can see them in the saved output without guessing. Do not treat the sample statuses as defaults for every language or every test runner on the project.&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;"command"&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="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-m"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pytest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-q"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tests/test_parser.py::test_trailing_comma"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"before_status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"after_status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"failure_marker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"trailing comma"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success_marker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1 passed"&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;h2&gt;
  
  
  Capture both sides with one script
&lt;/h2&gt;

&lt;p&gt;The capture script reads the manifest, runs the listed command, and writes status plus both streams into the requested side directory. It does not interpret the bug, and it does not accept a free-form shell string, because argument lists avoid accidental quoting surprises. The contributor runs it once on the untouched checkout, applies the human or model patch, then runs it again with the after side. If the before status already matches the after status, the oracle is invalid and the patch should not be opened.&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;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Proposed local helper. Not a recorded run against an upstream repository.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;side&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;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;manifest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence/manifest.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&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="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stdout.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stderr.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python capture_oracle.py before
python capture_oracle.py after
python check_oracle.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Check the oracle before review comments exist
&lt;/h2&gt;

&lt;p&gt;The checker loads the manifest and both status files, then confirms the failure marker and the success marker landed on the correct side. It also rejects a success marker that already appears in the before output, which catches tests that never failed. A nonzero checker result means the pull request description must not claim that the captured bug is fixed. The script below is a proposal for a fork-local gate, and it should be adapted to the project's real test entry point.&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;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Proposed checker. Sample markers are not universal pass criteria.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&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;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;manifest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manifest.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;before_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;before&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;after_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;before_text&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;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;before&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stdout.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;before&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stderr.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;after_text&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;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stdout.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stderr.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;before_status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;before_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="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;before status does not match the manifest&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;after_status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="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;after status does not match the manifest&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;manifest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;failure_marker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;before_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;errors&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;failure marker missing from before output&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;manifest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success_marker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;after_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;errors&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;success marker missing from after output&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;manifest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success_marker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;before_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;errors&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;success marker already present before the patch&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;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;oracle holds: failure captured, then cleared, under one command&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="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let a free model review the contract, not invent it
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;MonkeyCode's free model access can sit in the review lane after the oracle already exists on disk. The useful task is a bounded reading of the diff against the evidence files, not a fresh verdict on the bug. A careful prompt asks the model to list mismatches, untested branches, and claims that the captured files do not support. The free server option helps when a clean remote run is needed, provided the resulting evidence files still pass the local checker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Review only evidence/manifest.json, the before and after captures, and the diff.
Do not claim a bug is fixed unless the checker would pass on those files.
List pull request claims that the captured output does not support.
Do not widen the patch, and do not suggest new dependencies.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Split model comments from maintainer decisions
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Model may draft&lt;/th&gt;
&lt;th&gt;Human must decide&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Did the before status match the manifest?&lt;/td&gt;
&lt;td&gt;Quote the status file&lt;/td&gt;
&lt;td&gt;Reject the request if it does not&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Did the marker move from failure to success?&lt;/td&gt;
&lt;td&gt;Point at the two captures&lt;/td&gt;
&lt;td&gt;Confirm the marker is specific enough&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does the diff touch paths outside the fix and the test?&lt;/td&gt;
&lt;td&gt;List the extra paths&lt;/td&gt;
&lt;td&gt;Accept the scope or split the series&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Are license, API, or release notes correct?&lt;/td&gt;
&lt;td&gt;Flag uncertainty only&lt;/td&gt;
&lt;td&gt;Own the final answer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Should this merge?&lt;/td&gt;
&lt;td&gt;No draft of a merge vote&lt;/td&gt;
&lt;td&gt;Yes, after reading the files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table is the review boundary for this workflow, and it stays useful even if the model name changes next month. Current quotas, model lists, and server limits are product facts that expire, so this article does not quote them. Contributors should read the current MonkeyCode documentation before relying on a free run for a time-boxed contribution. A changed limit is a reason to run the same scripts locally, not a reason to skip the oracle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the patch inside the oracle
&lt;/h2&gt;

&lt;p&gt;A frozen oracle does not prove that every edited line was necessary, so the contributor still reads the diff before opening the request. Extra refactors, renamed helpers, and drive-by formatting changes should move to a separate commit or leave the branch. The model may list those extra paths, but it should not be asked to clean up the module after the evidence is green. A small patch plus a failing-then-passing command is easier to revert than a broad rewrite with a flattering summary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commands a reviewer can rerun
&lt;/h2&gt;

&lt;p&gt;The pull request body should contain the manifest command and the checker result, copied from the terminal rather than paraphrased. A reviewer on another machine can then run the same argument list, compare status files, and stop if the marker is too vague. A documented setup target belongs in the manifest notes, and this article does not invent a universal container name. The evidence files stay in the fork until the maintainer asks for them, because some projects prefer not to commit bulky logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the marker lies
&lt;/h2&gt;

&lt;p&gt;A marker that appears in ordinary passing output will make the checker reject a real fix, and that failure is useful. The contributor should choose a string that shows up only in the broken run, such as a specific exception text or a fixture name. If no such string exists, the test itself is the missing artifact, and editing production code first would hide that gap. Flaky commands are out of scope, because a status that changes between two before captures means the oracle is not ready for model review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this gate
&lt;/h2&gt;

&lt;p&gt;This approach is a poor fit for patches that cannot be reduced to one command with a stable marker. Documentation-only edits, visual changes, and rare race conditions need a different proof, because a single captured status can look green while the bug remains. Projects that already require a recorded replay file should follow that project rule instead of adding a second evidence format. The checker also does not replace secret scanning, license review, or a blast-radius look at shared helpers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Close the branch only after the files agree
&lt;/h2&gt;

&lt;p&gt;A contributor who wants a second reading can paste the checker output and the diff into a free model session. The only requested output should be unsupported claims, checked against files already stored in the evidence directory. Those scripts remain unexecuted proposals, so each fork should adjust markers to its own test runner before trusting a green line. When the two captures and the checker agree, the branch is ready for a human reviewer rather than for another generated summary.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>git</category>
      <category>ai</category>
    </item>
    <item>
      <title>Convert CONTRIBUTING.md Into an Executable Preflight Gate Before an OSS Patch Leaves Your Fork</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Thu, 08 Oct 2026 09:26:47 +0000</pubDate>
      <link>https://dev.to/datars_7274/convert-contributingmd-into-an-executable-preflight-gate-before-an-oss-patch-leaves-your-fork-mah</link>
      <guid>https://dev.to/datars_7274/convert-contributingmd-into-an-executable-preflight-gate-before-an-oss-patch-leaves-your-fork-mah</guid>
      <description>&lt;p&gt;A contributor spends a weekend on a null-dereference fix, opens the pull request on Monday morning, and watches CI fail on a rule that CONTRIBUTING.md stated in paragraph nine. The patch logic is correct, but the branch name lacks the expected prefix and the changelog entry is missing. Three review rounds later, the maintainer merges a change whose packaging cost more than its implementation.&lt;/p&gt;

&lt;p&gt;That failure mode is rarely about code quality, and it is almost always about packaging. Contribution guidelines are written as prose for humans and enforced as machines somewhere else, so the gap gets paid for in review latency. The workflow below closes that gap with an executable preflight gate, a reproducible test step, and a narrow review role for free-tier models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why prose rules and CI checks drift apart
&lt;/h2&gt;

&lt;p&gt;Most repositories accumulate contribution rules in three separate places, and none of them is authoritative. CONTRIBUTING.md explains intent, CI enforces a subset, and maintainers enforce the remainder from memory during review.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The document drifts after a tooling change, because nobody re-reads paragraph nine.&lt;/li&gt;
&lt;li&gt;CI cannot check intent, so reviewers absorb the difference as unpaid coordination work.&lt;/li&gt;
&lt;li&gt;Contributors learn the real rules only after a failed pull request, which is the most expensive classroom.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical fix is not stricter CI. It is a local gate that runs the rules the repository already claims to have, before a patch becomes other people's problem.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The snippets below are illustrative and were not run against a specific public repository; adapt paths and tool names to your target project before relying on them.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Extract the rules into a reviewed YAML file
&lt;/h2&gt;

&lt;p&gt;Convert prose into a small machine-readable file that a human approves once and CI can diff later. Keep every rule traceable to the sentence it came from, so a disagreement can be settled by reading the source document.&lt;/p&gt;

&lt;p&gt;A free model tier handles the mechanical extraction well, because the task is reading and structuring, not deciding. The prompt below deliberately forbids inference, which is the failure mode that turns an extraction pass into invented policy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are extracting contribution rules from a repository document.
Return YAML only, with this schema:
  version: 1
  branch_pattern: &amp;lt;regex or null&amp;gt;
  required_when:
    - path: &amp;lt;file that must change&amp;gt;
      when_changed: [&amp;lt;glob&amp;gt;, ...]
Return a separate key `unresolved` for any sentence that is advisory rather than checkable.
For every rule, include `source_line`, the line number in the document.
Do not infer rules that are not written. Mark ambiguous rules with `needs_human: true`.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting file stays small on purpose. A gate with forty checks gets disabled within a week, while one with five honest checks survives contact with a real release cycle.&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="c1"&gt;# .contrib-rules.yml — extracted from CONTRIBUTING.md, human-reviewed&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;branch_pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^(fix|feat|docs|chore)/[a-z0-9._-]+$'&lt;/span&gt;
&lt;span class="na"&gt;required_when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CHANGELOG.md&lt;/span&gt;
    &lt;span class="na"&gt;when_changed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src/**/*.py'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lib/**/*.js'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docs/&lt;/span&gt;
    &lt;span class="na"&gt;when_changed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**/public_api.py'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;unresolved&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Prefer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;small&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pull&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requests."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Build the preflight gate
&lt;/h2&gt;

&lt;p&gt;The gate has two jobs: reject packaging mistakes locally, and run the project's own test dialect exactly as the repository defines it. A shell wrapper handles ordering, while a small Python checker evaluates the file-level rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# scripts/preflight.sh — run the repo's stated rules before pushing a patch&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;BASE&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;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;/main&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;RULES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;".contrib-rules.yml"&lt;/span&gt;

&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;pattern&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;python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import yaml;print(yaml.safe_load(open('&lt;/span&gt;&lt;span class="nv"&gt;$RULES&lt;/span&gt;&lt;span class="s2"&gt;'))['branch_pattern'])"&lt;/span&gt;&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;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ &lt;span class="nv"&gt;$pattern&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"preflight: branch '&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;' does not match &lt;/span&gt;&lt;span class="nv"&gt;$pattern&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="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;python3 scripts/preflight_rules.py &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
make &lt;span class="nb"&gt;fmt
&lt;/span&gt;make lint
make &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;preflight_rules.py — verify file-level contribution rules locally.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fnmatch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;

&lt;span class="n"&gt;RULES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safe_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.contrib-rules.yml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;changed_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&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;list&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;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&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;diff&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;--name-only&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...HEAD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="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="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&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;def&lt;/span&gt; &lt;span class="nf"&gt;check_required_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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;list&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;problems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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;=&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;rule&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;RULES&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;required_when&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;triggers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rule&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;when_changed&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;touched&lt;/span&gt; &lt;span class="o"&gt;=&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;fnmatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fnmatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&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;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;triggers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;touched&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required file not updated: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="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;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;origin/main&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check_required_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;changed_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&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;issue&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;preflight: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reproducing the failure in a clean checkout
&lt;/h3&gt;

&lt;p&gt;A gate that only passes on a dirty working tree teaches nothing, so reproduce the failure once in a throwaway worktree. This isolates the patch from editor state, local build artifacts, and half-installed dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add ../oss-repro &lt;span class="nt"&gt;-b&lt;/span&gt; preflight-check origin/main
&lt;span class="nb"&gt;cd&lt;/span&gt; ../oss-repro
git cherry-pick &amp;lt;your-commit-sha&amp;gt;
bash scripts/preflight.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the gate passes in the clean worktree and fails in CI, the difference is environmental rather than logical, and the useful artifact becomes a pinned environment file instead of another code change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Use a free model tier as a second reviewer
&lt;/h2&gt;

&lt;p&gt;Preflight catches mechanical rules, but it cannot notice that a diff touches a code path the rule file never anticipated. That is where a free model tier adds value, provided the review is constrained to the same rule file that the gate uses.&lt;/p&gt;

&lt;p&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode provides free model access and a free server option, and the workflow below uses the free model access tier for the two reading-heavy steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input A: RULES (the .contrib-rules.yml content)
Input B: DIFF (unified diff, no unrelated files)

List every rule from RULES that the diff may violate.
For each candidate, output: rule path, evidence line from the diff, confidence (low/medium/high),
and the exact question a human must answer.
Do not suggest preferences that are absent from RULES.
If no rule applies, return the single line: no rule-based findings.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prompt is intentionally boring, because an unconstrained reviewer produces stylistic noise that costs more to triage than it saves. Every finding is a question for a human, never an automatic change request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the free server option fits
&lt;/h3&gt;

&lt;p&gt;Some projects cannot run their test suite on a contributor laptop, because the suite needs containers, services, or a long wall-clock budget. In those cases the free server option can host the preflight and test run, so the gate executes in a consistent environment instead of a laptop that happens to have the right toolchain.&lt;/p&gt;

&lt;p&gt;Availability limits, provisioning details, and whether the free tier covers a specific workload should be confirmed against the project's current documentation before a team depends on it. Treat the free path as a convenience for review and reproduction steps, not as a substitute for the project's own CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table: what to automate, what to keep human
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Delegate to a model?&lt;/th&gt;
&lt;th&gt;Human check required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Extract rules from CONTRIBUTING.md&lt;/td&gt;
&lt;td&gt;Yes, free tier is sufficient&lt;/td&gt;
&lt;td&gt;Every rule and its source line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch and file-naming checks&lt;/td&gt;
&lt;td&gt;No, run deterministically in preflight&lt;/td&gt;
&lt;td&gt;None beyond approving the rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test failure triage&lt;/td&gt;
&lt;td&gt;Yes, as a summarizer&lt;/td&gt;
&lt;td&gt;Reproduce the failure in a clean worktree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Writing the patch itself&lt;/td&gt;
&lt;td&gt;Optional, with a scoped prompt&lt;/td&gt;
&lt;td&gt;Full diff review plus test evidence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changelog and docs wording&lt;/td&gt;
&lt;td&gt;Yes, as a first draft&lt;/td&gt;
&lt;td&gt;Accuracy of version and behavior claims&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security-sensitive changes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Maintainer review and threat modeling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Final merge decision&lt;/td&gt;
&lt;td&gt;Never&lt;/td&gt;
&lt;td&gt;Maintainer, always&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Limitations and failure modes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rule extraction can misread a conditional sentence, so &lt;code&gt;needs_human&lt;/code&gt; markers matter more than tidy output.&lt;/li&gt;
&lt;li&gt;Model review produces confident false positives, and each one consumes maintainer attention.&lt;/li&gt;
&lt;li&gt;The rules file drifts from CONTRIBUTING.md unless a scheduled CI job re-extracts and diffs it.&lt;/li&gt;
&lt;li&gt;A preflight gate hides failures only if contributors remember to run it, so wire it into a pre-push hook rather than a wiki page.&lt;/li&gt;
&lt;li&gt;Free-tier availability is not a service guarantee, and long-running suites still need a fallback path.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who should skip this workflow
&lt;/h2&gt;

&lt;p&gt;Repositories that already expose one authoritative &lt;code&gt;make check&lt;/code&gt; target do not need a parallel gate, because the rules are already executable. Projects with strict supply-chain requirements should keep model-assisted review out of the loop entirely, since prompts can leak unreleased code. Single-maintainer projects with low contribution volume usually gain more from a shorter CONTRIBUTING.md than from automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short checklist before push
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Confirm which sentence in CONTRIBUTING.md each rule in the YAML file came from.&lt;/li&gt;
&lt;li&gt;Run the preflight script in a clean worktree, not in your editor's dirty tree.&lt;/li&gt;
&lt;li&gt;Restrict model review to rules that already exist, and convert every finding into a question.&lt;/li&gt;
&lt;li&gt;Re-extract the rules file when the underlying document changes, and review the diff.&lt;/li&gt;
&lt;li&gt;Revert any change that the gate cannot explain in one sentence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is not to automate contribution judgment; it is to stop paying review latency for rules that were written down months ago. Teams that want to try the free model access and free server path described above can evaluate it against their own repository rules before adopting any of it.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>testing</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Redact the Review Packet Before a Model Sees an OSS Failure Log</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Thu, 24 Sep 2026 19:24:40 +0000</pubDate>
      <link>https://dev.to/datars_7274/redact-the-review-packet-before-a-model-sees-an-oss-failure-log-1g8j</link>
      <guid>https://dev.to/datars_7274/redact-the-review-packet-before-a-model-sees-an-oss-failure-log-1g8j</guid>
      <description>&lt;p&gt;A small open-source patch often dies in review for reasons that never appear in the diff stat. A contributor copies a failing CI log into a chat box and asks a model to propose a fix. The log still holds a short-lived fixture token and an absolute path from the runner home directory. The returned diff also deletes a comment that explained why a locale-sensitive comparison had to stay explicit.&lt;/p&gt;

&lt;p&gt;The pull request then looks cleaner than the bug, and that kind of cleanliness is a poor form of progress. A maintainer can reject the change before anyone gives the new tests a careful and patient reading. The failure is a workflow problem, not a reason to ban careful model help on contributor patches. The durable order remains reproduce, isolate, patch, and test, using a packet the model is allowed to see.&lt;/p&gt;

&lt;p&gt;Free model access can critique that packet once the current quota and server terms are confirmed in the docs. The method stays useful for the reader even if every product name is removed from the article. Unverified allowance numbers stay labeled as outreach claims and are not treated as measured product facts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce before the model speaks
&lt;/h2&gt;

&lt;p&gt;The first artifact is a local reproducer that a stranger could run again from a clean checkout. A contributor checks out the default branch, records the commit, and runs the narrowest command that fails. Failure output lands in a scratch directory that the repository already ignores through its gitignore rules. Only after that file exists should anyone ask whether a model is able to interpret the failure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin
git switch &lt;span class="nt"&gt;--detach&lt;/span&gt; origin/main
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /tmp/oss-repro
git rev-parse HEAD &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/oss-repro/base.txt
&lt;span class="c"&gt;# Replace the test path with the failing target named in the issue.&lt;/span&gt;
pytest tests/test_locale_sort.py &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--tb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;short &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/oss-repro/fail.txt 2&amp;gt;&amp;amp;1
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/oss-repro/exit_code.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those commands illustrate a pattern, and they do not claim that the target repository actually uses pytest. The contributor still matches the project's documented test entry point before trusting the saved failure log. A model should not guess the runner from a README fragment pasted without the surrounding project config. If the documented command needs a service the laptop lacks, that gap is written down instead of invented away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a redacted review packet
&lt;/h2&gt;

&lt;p&gt;The second artifact is a short redaction script that strips obvious secrets and machine-specific local paths. The script below is a proposal, and it has not been executed against a real CI log for this draft. It stays small so a human can audit every substitution rule before the first local run. It will miss some secret shapes, and it should not be treated as a complete security scanner.&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;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Proposal: redact a local failure log before model review. Not executed here.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;RULES&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;(?i)(api[_-]?key|token|password|secret)\s*[:=]\s*\S+&lt;/span&gt;&lt;span class="sh"&gt;"&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;\1=&amp;lt;redacted&amp;gt;&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;/home/[^/\s]+&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;/home/&amp;lt;user&amp;gt;&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;/Users/[^/\s]+&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;/Users/&amp;lt;user&amp;gt;&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;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\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;&amp;lt;email&amp;gt;&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;redact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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;str&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;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repl&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;RULES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pattern&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="n"&gt;repl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&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;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;redact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A contributor reads the rules, runs the script against a copy, and then compares both files by eye. Lines that still show hostnames, customer identifiers, or signed URLs remain stored on the local disk. The packet allowed to leave holds the base commit, the exit code, the redacted traceback, and a human note.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 scripts/redact_log.py /tmp/oss-repro/fail.txt /tmp/oss-repro/fail.redacted.txt
diff &lt;span class="nt"&gt;-u&lt;/span&gt; /tmp/oss-repro/fail.txt /tmp/oss-repro/fail.redacted.txt | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What stays out of the packet
&lt;/h3&gt;

&lt;p&gt;Several items never belong in a hosted review session, even after a quick automated redaction pass. Raw environment dumps, private keys, and unpublished vulnerability notes all stay on the local machine. Screenshots of internal dashboards are also excluded, because extracted text can still hide live tokens. When the failure cannot be described without those materials, the contributor asks maintainers for a public fixture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lock comments that carry invariants
&lt;/h2&gt;

&lt;p&gt;Clear code often depends on a comment that a tidy automated rewrite will happily delete without asking. Recent public developer discussions have stressed that comments were never the real enemy of practical clarity. A note about a locale rule, a protocol quirk, or a security boundary belongs to the module contract. A model that prefers shorter functions will treat that note as clutter unless the packet forbids deletion.&lt;/p&gt;

&lt;p&gt;The contributor extracts those sentences into a lock file before anyone starts drafting the actual patch. Each anchor is a full sentence copied from the current source, not a paraphrase written for the model. Three or four anchors are enough for a focused bugfix that touches only a single small module. A change that needs dozens of locks is too wide for one session and should be split before review.&lt;/p&gt;

&lt;p&gt;A lock file can start as plain text, with one verbatim source sentence stored on each line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Copied verbatim from current source. Sample anchors only, not from a real repository.
Keep the comparison explicit because locale-aware sort order is not stable across runner images.
Do not cache the token beyond this function, because the fixture clock resets between tests.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Proposal check, run from the feature branch after the patch is applied locally.&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; anchor&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$anchor&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\#&lt;/span&gt;&lt;span class="k"&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="k"&gt;esac&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$anchor&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'missing invariant comment: %s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$anchor&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt; &amp;lt; /tmp/oss-repro/comment-locks.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The check uses exact text search, so a harmless rewording looks like a failure, which is the intended bias. The contributor restores the original sentence or asks the maintainer before changing the locked wording. A passing lock check does not prove the behavior is correct, and it only shows the chosen sentences survived.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask for a review, not an unscoped rewrite
&lt;/h2&gt;

&lt;p&gt;The prompt stays narrow once the redacted packet and the comment lock file both exist on disk. The human asks for risks, missing tests, and comment deletions, and does not request a whole-file replacement. A useful reply names a line range, a suspected behavior change, and a test that would expose that suspicion. A reply that rewrites unrelated functions is discarded, even when the surrounding prose sounds fully confident.&lt;/p&gt;

&lt;p&gt;Local commands remain authoritative after any accepted hunk is applied by hand in the working tree. The contributor reruns the original failing command, then one neighboring test target, and records both exit codes. A green result on a free remote server does not replace project CI, because images may differ from the matrix. Remote runs stay a first-pass convenience, and they are not evidence that the contributor patch is finished.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attach only the redacted log, the recorded base commit, and the comment-lock list to the model session.&lt;/li&gt;
&lt;li&gt;Require a risk list that includes a test idea, and reject any reply that edits project files on its own.&lt;/li&gt;
&lt;li&gt;Apply the accepted hunks manually, then rerun the original command together with one neighboring test target.&lt;/li&gt;
&lt;li&gt;Record the new exit codes in the pull request, and keep every redacted log file out of git history.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Decision table for where the work should run
&lt;/h2&gt;

&lt;p&gt;The following table routes work among the laptop, a free model review, and a free remote server option. It is a decision aid for contributors, and it is not a benchmark of speed, price, or model accuracy. Cells marked unsuitable mean the hosted step stays unused, not that a sharper prompt makes the upload safe. Contributors who want measurements should time their own repository rather than borrow numbers from this article.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Local machine&lt;/th&gt;
&lt;th&gt;Free model review&lt;/th&gt;
&lt;th&gt;Free remote server&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Log may contain a token or a home path&lt;/td&gt;
&lt;td&gt;Redact first, then decide&lt;/td&gt;
&lt;td&gt;Do not upload the raw log&lt;/td&gt;
&lt;td&gt;Do not upload the raw log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One-file logic bug with locked comments&lt;/td&gt;
&lt;td&gt;Reproduce and patch here&lt;/td&gt;
&lt;td&gt;Critique the diff and the locks&lt;/td&gt;
&lt;td&gt;Optional smoke test only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Needs a maintainer-only secret or private fixture&lt;/td&gt;
&lt;td&gt;Stop and ask maintainers&lt;/td&gt;
&lt;td&gt;Unsuitable&lt;/td&gt;
&lt;td&gt;Unsuitable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Touches public API, migrations, or security checks&lt;/td&gt;
&lt;td&gt;Write the behavior note locally&lt;/td&gt;
&lt;td&gt;Second opinion only&lt;/td&gt;
&lt;td&gt;Not sufficient evidence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suite needs services the laptop cannot start&lt;/td&gt;
&lt;td&gt;Record the gap in the note&lt;/td&gt;
&lt;td&gt;Explain the gap, invent nothing&lt;/td&gt;
&lt;td&gt;Use only if the image is documented&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Where a free assistant fits, without invented limits
&lt;/h2&gt;

&lt;p&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach.&lt;/p&gt;

&lt;p&gt;MonkeyCode enters this method as an open-source coding assistant only after the packet is redacted and comments are locked. Operator notes supplied with this draft describe free model access and a free server option for that bounded review. Those notes also mention a free token allowance on the order of ten million tokens for outreach readers. A plan that assumes a permanent quota will break the moment the published limits change without notice.&lt;/p&gt;

&lt;p&gt;This article does not treat that allowance, any model name, hardware shape, or server duration as a verified fact. No primary source dated 2026-09-25 was attached, so the figure stays an unverified operator claim. Readers should confirm the live offer in the current project documentation before planning a session around it. If the docs and the outreach notes disagree, the documentation wins and the notes should be ignored.&lt;/p&gt;

&lt;p&gt;A free model pass can list risks against the redacted packet when the docs still describe that access. A free server can host a smoke run only when the current docs offer an image that matches the task. Neither option should ever receive raw CI logs, private keys, customer fixtures, or unpublished security reports. Readers who never open the project can still keep the script, the lock file, and the routing table.&lt;/p&gt;

&lt;p&gt;One practical follow-up is to place this packet layout beside the current MonkeyCode docs and compare coverage. The comparison should ask whether the free options cover a single redacted review, not an entire migration. That check belongs to the contributor, and it should happen before any log leaves the laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;The sample rules miss multiline secrets, encoded blobs, and tokens that lack a familiar key name nearby. An exact comment lock fails closed when a later commit has already reworded the invariant in place. A model can still invent a test path the repository does not contain, so exit codes must come from local commands. Free access can shrink, change models, or end without notice, which makes a fixed-quota plan fragile from the start.&lt;/p&gt;

&lt;p&gt;This draft records no timings, no accuracy scores, and no claim that a hosted run matches maintainer CI images. The redaction script can also over-redact and hide the very path segment a reviewer needed to see. Human review of the diff between raw and redacted logs is mandatory, and it cannot be skipped for speed. A workflow this small will not catch a wrong bug theory that happens to leave every locked comment intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this workflow
&lt;/h2&gt;

&lt;p&gt;Teams handling production credentials, medical records, or unpublished vulnerability details should not upload those failure logs. Maintainers who require a contributor agreement before any external processing should enforce that policy before upload. Contributors who cannot yet run the documented tests locally should close that gap before asking a model for help. A wide refactor is a poor fit, because a short lock list cannot describe every behavior change on the branch.&lt;/p&gt;

&lt;p&gt;The habit that survives a rejected suggestion is smaller and older than any particular assistant product. Reproduce the failure, redact the evidence, lock the comments that carry invariants, and let the project tests decide. A free review pass can sit beside that habit, and it never replaces the maintainer who must still read the diff.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>git</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>Freeze User-Visible Strings Before an OSS Patch Hits Review</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Wed, 23 Sep 2026 16:17:23 +0000</pubDate>
      <link>https://dev.to/datars_7274/freeze-user-visible-strings-before-an-oss-patch-hits-review-308d</link>
      <guid>https://dev.to/datars_7274/freeze-user-visible-strings-before-an-oss-patch-hits-review-308d</guid>
      <description>&lt;p&gt;A mid-size command-line library accepted a one-line error-message change on an otherwise quiet Thursday afternoon. The contributor had reproduced a confusing parser failure, corrected the branch, and then rewrote the printed message for newcomers. Local unit tests stayed green because they asserted exception classes rather than the exact printed text. Two days later a packaging script that grepped the old phrase failed inside a downstream nightly job.&lt;/p&gt;

&lt;p&gt;Maintainers meet this pattern often enough that it no longer reads as a harmless wording nit. Scripts, runbooks, support macros, and tutorial snippets treat error text, log lines, and CLI help as shipped contracts. A coding model asked to improve clarity will rewrite those strings unless the contribution process freezes them first. The rest of this article records a ledger workflow that keeps that freeze explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why string drift survives green tests
&lt;/h2&gt;

&lt;p&gt;Most OSS suites protect control flow rather than the exact bytes that leave the process. Assertions check status codes, exception types, and structured fields, while the human-readable remainder stays unpinned. Formatters and AI review passes then treat that remainder as commentary instead of interface. That is how a correct parser fix still breaks a downstream nightly job.&lt;/p&gt;

&lt;p&gt;Treat three classes of text as user-visible until a maintainer writes otherwise in review notes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Error messages and panic text that operators may grep during an incident&lt;/li&gt;
&lt;li&gt;Log lines that on-call documents quote inside runbooks and playbooks&lt;/li&gt;
&lt;li&gt;CLI help, flag names, and usage examples rendered by &lt;code&gt;--help&lt;/code&gt; output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documentation headings can move without a migration window in most projects. Previously shipped messages and wire-format names should not move without an explicit note.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce, inventory, patch, then review
&lt;/h2&gt;

&lt;p&gt;The sequence below assumes a clean local checkout of the upstream default branch. It does not require one language, though the sample helper is Python. Each stage produces a file that later stages can check. The model pass, if used at all, only compares those files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reproduce on a throwaway worktree
&lt;/h3&gt;

&lt;p&gt;Create an isolated worktree so the inventory never mixes with unrelated dirty files. Fetch the default branch before copying so the ledger compares against current upstream text. Run the original failing command and keep stderr outside the repository tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin
git worktree add /tmp/oss-string-freeze origin/main
&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp/oss-string-freeze
python &lt;span class="nt"&gt;-m&lt;/span&gt; pytest tests/test_parser.py &lt;span class="nt"&gt;-k&lt;/span&gt; bad_timestamp &lt;span class="nt"&gt;-vv&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; app.cli parse broken.json 2&amp;gt; /tmp/before.err &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The worktree is disposable after the patch lands. The stderr capture is evidence, not product code, and should stay uncommitted. If the project uses fixtures rather than a CLI, dump the raised message with the same redirect pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build a string ledger from the intended diff
&lt;/h3&gt;

&lt;p&gt;After a candidate patch exists on a branch, extract added and removed quoted strings instead of reading the diff as prose. Exclude vendored trees and snapshot files so generated noise does not flood the ledger. The helper below is a starting point, not a parser for every language.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff origin/main...HEAD &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;':!vendor'&lt;/span&gt; &lt;span class="s1"&gt;':!*.snap'&lt;/span&gt; &lt;span class="s1"&gt;':!po/*.po'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/patch.diff
python3 extract_strings.py origin/main &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; STRING_LEDGER.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Extract added and removed quoted strings from git diff.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="n"&gt;STRING_RE&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;[&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;\']{8,})[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\']&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;diff_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cmd&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;git&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;diff&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;-U0&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...HEAD&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;--&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;:!vendor&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;:!*.snap&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="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;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;origin/main&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;diff_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&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;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+++&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STRING_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;removed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STRING_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;# String ledger&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;## Removed&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;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromkeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;removed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;## Added&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;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromkeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Classify every removed line as &lt;code&gt;freeze&lt;/code&gt;, &lt;code&gt;migrate&lt;/code&gt;, or &lt;code&gt;accident&lt;/code&gt; in the same file. Search the default branch for each removed string so the class is based on callers, not taste.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"invalid timestamp in input"&lt;/span&gt; origin/main &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;':!tests'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

| String | Direction | Class | Notes |
| --- | --- | --- | --- |
| invalid timestamp in input | removed | migrate | keep old text for one minor release |
| cannot parse timestamp: expected RFC3339 | added | new | document in CHANGELOG |
| debug dump written to /tmp | added | accident | drop before review |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;freeze&lt;/code&gt; class means the patch must restore the old bytes before review. A &lt;code&gt;migrate&lt;/code&gt; class requires a changelog bullet and, when possible, a dual-message window. An &lt;code&gt;accident&lt;/code&gt; class is text the author or an assistant introduced without a product reason.&lt;/p&gt;

&lt;h3&gt;
  
  
  Patch against the ledger, not against taste
&lt;/h3&gt;

&lt;p&gt;Apply the functional fix first and only then decide whether any user-visible string must change. If a message is false because the behavior was false, keep the old wording when downstream parsers depend on it. Ship both sentences for one release when the project already has a deprecation policy.&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;# Proposal: dual-message window, not a silent rewrite.
# Leave unexecuted until the project agrees on deprecation policy.
&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ParserError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invalid timestamp in input; expected RFC3339&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;Label dual-message examples as proposals when the repository has no published deprecation policy. Do not let a model pick the friendlier sentence as a default. Restore any &lt;code&gt;accident&lt;/code&gt; lines by deleting them from the working tree before the next test run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test the ledger, then the original behavior
&lt;/h3&gt;

&lt;p&gt;Add a cheap presence check so frozen strings still appear in source. This is not a localization framework and does not parse format strings. It only stops an accidental rewrite from riding along with a logic fix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tests/test_string_ledger.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;FROZEN&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;invalid timestamp in input&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;test_frozen_strings_still_present&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;rglob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;joined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;FROZEN&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;joined&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the ledger test before the original reproducer so a wording regression fails first. Capture stderr again and compare it with the file from the worktree setup. If the wording diff includes a &lt;code&gt;freeze&lt;/code&gt; class string, restore those bytes before any review pass.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pytest tests/test_string_ledger.py tests/test_parser.py &lt;span class="nt"&gt;-vv&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; app.cli parse broken.json 2&amp;gt; /tmp/after.err &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;diff &lt;span class="nt"&gt;-u&lt;/span&gt; /tmp/before.err /tmp/after.err &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compare the ledger with the diff on a free model
&lt;/h3&gt;

&lt;p&gt;This is the only stage where a coding model should enter the loop. The task is comparison, not rewrite, and the prompt should forbid wording suggestions. Paste &lt;code&gt;git diff origin/main...HEAD&lt;/code&gt; together with &lt;code&gt;STRING_LEDGER.md&lt;/code&gt; and ask for omissions only.&lt;/p&gt;

&lt;p&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach. Contributors who already build this inventory locally can send the ledger and the diff through MonkeyCode's free model access, and can use the free server option when that comparison should run off the laptop. The model exists to catch table omissions, not to invent clearer error text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are comparing STRING_LEDGER.md with the unified diff.
List: (1) added or removed quoted strings in the diff that lack a ledger row,
(2) ledger rows whose text does not appear in the diff,
(3) any freeze row whose old bytes are still missing from the tree.
Do not suggest wording improvements. Do not rewrite the patch.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the model reports extra strings, update the ledger or revert the extra edits. If it reports none, the patch can go to a human maintainer, who still owns tone and deprecation policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table for string classes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;When to use it&lt;/th&gt;
&lt;th&gt;Required artifact&lt;/th&gt;
&lt;th&gt;Ready for review&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;freeze&lt;/td&gt;
&lt;td&gt;Downstream scripts or docs quote the exact bytes&lt;/td&gt;
&lt;td&gt;ledger row plus presence test&lt;/td&gt;
&lt;td&gt;old string still in the tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;migrate&lt;/td&gt;
&lt;td&gt;Behavior change makes the old sentence false&lt;/td&gt;
&lt;td&gt;ledger row plus changelog bullet&lt;/td&gt;
&lt;td&gt;old and new text both documented&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;Entirely new failure mode or help flag&lt;/td&gt;
&lt;td&gt;ledger row only&lt;/td&gt;
&lt;td&gt;no removed twin hiding nearby&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;accident&lt;/td&gt;
&lt;td&gt;Debug dumps, speculative help, assistant asides&lt;/td&gt;
&lt;td&gt;none; delete the text&lt;/td&gt;
&lt;td&gt;gone from &lt;code&gt;git diff&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use the table as a gate, not as a style guide. A patch that still contains an &lt;code&gt;accident&lt;/code&gt; row is not ready, even when tests are green. A &lt;code&gt;migrate&lt;/code&gt; row without a changelog bullet is also not ready, because downstream authors will not learn the new bytes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;Quoted-string extraction misses template literals, concatenated fragments, and gettext catalogs. Dynamic messages built from several pieces will under-count, so the ledger is a net rather than a proof. Generated code, vendored files, and snapshot fixtures can flood the report unless those paths are excluded from &lt;code&gt;git diff&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Projects that localize every user-facing sentence should run this workflow against message catalogs rather than source literals. Security advisories sometimes must change an error to avoid leaking internals, and those patches should skip the freeze class. A hosted model will not know the deprecation policy unless that policy is pasted beside the ledger.&lt;/p&gt;

&lt;p&gt;The free model pass does not replace the local worktree, the presence test, or maintainer judgment. No duration, quota, hardware size, or model name is implied by using a free server for the comparison. Teams that need a guarantee against string drift still have to keep the presence test in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this approach
&lt;/h2&gt;

&lt;p&gt;Drive-by typo fixes in comments do not need a ledger or a model pass. Embargoed security patches should not paste diffs into any hosted model, even for a string comparison. Repositories without a shipped CLI, log contract, or scriptable error text will spend more time classifying strings than they will save in review.&lt;/p&gt;

&lt;p&gt;Authors who cannot run the original reproducer locally should not certify that user-visible output is stable. The extra file exists to keep taste out of the first review pass, not to freeze language forever. Maintainers can still improve wording after the functional fix lands, and they should do that in a dedicated docs change.&lt;/p&gt;

&lt;p&gt;Contributors who already keep a worktree and a ledger can run the comparison on MonkeyCode's free models when they want a second pass on the table.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>git</category>
      <category>ai</category>
    </item>
    <item>
      <title>Match the Repo Test Dialect Before an OSS Patch Leaves the Fork</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Tue, 22 Sep 2026 14:34:17 +0000</pubDate>
      <link>https://dev.to/datars_7274/match-the-repo-test-dialect-before-an-oss-patch-leaves-the-fork-434l</link>
      <guid>https://dev.to/datars_7274/match-the-repo-test-dialect-before-an-oss-patch-leaves-the-fork-434l</guid>
      <description>&lt;p&gt;A first-time contributor cloned a popular HTTP client on a Sunday evening and reproduced a timeout bug. The crash appeared only when a redirect chain mixed HTTP/2 frames with a stale connection pool. The patch looked small in the editor, yet the project's CI matrix covered three language versions and two TLS backends. Maintainers bounced the pull request because the new test used a helper name that did not exist in the suite.&lt;/p&gt;

&lt;p&gt;This composite scene shows up in public trackers even when the functional fix itself is technically correct. Reviewers then spend scarce maintainer time teaching house style instead of judging the intended behavior change. A merge packet that freezes the failing assertion, shadows the upstream job, and checks dialect cuts that extra round trip. The workflow treats a free coding model as a dialect reviewer rather than as the author of production code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why dialect mismatches stall otherwise valid patches
&lt;/h2&gt;

&lt;p&gt;Open-source test suites accumulate local verbs, fixture factories, and assertion helpers that never appear in tutorials. A new file that imports unittest mock patterns into a pytest house, or the reverse, reads like a drive-by rewrite. Continuous integration then fails on collection errors long before it can exercise the regression the patch claims to close. Maintainers reasonably ask for a rewrite because they cannot tell a real fix from a second coding style landing in tree.&lt;/p&gt;

&lt;p&gt;House dialect is not the same thing as clean code in the abstract. Neighboring tests already show how the project fakes time, sockets, clocks, and HTTP backends. Copying that local grammar keeps the review focused on behavior instead of on renaming helpers under discussion. The fork should learn that grammar before any model is invited to comment on the diff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a merge packet on the fork
&lt;/h2&gt;

&lt;p&gt;The packet is a small directory that travels beside the branch and survives a clean clone of the public fork. It stores a frozen assertion, a CI test selector, a dialect sample, and the rebased candidate diff. Maintainers can replay those files after checkout without reconstructing the original laptop or the container image. The same packet is the only context a free model should receive during a later dialect review pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  Packet layout
&lt;/h3&gt;

&lt;p&gt;Place the files under &lt;code&gt;.merge-packet/&lt;/code&gt; and keep them untracked or tracked, according to the project's ignore rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;assertion.lock&lt;/code&gt; — failing node id, exact assertion text, and captured at SHA&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selector.txt&lt;/code&gt; — the CI test command copied from the workflow or Makefile&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;base.sha&lt;/code&gt; — default-branch commit that the selector was last proven against&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dialect_sample.md&lt;/code&gt; — excerpts from three nearby tests, with repository paths&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;patch.diff&lt;/code&gt; — behavior change plus matching test, rebased onto the default branch&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;review_checklist.md&lt;/code&gt; — allowed dialect findings, isolation notes, and rollback path&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 — Freeze one assertion, not the entire CI log
&lt;/h2&gt;

&lt;p&gt;Contributors should copy the failing node id and the exact assertion text into &lt;code&gt;assertion.lock&lt;/code&gt; before editing production files. Full logs mix compiler warnings, retry noise, and unrelated suite failures that hide the contract under review. A frozen message becomes the oracle that later tests must fail before the patch and pass after the patch. If the suite cannot address that node in isolation, the contribution is not ready for a model-assisted review.&lt;/p&gt;

&lt;p&gt;The following file is a template, not a capture from a live upstream run:&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="c1"&gt;# .merge-packet/assertion.lock&lt;/span&gt;
&lt;span class="c1"&gt;# Template only — replace with values from the local failing node.&lt;/span&gt;
&lt;span class="na"&gt;node_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tests/client/test_redirects.py::test_timeout_on_stale_pool&lt;/span&gt;
&lt;span class="na"&gt;assertion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;AssertionError: expected ReadTimeout after stale HTTP/2 pool reuse,&lt;/span&gt;
  &lt;span class="s"&gt;got 200 from redirected origin&lt;/span&gt;
&lt;span class="na"&gt;captured_at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-09-22T00:00:00Z&lt;/span&gt;
&lt;span class="na"&gt;notes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Fail this node on the default branch before applying patch.diff.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Pass this node on the branch after patch.diff lands.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2 — Copy the upstream selector from the workflow file
&lt;/h2&gt;

&lt;p&gt;Most projects already declare the test command inside GitHub Actions, GitLab CI, or a Makefile target. The fork should run that same selector rather than a personal pytest invocation with extra flags and random markers. Shadowing the job catches missing extras, skipped markers, and environment variables that never appear in README snippets. The selector belongs in &lt;code&gt;selector.txt&lt;/code&gt; so a reviewer can see the exact command without opening the workflow history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# .merge-packet/shadow_ci.sh&lt;/span&gt;
&lt;span class="c"&gt;# Template only — not executed against a live upstream in this article.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--show-toplevel&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;PACKET&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;ROOT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.merge-packet"&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

git rev-parse HEAD &lt;span class="o"&gt;&amp;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;PACKET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/head.sha"&lt;/span&gt;
&lt;span class="nv"&gt;BASE&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;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'\r'&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PACKET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/base.sha"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"shadowing selector against recorded base &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;SELECTOR&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;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'\r'&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PACKET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/selector.txt"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# Example selector.txt line:&lt;/span&gt;
&lt;span class="c"&gt;# PYTHONPATH=src pytest tests/client/test_redirects.py::test_timeout_on_stale_pool -q&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SELECTOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record the default-branch SHA before the first shadow run so later rebases have a comparison point. A green run against an unknown base does not prove that upstream collection will accept the new module path. Contributors should refresh &lt;code&gt;base.sha&lt;/code&gt; whenever they merge or rebase onto the project's default branch. The packet then shows reviewers which tree the selector last executed against.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Sample three nearby tests as the dialect source
&lt;/h2&gt;

&lt;p&gt;Dialect is easier to copy from neighboring files than from a style guide that the repository never actually follows. The sample should include fixture names, assertion helpers, time control, and how the suite talks to the network. Three files are enough to show repeated patterns without dumping the entire tests directory into a prompt window. A short extractor can print imports and assertion calls so the sample stays mechanical instead of hand-wavy.&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;# .merge-packet/extract_dialect.py
# Template only — unexecuted example for pytest-like suites.
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;MARKERS&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;assert&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;pytest&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;fixture&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;monkeypatch&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;responses&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;respx&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;freezegun&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;httpx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;asserts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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;=&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;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&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;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ImportFrom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;from &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; import ...&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;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;asserts&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="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_source_segment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assert ...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;kept_imports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;imports&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;MARKERS&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&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;## &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_posix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;### imports&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;kept_imports&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="n"&gt;lines&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;### assertions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;asserts&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="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;neighbors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tests/client/test_redirects.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tests/client/test_pool.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tests/client/test_timeouts.py&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="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.merge-packet/dialect_sample.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&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;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;neighbors&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose neighbors by directory, not by popularity of the helper names. A timeout bug in the HTTP client should sample other client tests rather than unrelated CLI snapshot tests. Generated golden files are a weak dialect source because they hide the assertions that humans actually review. If the suite is generated, freeze one generated output and say so inside &lt;code&gt;dialect_sample.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Isolate the patch from drive-by refactors
&lt;/h2&gt;

&lt;p&gt;Reviewers reject mixed diffs that reformat imports, rename locals, and fix the bug inside a single commit. The candidate &lt;code&gt;patch.diff&lt;/code&gt; should contain the behavior change and the matching test, rebased onto the default branch. Formatting and comment cleanups belong in a follow-up issue if the project even wants them at all. Isolation makes the dialect review cheaper because the model is not asked to judge unrelated churn.&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;# Template only — produce a reviewable diff after tests match dialect.&lt;/span&gt;
git fetch origin
git rebase origin/main
git diff origin/main...HEAD &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;':!.merge-packet'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .merge-packet/patch.diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test added for the frozen assertion should sit next to those three neighbor files. New support helpers need a name already used in the sample, or a short note explaining why a new helper is required. Private modules that neighboring tests never import should stay out of the new file. That rule prevents the patch from widening the public test surface by accident.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Run a dialect review on free model access
&lt;/h2&gt;

&lt;p&gt;A contributor who already uses MonkeyCode can run the dialect review through free model access and the free server option. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The model should receive the merge packet only, not a dump of unrelated files from the working tree. Human maintainers remain the merge authority, and the model output is a checklist of dialect mismatches.&lt;/p&gt;

&lt;p&gt;The prompt below is a labeled template. It asks for findings, not for a rewritten production patch, and it forbids inventing helpers that the sample does not contain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are reviewing an OSS merge packet for test dialect only.
Read assertion.lock, selector.txt, dialect_sample.md, and patch.diff.
Do not invent fixtures, helpers, or modules that dialect_sample.md does not show.
Return markdown with these headings only:
1. Dialect mismatches (file:line, nearby pattern, required change)
2. Isolation issues (drive-by refactors, unrelated renames)
3. Oracle check (does the new test target assertion.lock?)
4. Rollback note (how to revert without leaving the new helper)
If evidence is missing, say "unknown" instead of guessing house style.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allowed findings stay narrow so the human can apply them without a second design debate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unknown helper or fixture name that the sample never uses.&lt;/li&gt;
&lt;li&gt;Wrong fixture scope, including function versus module setup that neighbors avoid.&lt;/li&gt;
&lt;li&gt;Real network calls where neighboring tests fake HTTP, TLS, or DNS.&lt;/li&gt;
&lt;li&gt;Test file location that does not match the package layout in the sample.&lt;/li&gt;
&lt;li&gt;Assertion style drift, such as raw &lt;code&gt;==&lt;/code&gt; where the house wraps &lt;code&gt;pytest.raises&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Replay the packet after every rebase
&lt;/h2&gt;

&lt;p&gt;Rebases rewrite context lines, so the frozen assertion and the shadowed selector must run again after each rebase. A green local run against an old default branch is not evidence that upstream CI will collect the new test. The packet should record the default-branch SHA beside the selector so reviewers can see the exact base. If the assertion text drifts after rebase, the oracle is stale and the contributor must freeze a new message.&lt;/p&gt;

&lt;p&gt;Store a short replay log next to the selector rather than pasting terminal color codes into the pull request. One passing line and one failing line, taken from the isolated node, are enough evidence for most maintainers. Timestamp the replay against &lt;code&gt;base.sha&lt;/code&gt; so later comments do not argue about an obsolete tree. The pull request body can link the packet path instead of embedding a screenshot of an entire CI log.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal on the fork&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Stop the PR if&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frozen assertion missing&lt;/td&gt;
&lt;td&gt;Capture node id before editing production files&lt;/td&gt;
&lt;td&gt;The suite cannot isolate the node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Selector differs from CI&lt;/td&gt;
&lt;td&gt;Copy the command from the workflow file&lt;/td&gt;
&lt;td&gt;The job needs secrets or private images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dialect sample empty&lt;/td&gt;
&lt;td&gt;Extract three neighbor tests&lt;/td&gt;
&lt;td&gt;Tests are generated and have no assertions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diff includes rename or format-only hunks&lt;/td&gt;
&lt;td&gt;Split commits and regenerate &lt;code&gt;patch.diff&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The bugfix cannot be rebased alone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model flags a helper mismatch&lt;/td&gt;
&lt;td&gt;Rewrite the test to match &lt;code&gt;dialect_sample.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Production code needs an API redesign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oracle still fails after the patch&lt;/td&gt;
&lt;td&gt;Do not open the pull request&lt;/td&gt;
&lt;td&gt;The frozen message no longer matches reality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;The workflow does not replace a maintainer reading the production change or checking license headers and security notes. Free model access can miss project-specific macros, generated fixtures, or custom pytest plugins that a sample will under-represent. Shadowing CI still fails when the upstream job needs secrets, hardware, or proprietary containers the fork cannot reproduce. None of the commands above were executed against a live upstream repository for this article, so treat them as templates.&lt;/p&gt;

&lt;p&gt;Model review also cannot certify performance, licensing, or ABI promises. A dialect match only says the new test looks like the house, not that the patch is the right architectural change. Contributors still need the project's contributing guide, code of conduct, and any required test matrix beyond the single frozen node. Treat model output as a pre-submit lint for tests, not as a substitute for maintainer judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One-line documentation or typo pull requests with no test change.&lt;/li&gt;
&lt;li&gt;Embargoed security fixes that must not land on a shared public server.&lt;/li&gt;
&lt;li&gt;Changes that require proprietary hardware, licensed protocol dumps, or private containers.&lt;/li&gt;
&lt;li&gt;Repositories that already enforce dialect with formatters, custom linters, and coverage gates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contributors sending one-line documentation fixes do not need a merge packet or a model review loop. Embargoed security patches should stay off public free servers until the project's disclosure process is complete. Newcomers who cannot run the upstream selector locally should ask for a repro harness instead of guessing dialect from chat. Teams that already enforce dialect with linters and coverage gates can keep those tools and skip the model pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the oracle and the selector even without a model
&lt;/h2&gt;

&lt;p&gt;The Sunday bounce was not about intelligence or effort; it was about landing a foreign test dialect in a living suite. A frozen assertion, a shadowed CI selector, and a three-file dialect sample give maintainers something they can replay. The merge packet remains useful if every model mention is removed, because the oracle and the selector are the artifacts. Readers who already have free model access nearby can run the dialect checklist there and still keep humans as the merge gate.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>Ship an OSS Patch With a Reviewer Question Bank, Not Just a Diff</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Mon, 21 Sep 2026 12:46:43 +0000</pubDate>
      <link>https://dev.to/datars_7274/ship-an-oss-patch-with-a-reviewer-question-bank-not-just-a-diff-3ag0</link>
      <guid>https://dev.to/datars_7274/ship-an-oss-patch-with-a-reviewer-question-bank-not-just-a-diff-3ag0</guid>
      <description>&lt;p&gt;A maintainer opened the crash-fix pull request after a long triage shift and found a three-line diff with no reproduction notes. The commit message claimed the parser no longer panicked, yet the issue still lacked a failing command for a clean checkout. Review time vanished into guesswork about callers, error paths, and whether the public API still returned the same sentinel values. The tab closed, and the contributor waited three days for a review that never started.&lt;/p&gt;

&lt;p&gt;That stall is rarely about missing brilliance in the patch, and it is almost never about git hygiene alone. Maintainers ration attention across many repositories, and an unexplained diff is expensive even when the change is correct. Contributors who used a coding model to draft the hunks often ship fluent code that still fails the social contract of review. The missing artifact is not more commentary in the PR template; it is a question bank the contributor already answered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unexplained diffs stall because review is interrogation
&lt;/h2&gt;

&lt;p&gt;Open-source review is a time-boxed interrogation, not a rubber stamp on a green CI badge. A careful reviewer still needs the reproduction, the moved public symbols, and the error paths that must keep failing. Those demands appear whether or not the contributor writes them down in advance of the request. Writing them first turns the pull request into evidence instead of a riddle wrapped in a unified diff.&lt;/p&gt;

&lt;p&gt;Most contribution templates ask for a summary, a test plan, and a checklist of boxes. Those boxes age into ritual, and they do not change when the diff touches an exported error type. A question bank is generated from this branch's paths, headers, and exit codes, so the questions track the patch. The template in &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; can stay generic while the bank stays specific to the branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The artifact: REVIEWER_QUESTIONS.md
&lt;/h2&gt;

&lt;p&gt;The proposed artifact is a single Markdown file named &lt;code&gt;REVIEWER_QUESTIONS.md&lt;/code&gt; that lives beside the patch branch. Each entry is a maintainer question, a required evidence pointer, and a short answer that cites a file and line. Unanswered items remain marked &lt;code&gt;TODO&lt;/code&gt; so a local gate can refuse to open the pull request. The file is not a blog post and should stay short enough to read in about twelve minutes.&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;# Reviewer Question Bank&lt;/span&gt;

Project: example-parser
Issue: https://github.com/example/parser/issues/1842
Branch: fix/issue-1842
Base: origin/main

&lt;span class="gu"&gt;## Q1. Reproduction&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: What single command fails on a clean checkout of main and passes on this branch?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: TODO
&lt;span class="p"&gt;-&lt;/span&gt; Answer: TODO

&lt;span class="gu"&gt;## Q2. Public surface&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: Which exported symbols changed name, type, or error contract?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: TODO
&lt;span class="p"&gt;-&lt;/span&gt; Answer: TODO

&lt;span class="gu"&gt;## Q3. Negative path&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: Which input must still fail, and what exit code is preserved?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: TODO
&lt;span class="p"&gt;-&lt;/span&gt; Answer: TODO

&lt;span class="gu"&gt;## Q4. Regression test&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: Where is the test that would have failed before the patch?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: TODO
&lt;span class="p"&gt;-&lt;/span&gt; Answer: TODO

&lt;span class="gu"&gt;## Q5. Commit shape&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: Does each commit encode one logical change a revert could isolate?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: TODO
&lt;span class="p"&gt;-&lt;/span&gt; Answer: TODO

&lt;span class="gu"&gt;## Q6. Docs and changelog&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: What user-visible behavior needs a changelog note, or why is none required?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: TODO
&lt;span class="p"&gt;-&lt;/span&gt; Answer: TODO
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Six steps from a failing command to a fail-closed gate
&lt;/h2&gt;

&lt;p&gt;The following workflow is a proposed local checklist, and the commands are illustrative rather than a recorded run against a public crate. Contributors should swap the binary names, fixture paths, and test runners for the project under patch. The point of the checklist is the review packet rather than any particular language or CI toolchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Freeze the failing command
&lt;/h3&gt;

&lt;p&gt;Before any edit, record one command that fails on a clean checkout of the upstream default branch. Store that command in the question bank under reproduction so later answers cannot drift into a private setup. If the crash needs a fixture, check the fixture into the branch rather than describing it in prose. Reviewers should be able to paste the command without guessing at environment variables or hidden data files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin
git switch &lt;span class="nt"&gt;-c&lt;/span&gt; fix/issue-1842 origin/main
&lt;span class="c"&gt;# Proposed: capture the failing invocation, not a narrative.&lt;/span&gt;
./target/debug/tool parse tests/fixtures/issue-1842.json
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"expected non-zero on main"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Keep every hunk load-bearing
&lt;/h3&gt;

&lt;p&gt;Edit only the symbols required to make that command pass, and resist drive-by cleanups that enlarge the review surface. A question bank cannot rescue a diff that also reformats a neighboring module or renames an unrelated helper. Split formatting and refactors into separate pull requests if the project will accept them at all. The bank should list every touched path so a maintainer can see the blast without running extra git archaeology.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; origin/main...HEAD
git diff &lt;span class="nt"&gt;--stat&lt;/span&gt; origin/main...HEAD
git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; origin/main..HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Collect exit codes instead of vibe screenshots
&lt;/h3&gt;

&lt;p&gt;Run the original failing command, the nearest unit tests, and one negative path that should still error after the fix. Capture the exit codes and a one-line summary rather than pasting entire logs into the pull request body. The question bank needs those exit codes as answers, not as decorative terminal screenshots that hide the command. Label any unexecuted matrix as proposed so a maintainer does not treat a wish as a result.&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;# Proposed local evidence, not a claimed CI run.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; +e
./target/debug/tool parse tests/fixtures/issue-1842.json
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"repro_exit=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
cargo &lt;span class="nb"&gt;test &lt;/span&gt;parse_issue_1842 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--nocapture&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"unit_exit=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
./target/debug/tool parse tests/fixtures/truncated.json
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"negative_exit=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Pack the diff and draft questions
&lt;/h3&gt;

&lt;p&gt;A coding model can draft questions from the unified diff, but it cannot invent evidence the tests never produced. Feed the model the diff, the test commands, and the project's CONTRIBUTING snippet, then keep only questions a human can answer with citations.&lt;/p&gt;

&lt;p&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode's free model access can draft the bank from a unified diff, and the free server option can run the recorded test commands.&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;# Proposed helper: pack a small context bundle for a coding model.&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .review-packet
git diff origin/main...HEAD &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .review-packet/patch.diff
git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; origin/main..HEAD &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .review-packet/commits.txt
git diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; origin/main...HEAD &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .review-packet/paths.txt
python3 scripts/list_fn_headers.py &amp;lt; .review-packet/patch.diff &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .review-packet/headers.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Proposed helper: list added and removed fn headers from a unified diff.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+++&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fn &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;added&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="n"&gt;raw&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="nf"&gt;rstrip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fn &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;removed&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="n"&gt;raw&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="nf"&gt;rstrip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;## Removed headers&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;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;removed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- `&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="si"&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;## Added headers&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;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- `&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;`&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Proposed prompt for the drafting pass, to be edited by a human before any answer is trusted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are drafting reviewer questions for an OSS patch, not writing the patch.
Read patch.diff, headers.md, and commits.txt.
Propose at most eight questions a maintainer would ask before merging.
Reject style nits. Prefer reproduction, public surface, negative paths,
tests, commit shape, and changelog impact.
Do not invent test results. Leave every Answer and Evidence as TODO.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Fill answers with file:line citations
&lt;/h3&gt;

&lt;p&gt;Each answer should be one or two sentences and must point at a path a reviewer can open. Saying tests pass is not an answer, because it hides which command and which assertion moved. If the model drafted a question the tests cannot answer, delete the question instead of fabricating a citation. A short honest bank beats a long bank that launders missing evidence behind confident, fluent prose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Q1. Reproduction&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: What single command fails on a clean checkout of main and passes on this branch?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: tests/fixtures/issue-1842.json, src/parse.rs:214
&lt;span class="p"&gt;-&lt;/span&gt; Answer: &lt;span class="sb"&gt;`./target/debug/tool parse tests/fixtures/issue-1842.json`&lt;/span&gt; exited 101 on main and 0 on HEAD.

&lt;span class="gu"&gt;## Q2. Public surface&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: Which exported symbols changed name, type, or error contract?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: src/lib.rs:88 (still &lt;span class="sb"&gt;`pub fn parse`&lt;/span&gt;)
&lt;span class="p"&gt;-&lt;/span&gt; Answer: No exported name changed; &lt;span class="sb"&gt;`parse`&lt;/span&gt; still returns &lt;span class="sb"&gt;`Result&amp;lt;Doc, ParseError&amp;gt;`&lt;/span&gt;.

&lt;span class="gu"&gt;## Q3. Negative path&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Question: Which input must still fail, and what exit code is preserved?
&lt;span class="p"&gt;-&lt;/span&gt; Evidence: tests/fixtures/truncated.json, src/parse.rs:240
&lt;span class="p"&gt;-&lt;/span&gt; Answer: Truncated input still exits 1 with &lt;span class="sb"&gt;`ParseError::UnexpectedEof`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Refuse to open the pull request while TODO remains
&lt;/h3&gt;

&lt;p&gt;A local gate keeps the social contract from depending on memory when the pull request is finally opened. The script below is proposed, and it only searches for the TODO markers the template uses. Contributors can wire it as a pre-push hook or as a make target named &lt;code&gt;review-packet&lt;/code&gt;. Opening the pull request then becomes a copy of the bank into the PR body, not a second writing task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# Proposed gate: refuse to open a PR while the bank still has TODO answers.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nv"&gt;BANK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"REVIEWER_QUESTIONS.md"&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="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BANK&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"missing &lt;/span&gt;&lt;span class="nv"&gt;$BANK&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="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi
if &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;'^- (Answer|Evidence): TODO'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BANK&lt;/span&gt;&lt;span class="s2"&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"question bank is incomplete"&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="k"&gt;fi
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"question bank is complete"&lt;/span&gt;
&lt;span class="c"&gt;# Proposed: only run after the gate passes.&lt;/span&gt;
&lt;span class="c"&gt;# gh pr create --fill --body-file REVIEWER_QUESTIONS.md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pass rules for each required question
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Required evidence&lt;/th&gt;
&lt;th&gt;Pass rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reproduction&lt;/td&gt;
&lt;td&gt;command plus exit codes&lt;/td&gt;
&lt;td&gt;Fails on &lt;code&gt;origin/main&lt;/code&gt;, passes on &lt;code&gt;HEAD&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public surface&lt;/td&gt;
&lt;td&gt;exported names from the diff&lt;/td&gt;
&lt;td&gt;No undocumented rename or signature change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negative path&lt;/td&gt;
&lt;td&gt;one input that must still fail&lt;/td&gt;
&lt;td&gt;Non-zero exit and original error type preserved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Regression test&lt;/td&gt;
&lt;td&gt;test path and assertion line&lt;/td&gt;
&lt;td&gt;Test failed before the patch and passes after&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Commit shape&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git log --oneline&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One logical change per commit, revertible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docs&lt;/td&gt;
&lt;td&gt;changelog, rustdoc, or skip reason&lt;/td&gt;
&lt;td&gt;Skip only for internal helpers with no user behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;The bank does not replace a maintainer who knows the crate's history, and it will not catch semantic bugs the tests never expressed. Models often over-generate questions about style and under-generate questions about concurrency, ABI, and platform quirks. A free server run is only as good as the command the contributor recorded in the first step. Teams that already require a formal design review should treat this file as a packet, not as a substitute for that review.&lt;/p&gt;

&lt;p&gt;Generated questions also drift when the diff includes vendored code, snapshots, or generated protobuf bindings. In those cases the header lister will emit noise, and a human should delete those rows before the drafting pass. The gate only proves that answers exist as text; it does not prove that the cited lines implement the claim. Lying in the bank is still possible, so maintainers should sample at least one citation against the working tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this packet
&lt;/h2&gt;

&lt;p&gt;Tiny typo pull requests do not need a twelve-minute packet, and the process would look like ceremony. Security issues that cannot discuss the exploit path in public should stay in the project's private disclosure channel. Contributors who cannot run the failing command at all should not invent passing answers for a server they never invoked. Projects that forbid model-assisted patches in &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; should skip the drafting step and fill the bank by hand, or skip the bank.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typo-only or comment-only pull requests&lt;/li&gt;
&lt;li&gt;Private security disclosures that cannot describe the failure mode&lt;/li&gt;
&lt;li&gt;Patches the contributor cannot execute on a clean checkout&lt;/li&gt;
&lt;li&gt;Repositories that ban model-assisted contributions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next time a crash fix looks ready, the contributor can spend twenty minutes answering the questions a tired maintainer will ask anyway. The resulting packet does not make the patch correct, but it makes incorrectness cheaper to see. A filled bank also gives a coding model a narrower job than rewriting a module until continuous integration turns green. That narrower job is the difference between a reviewable patch and a fluent diff that still stalls for days.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>git</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>A One-Command Reproducer Kit That Survives a Clean OSS Checkout</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Sun, 20 Sep 2026 10:57:53 +0000</pubDate>
      <link>https://dev.to/datars_7274/a-one-command-reproducer-kit-that-survives-a-clean-oss-checkout-38fc</link>
      <guid>https://dev.to/datars_7274/a-one-command-reproducer-kit-that-survives-a-clean-oss-checkout-38fc</guid>
      <description>&lt;p&gt;A contributor opened a pull request against a popular HTTP client with a three-line timeout fix and a screenshot. Maintainers could not reproduce the hang on CI, so the branch sat idle across two review cycles. The hidden cause was a leftover &lt;code&gt;HTTP_PROXY&lt;/code&gt; export in a shell profile plus a vendored snapshot that no longer matched &lt;code&gt;main&lt;/code&gt;. The patch itself was reasonable; the missing artifact was a reproduction kit that survived a clean clone.&lt;/p&gt;

&lt;p&gt;Industry chatter in mid-September 2026 keeps returning to the same failure mode: generated diffs look complete while the engineering work around them is skipped. Open-source review is where that gap becomes public. A maintainer cannot merge a story about a laptop. A maintainer can merge a command that fails the same way on a fresh tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dirty trees hide the actual bug
&lt;/h2&gt;

&lt;p&gt;Local developer machines accumulate exports, toolchains, cached wheels, and half-applied patches that never exist on a maintainer laptop. A failure that depends on that residue will vanish the moment someone clones the repository into an empty directory. Maintainers then spend review time debugging the reporter's environment instead of the library. A clean-clone gate makes that class of confusion expensive for the contributor and cheap for the project.&lt;/p&gt;

&lt;p&gt;Screenshots, truncated logs, and "it works on my machine after I source &lt;code&gt;.envrc&lt;/code&gt;" notes do not travel. They also do not bisect. The kit described here is the first deliverable of an OSS bugfix, not an afterthought pasted under the diff. The patch comes only after the kit fails for the same reason in two isolated trees.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the kit must contain
&lt;/h2&gt;

&lt;p&gt;A useful kit is not a paragraph of remembered steps inside the issue form. It is a script, a pinned revision, an expected failure, and a short environment dump that another person can run without extra narrative. The kit should fail for the same observable reason on two machines before any production patch is written. The following items are the minimum set for most application-level bugs in published libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pinned upstream remote plus a commit SHA or release tag&lt;/li&gt;
&lt;li&gt;one command that exits non-zero while the bug is present&lt;/li&gt;
&lt;li&gt;captured tool versions for the language, package manager, compiler, and OS&lt;/li&gt;
&lt;li&gt;explicit unset of proxy, credential, and vendor-cache variables&lt;/li&gt;
&lt;li&gt;a recorded last-known-good tag when the reporter already has that information&lt;/li&gt;
&lt;li&gt;a short expected-versus-actual block that a stranger can compare by eye&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The kit is not a substitute for the project's own test suite. It is a passport that lets a stranger reach the failing assertion without inheriting the reporter's shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  A one-command template
&lt;/h2&gt;

&lt;p&gt;The script below is a labeled template, not a captured run from a specific repository. Operators should replace the remote, SHA, language toolchain, and failing invocation with values from the issue they are actually working. The important property is isolation: a temporary directory, a fresh clone, and an environment that starts empty of proxy and virtualenv hints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# repro_kit.sh — labeled template for a clean-clone OSS reproducer&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;REMOTE&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;REMOTE&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;https&lt;/span&gt;://github.com/example/http-client.git&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;SHA&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;SHA&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;a1b2c3d4e5f60718293a4b5c6d7e8f9012345678&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;WORKDIR&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="nt"&gt;-d&lt;/span&gt; /tmp/oss-repro.XXXXXX&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;'rm -rf "$WORKDIR"'&lt;/span&gt; EXIT

&lt;span class="c"&gt;# Strip common local residue that maintainers will not have.&lt;/span&gt;
&lt;span class="nb"&gt;unset &lt;/span&gt;HTTP_PROXY HTTPS_PROXY ALL_PROXY http_proxy https_proxy all_proxy &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
unset &lt;/span&gt;VIRTUAL_ENV PYTHONPATH NODE_PATH GOPATH GOFLAGS CARGO_HOME &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin:/bin:/usr/local/bin"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"workdir=&lt;/span&gt;&lt;span class="nv"&gt;$WORKDIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"uname=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; python3 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; python3 &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; git &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git &lt;span class="nt"&gt;--version&lt;/span&gt;

git clone &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REMOTE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKDIR&lt;/span&gt;&lt;span class="s2"&gt;/src"&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKDIR&lt;/span&gt;&lt;span class="s2"&gt;/src"&lt;/span&gt;
git checkout &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SHA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"HEAD=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse HEAD&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"describe=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git describe &lt;span class="nt"&gt;--always&lt;/span&gt; &lt;span class="nt"&gt;--dirty&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Project-specific install. Keep it deterministic; avoid user-site packages.&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="c"&gt;# shellcheck disable=SC1091&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;

&lt;span class="c"&gt;# The single failing command. Replace with the issue's minimal trigger.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; +e
python - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;PY&lt;/span&gt;&lt;span class="sh"&gt;'
from client import Session

s = Session(timeout=0.05)
try:
    s.get("https://example.invalid/slow")
    raise SystemExit("expected timeout, got success")
except Exception as exc:
    name = type(exc).__name__
    if name != "Timeout":
        print(f"actual_exception={name}: {exc}")
        raise SystemExit(2)
    print(f"reproduced:{name}")
    raise SystemExit(1)
&lt;/span&gt;&lt;span class="no"&gt;PY
&lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"repro_exit=&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A passing mental check for this script is simple. A stranger with network access and the language toolchain should reach the same non-zero exit without reading the pull request. If the script needs a paragraph of preamble, the kit is still a blog post and not yet a kit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expected versus actual, in the repo
&lt;/h2&gt;

&lt;p&gt;Issue threads lose formatting and lose files. Checking a tiny sidecar into the branch keeps the contract next to the script. The file below is also a template; the strings must come from a real run, not from memory of the original crash.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# repro_kit.expect
remote: https://github.com/example/http-client.git
sha: a1b2c3d4e5f60718293a4b5c6d7e8f9012345678
command: python repro_min.py
expected_exit: 1
expected_stderr_contains: reproduced:Timeout
forbidden_stderr: HTTP_PROXY
last_known_good_tag: v2.4.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store the script and the expect file in a directory that reviewers can delete after merge, such as &lt;code&gt;repro/issue-8412/&lt;/code&gt;. Do not hide them inside a personal gist that will rot. The pull request body should link to the path and paste the last local run, including &lt;code&gt;HEAD&lt;/code&gt; and &lt;code&gt;repro_exit&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table: when the kit is honest
&lt;/h2&gt;

&lt;p&gt;Use the table before writing production code. Each row is a gate. A "no" in the remote column means the bug is still a local myth, even if the laptop demo looks perfect.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Observation after &lt;code&gt;repro_kit.sh&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Local dirty tree&lt;/th&gt;
&lt;th&gt;Fresh &lt;code&gt;/tmp&lt;/code&gt; clone&lt;/th&gt;
&lt;th&gt;Remote clean machine&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Same non-zero exit and same exception name&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;Write the patch; kit is load-bearing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fails locally, passes on fresh clone&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;Stop; inspect exports, caches, extra remotes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fails on fresh clone, passes on remote&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;Record OS, CPU, and filesystem; do not send a Linux-only guess&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passes everywhere, including the reported SHA&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;The issue is closed or mis-filed; do not invent a fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fails with different exceptions across machines&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;Narrow the trigger; the kit is still too wide&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requires secrets, production data, or a private registry&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;maybe&lt;/td&gt;
&lt;td&gt;maybe&lt;/td&gt;
&lt;td&gt;Do not publish the kit; use a redacted fixture or a private maintainer channel&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The interesting row is the second one. That is the screenshot pull request. The clean clone is the cheapest way to discover it before a maintainer does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the kit where the laptop cannot help
&lt;/h2&gt;

&lt;p&gt;A second machine is not a luxury for this workflow. It is the control group. Continuous integration on the fork is one control group, provided the workflow file does not reuse caches that hide the bug. A disposable remote workspace is another, provided it starts without the reporter's &lt;code&gt;direnv&lt;/code&gt;, keychain, or Docker layer cache.&lt;/p&gt;

&lt;p&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode offers free model access and a free server option that can host a throwaway clone for this control-group run. The models are useful later for reviewing the kit text; the server is useful now because it does not inherit the laptop's residue. No quota, model catalog, or hardware profile is claimed here, because those details change and do not belong in a frozen article.&lt;/p&gt;

&lt;p&gt;A practical remote pass looks like the following sequence. Clone into a new directory, copy only &lt;code&gt;repro_kit.sh&lt;/code&gt; and &lt;code&gt;repro_kit.expect&lt;/code&gt;, and refuse to copy &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;venv&lt;/code&gt;, or &lt;code&gt;node_modules&lt;/code&gt;. Run the script once, capture stdout and stderr to a file, and attach that file to the issue. If the remote exit code disagrees with the laptop, the patch waits.&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;# Labeled example: capture a remote control-group run.&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x repro_kit.sh
./repro_kit.sh &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro_remote.log 2&amp;gt;&amp;amp;1
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"remote_exit=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; repro_remote.log
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^(HEAD|describe|repro_exit|reproduced:|actual_exception=)'&lt;/span&gt; repro_remote.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Free-model review of the kit, not the vibes
&lt;/h2&gt;

&lt;p&gt;Generated patches often read as confident while the reproduction story remains sloppy. The safer use of a free coding model in this workflow is editorial, and it happens before the production diff exists. Paste the script, the expect file, and the draft issue comment. Ask for a maintainer-facing review of clarity, not for a speculative fix.&lt;/p&gt;

&lt;p&gt;A prompt that stays inside that boundary looks like the block below. It is labeled, because it is a proposal rather than a log from a particular model run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are reviewing an OSS reproduction kit, not writing a patch.
Point out missing pins, leftover environment coupling, and claims
that a stranger cannot verify with one command. List concrete edits
to repro_kit.sh, repro_kit.expect, and the issue comment. Do not
propose production code. Do not invent versions I did not supply.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treat the model output as a diff against the kit. Keep every edit that removes hidden state, vague verbs, or un-pinned installs. Discard advice that adds a rewrite of the library. If the model wants to "just catch Timeout and retry," the workflow has already failed, because the task was documentation of the bug, not product design.&lt;/p&gt;

&lt;p&gt;After the kit is tightened, a second short pass can check the pull request body for maintainer time costs. Useful flags include missing SHA, missing exit code, commands that assume a particular absolute path, and logs that still contain home-directory fragments. Those are review comments the reporter can fix without waiting for a human round trip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Only then write the patch
&lt;/h2&gt;

&lt;p&gt;Once local fresh-clone and remote clean-machine runs agree, the patch has a job: make &lt;code&gt;repro_kit.sh&lt;/code&gt; exit zero for the right reason. Keep the kit on the branch until reviewers say otherwise. A green kit plus a green project test suite is a stronger story than a green suite alone, because the suite may never have covered the reported path.&lt;/p&gt;

&lt;p&gt;Commit shape still matters. One commit should add the kit and show the failure on the parent SHA if the project's CI will allow a known-failing commit. The next commit should contain the fix and the permanent regression test that will remain after &lt;code&gt;repro/&lt;/code&gt; is deleted. Do not squash away that history if the project likes bisectable series. The kit is evidence; the regression test is the long-term contract.&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;# Labeled local sequence after both environments agree on the failure.&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; issue-8412-timeout-repro
git add repro/issue-8412/repro_kit.sh repro/issue-8412/repro_kit.expect
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"repro: add clean-clone kit for issue 8412"&lt;/span&gt;

&lt;span class="c"&gt;# ... implement the library fix and a permanent test ...&lt;/span&gt;
git add src tests
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix: surface Timeout when the deadline is already expired"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the permanent test cannot be written without the kit's private fixture, the fixture needs to be reduced until it can live under &lt;code&gt;tests/&lt;/code&gt;. A kit that cannot be turned into a project test is still valuable for triage, but it should not be the only safety net after merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;This workflow assumes the bug is deterministic enough to fail a script twice. Flaky timing bugs, GPU-only faults, and races that need hours of load will not honor a one-command kit. Hardware-specific failures need a documented machine profile that a free generic server will not provide. The clean-clone gate also assumes the project can be built by a stranger from a tag; monorepos that require internal Bazel seeds or private wheels need a reduced public fixture first.&lt;/p&gt;

&lt;p&gt;The workflow is the wrong tool for embargoed security reports. A public reproducer kit that demonstrates a practical exploit does not belong on a fork. Those issues follow the project's security policy, which often means a private channel and a delayed disclosure, not a &lt;code&gt;repro/&lt;/code&gt; directory on a personal branch. License and CLA constraints are also out of scope for the script; they still block the pull request even when the kit is perfect.&lt;/p&gt;

&lt;p&gt;Free model access will not know whether the exception name is stable across minor tags. Free remote machines will not magically match an affected user's older distro. Both are controls against local dirt, not oracles. When the table's remote column cannot be filled, say so in the issue instead of implying a complete matrix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this approach
&lt;/h2&gt;

&lt;p&gt;Drive-by typo fixes, documentation-only pull requests, and issues already failing on upstream CI do not need a personal reproducer kit. Maintainers who already pasted a failing job URL have done the isolation work. Contributors without permission to clone the code, or without a legal right to redistribute a fixture, should stop at a redacted description and wait for maintainer instructions.&lt;/p&gt;

&lt;p&gt;Teams that punish extra files on a branch may prefer a gist or a CI job, but the isolation rules stay the same. The method is for reporters who are about to change shared behavior and who need a stranger to believe the bug exists. Readers who want a disposable machine for the control-group step can use MonkeyCode's free server option with its free model access, then keep the kit in the pull request regardless of where it was run.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>git</category>
      <category>ai</category>
    </item>
    <item>
      <title>Classify the Public Surface Before an OSS Crash Fix Hits Review</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Sat, 19 Sep 2026 09:15:48 +0000</pubDate>
      <link>https://dev.to/datars_7274/classify-the-public-surface-before-an-oss-crash-fix-hits-review-25ll</link>
      <guid>https://dev.to/datars_7274/classify-the-public-surface-before-an-oss-crash-fix-hits-review-25ll</guid>
      <description>&lt;p&gt;Consider a mid-size TypeScript CLI that received a three-line pull request stopping a null crash in flag parsing. The reporter attached a passing unit test, a screenshot of the local run, and a short stack note. Maintainers still closed the request after one pass because an exported helper changed return values for empty argv. Downstream packages had treated that helper as a stable contract, so the crash fix was a breaking change wearing patch-sized clothing.&lt;/p&gt;

&lt;p&gt;Correctness is not the only gate on an upstream pull request for libraries that already have downstream dependents in late 2026. Maintainers also protect exported names, documented flags, config keys, and the promise implied by the next version tag. A contributor who only proves the bug is gone still leaves contract classification sitting on the reviewer. The packet below keeps a human in charge of reproduce, patch, and test, then records a Semver Impact Card before anyone files the diff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why small crash fixes still stall on versioning
&lt;/h2&gt;

&lt;p&gt;Issue threads reward a green test and a short, readable diff against the reported file. Versioning rewards a boring, named claim about what downstream code may keep calling after the next tag. Those two rewards pull in opposite directions when a crash lives inside a helper that already ships in &lt;code&gt;__all__&lt;/code&gt;, &lt;code&gt;export&lt;/code&gt;, or a public header. The helper can start returning a documented empty object instead of throwing, which is kinder to interactive users and still a meaning change for callers that caught the exception.&lt;/p&gt;

&lt;p&gt;Review time then migrates from the hunk to an argument about frozen intent. Maintainers compare README examples, type stubs, changelog footnotes, and the last tagged tarball. Contributors repeat that the crash was never written down as a feature. The Semver Impact Card moves that argument into a table before the pull request exists, so the first human review starts on a classified claim rather than on informal confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four stages before &lt;code&gt;gh pr create&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The working sequence is reproduce, patch, test, and classify. Each stage writes a file under &lt;code&gt;.patch-packet/&lt;/code&gt; so the pull request can link evidence instead of retelling the narrative. Model output appears only after the first three stages are green on a clean tag, because a model that reviews a still-failing tree invents compatibility stories.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reproduce the reported failure on the issue tag, not on a dirty local &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Patch the owning module without drive-by refactors or formatting sweeps.&lt;/li&gt;
&lt;li&gt;Run the project's test runner plus one new assertion that binds the contract.&lt;/li&gt;
&lt;li&gt;Fill the Semver Impact Card and invite a model to falsify the proposed bump.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Stage 1: Reproduce on the reported tag
&lt;/h3&gt;

&lt;p&gt;Check out the tag named in the issue, not a local branch that already contains extra commits. A dirty tree hides whether upstream already shipped a fix, which makes any compatibility claim dishonest. Record the command, expected output, and observed output in &lt;code&gt;repro.md&lt;/code&gt; beside a tiny shell wrapper that exits non-zero on the broken tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch &lt;span class="nt"&gt;--tags&lt;/span&gt; origin
git switch &lt;span class="nt"&gt;--detach&lt;/span&gt; v4.2.1
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[dev]"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .patch-packet

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .patch-packet/repro.sh &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
#!/usr/bin/env bash
set -euo pipefail
# Documented contract: empty argv yields an empty object and exit 0.
# Observed on v4.2.1: TypeError from parse_argv([]).
python -m samplecli parse --argv '' --format json
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x .patch-packet/repro.sh
./.patch-packet/repro.sh&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"exit=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The wrapper must fail on the tagged release and later pass on the patched tree. If it cannot fail on that tag, the issue is not isolated enough for a compatibility claim, and the card should not be filled yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 2: Patch the owning module only
&lt;/h3&gt;

&lt;p&gt;Keep the diff inside the file that owns the crash path. Cross-cutting cleanups belong in a follow-up issue, not in a crash fix that also claims a version bump. After the edit, store a unified diff and a name-only file list next to the card so later review does not depend on a working tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;
git diff &lt;span class="nt"&gt;-U3&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; src/samplecli/parse.py &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .patch-packet/patch.diff
git diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .patch-packet/files.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A crash fix in this shape is usually a null guard plus a default that already appears in the docs. If the hunk set grows past the failing function, split the work before filling the card, because extra files inflate the public-surface table without extra evidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3: Bind the new behavior with the project runner
&lt;/h3&gt;

&lt;p&gt;Call the same runner the CI workflow already uses. Add one assertion that encodes the old crash input and the intended contract, then keep neighboring tests unmodified unless they encoded the crash as expected behavior. Do not introduce a second framework for a single upstream patch, because reviewers will not install it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tests/test_parse_empty_argv.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;samplecli.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parse_argv&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_empty_argv_returns_empty_object_without_raising&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_argv&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&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;flags&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;positionals&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;assert&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;help&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flags&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pytest &lt;span class="nt"&gt;-q&lt;/span&gt; tests/test_parse_empty_argv.py tests/test_parse.py
git add tests/test_parse_empty_argv.py src/samplecli/parse.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Green tests still do not prove that exported meaning stayed compatible for downstream imports. That proof is the card in the next stage, not another assertion about private helpers or log lines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 4: Classify public surface before the pull request
&lt;/h3&gt;

&lt;p&gt;Copy the template into &lt;code&gt;.patch-packet/semver-impact.md&lt;/code&gt; and complete every field on the same day as the diff. Blank cells are a stop for the contributor, not a reminder for the maintainer to finish the taxonomy. The proposed bump must cite the project's own versioning document, even when that document is only a short README section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Artifact: the Semver Impact Card
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Semver Impact Card&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Project / issue: samplecli#1842
&lt;span class="p"&gt;-&lt;/span&gt; Base tag: v4.2.1
&lt;span class="p"&gt;-&lt;/span&gt; Proposed bump: PATCH | MINOR | MAJOR
&lt;span class="p"&gt;-&lt;/span&gt; Versioning source: VERSIONING.md (commit abc1234) or README "Versioning"

&lt;span class="gu"&gt;## Public surface touched&lt;/span&gt;
| Kind | Name | Before | After | Visible to downstream? |
| ---- | ---- | ------ | ----- | ---------------------- |
| function | parse_argv | raises TypeError on [] | returns empty object | yes, listed in __all__ |
| CLI flag | --format | unchanged | unchanged | yes |
| config key | (none) | | | |
| file format | (none) | | | |

&lt;span class="gu"&gt;## Classification rules used&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; MAJOR: remove or rename an export, change return meaning, or reject previously valid input
&lt;span class="p"&gt;-&lt;/span&gt; MINOR: add an export or optional flag whose default preserves old calls
&lt;span class="p"&gt;-&lt;/span&gt; PATCH: fix a crash or wrong result without changing documented meaning

&lt;span class="gu"&gt;## Claim&lt;/span&gt;
PATCH. &lt;span class="sb"&gt;`parse_argv([])`&lt;/span&gt; now matches the documented empty-object example in README.md.
The TypeError was never listed as a contract in VERSIONING.md or the type stubs.

&lt;span class="gu"&gt;## Explicit non-claims&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Does not add --strict
&lt;span class="p"&gt;-&lt;/span&gt; Does not change JSON key order
&lt;span class="p"&gt;-&lt;/span&gt; Does not backport to the 3.x line

&lt;span class="gu"&gt;## Tests that bind the claim&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; tests/test_parse_empty_argv.py (new)
&lt;span class="p"&gt;-&lt;/span&gt; tests/test_parse.py (unchanged, still green)

&lt;span class="gu"&gt;## Items for maintainer confirmation&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Confirm parse_argv is public because __all__ includes it
&lt;span class="p"&gt;-&lt;/span&gt; Confirm the README example, not the TypeError, is the frozen contract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The table is the artifact a maintainer can scan without opening every hunk. The non-claims section matters as much as the bump, because it blocks extra behavior from sneaking into the pull request title. Store the filled card in git even if the project will not merge the &lt;code&gt;.patch-packet/&lt;/code&gt; directory, then paste a summary into the pull request body.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract candidate exports from the unified diff
&lt;/h2&gt;

&lt;p&gt;Hand-filled tables miss aliases, re-exports, and definitions added only as &lt;code&gt;+export&lt;/code&gt;. A small illustrative script greps added definition lines, then checks &lt;code&gt;__all__&lt;/code&gt; on the current file. The output is a candidate list for the card, not a legal API boundary and not a substitute for reading VERSIONING.md.&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;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;semver_scan.py — list definition lines in a unified diff (illustrative).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;DEF_RE&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;^\+\s*(?:export\s+)?(?:async\s+)?(?:def|function|class|const|exports\.)\s*([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;ALL_RE&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;__all__\s*=\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;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&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;definitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&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;list&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;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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;=&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;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEF_RE&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="n"&gt;line&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;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;found&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="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;public_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;py_source&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;set&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;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ALL_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;py_source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;set&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="n"&gt;tok&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tok&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&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="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tok&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;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;definitions_added_or_modified:&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;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="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;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;public_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in__all__:&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;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python .patch-packet/semver_scan.py .patch-packet/patch.diff src/samplecli/parse.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Label the script illustrative, because languages disagree about the word public. Go uses capitalization, Rust uses &lt;code&gt;pub&lt;/code&gt; and &lt;code&gt;pub use&lt;/code&gt;, C uses installed headers, and TypeScript uses &lt;code&gt;export&lt;/code&gt;. The card must accept or reject each candidate by name, including names the scanner never saw because they live only in documentation examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Falsify the bump with a free model after tests pass
&lt;/h2&gt;

&lt;p&gt;A language model is a weak author of production hunks and a useful adversary for a versioning claim. The human still reproduces the crash, writes the change, and runs the project test runner. The model receives only the card, the unified diff, and VERSIONING.md, then tries to show that the bump is too low, too high, or unsupported by the files.&lt;/p&gt;

&lt;p&gt;Contributors without a private GPU can run that second pass on a free model endpoint. MonkeyCode currently offers free model access and a free server option for this kind of review host. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Teams that want a hosted loop for the review prompt can use the free server option as one of several possible hosts. The product is not required; any local endpoint that accepts a text prompt can execute the same checklist against the packet files.&lt;/p&gt;

&lt;p&gt;Save the prompt as &lt;code&gt;.patch-packet/review-prompt.md&lt;/code&gt; and paste the card plus &lt;code&gt;git diff --name-only&lt;/code&gt; under a clear delimiter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;You are reviewing a Semver Impact Card for an upstream pull request.
Do not rewrite the patch. Do not invent symbols that are absent from the diff.

Inputs:
1) semver-impact.md
2) git diff --name-only and the unified diff
3) VERSIONING.md or the README versioning section

Tasks:
&lt;span class="p"&gt;-&lt;/span&gt; List every added, removed, or retyped name that looks exported.
&lt;span class="p"&gt;-&lt;/span&gt; State whether the proposed bump is too low, too high, or consistent.
&lt;span class="p"&gt;-&lt;/span&gt; Quote the rule from VERSIONING.md that supports that judgment.
&lt;span class="p"&gt;-&lt;/span&gt; Flag any line in Explicit non-claims that the diff already implements.
&lt;span class="p"&gt;-&lt;/span&gt; Return at most 12 lines with sections: missed_exports, bump_judgment, rule_quote, overclaims.

If evidence is missing, write insufficient evidence instead of guessing.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the prompt only after the wrapper fails on the base tag and passes on HEAD. Store the output in &lt;code&gt;.patch-packet/model-review.txt&lt;/code&gt; and treat disagreements as contributor work, not as automatic edits to &lt;code&gt;parse.py&lt;/code&gt;. A model that rewrites the hunk at this stage undoes the whole point of classifying a human patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table for the proposed bump
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Observation on the tagged tree&lt;/th&gt;
&lt;th&gt;Typical bump&lt;/th&gt;
&lt;th&gt;Stop filling the card if&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Crash on input the docs already allow&lt;/td&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;docs and tests disagree about the input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New optional flag with a preserving default&lt;/td&gt;
&lt;td&gt;MINOR&lt;/td&gt;
&lt;td&gt;the default changes old output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Return type or error class changes for valid input&lt;/td&gt;
&lt;td&gt;MAJOR&lt;/td&gt;
&lt;td&gt;the issue asked only for a crash fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rename of an exported helper&lt;/td&gt;
&lt;td&gt;MAJOR&lt;/td&gt;
&lt;td&gt;no alias remains for one release&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal function only, absent from docs and &lt;code&gt;__all__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;PATCH or no release&lt;/td&gt;
&lt;td&gt;the name appears in a public example&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table is a starting filter for contributors who do not yet know the project's customs. The project's VERSIONING.md wins when it conflicts with this chart, and the card should quote the winning sentence. When VERSIONING.md is missing, the card should say so in the versioning-source field and propose PATCH only for undocumented crash behavior that existing tests already allowed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample pull request body
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Summary&lt;/span&gt;
Crash on empty argv in parse_argv. Packet claims PATCH against v4.2.1.

&lt;span class="gu"&gt;## Evidence&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Repro: .patch-packet/repro.sh fails on v4.2.1, passes on this branch
&lt;span class="p"&gt;-&lt;/span&gt; Test: tests/test_parse_empty_argv.py
&lt;span class="p"&gt;-&lt;/span&gt; Surface: .patch-packet/semver-impact.md
&lt;span class="p"&gt;-&lt;/span&gt; Adversarial pass: .patch-packet/model-review.txt (informational only)

&lt;span class="gu"&gt;## Maintainer confirmation requested&lt;/span&gt;
Please confirm parse_argv is public and that README empty-object example is the contract.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep the model report informational. Maintainers did not ask for a generated review persona, and a contributor should not present model prose as CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;The scanner does not understand re-exports, decorator-wrapped APIs, or documentation-only contracts. A README sample can freeze behavior that never appears in &lt;code&gt;__all__&lt;/code&gt;, and plugin entry points can expose names that live only in packaging metadata. Generated bindings need a human pass over the installed artifact, not merely over the source diff. Model review can miss domain meaning, such as a numeric default that looks compatible but breaks a wire protocol or a sort order that tests never pinned.&lt;/p&gt;

&lt;p&gt;Free model access and a free server option do not make the review authoritative. They do not replace maintainer judgment, signed tags, or the project's CI matrix. The card also fails for embargoed security fixes that must not describe public surface in a public packet. Those patches follow the project's security policy rather than this template, and they should not be sent to a third-party endpoint.&lt;/p&gt;

&lt;p&gt;Time-sensitive product quotas, model catalogs, and hardware lists change often and are omitted here on purpose. Operators should confirm current availability on the surface they actually use, rather than copying capacity claims from a blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this packet
&lt;/h2&gt;

&lt;p&gt;Skip the card for typo-only documentation edits and for private forks with no downstream consumers. Skip it for contributors who have not reproduced the failure on a clean tag, because there is no honest base for a bump. Skip model review when the repository forbids sending source to third-party endpoints, including patches that contain secrets, customer data, or undisclosed vulnerabilities. Skip the whole packet when the maintainer template already requires a changelog with the same fields, because duplicate paperwork helps nobody and slows the merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the pull request should link
&lt;/h2&gt;

&lt;p&gt;A pull request that links the repro wrapper, the new test, &lt;code&gt;semver-impact.md&lt;/code&gt;, and &lt;code&gt;model-review.txt&lt;/code&gt; gives reviewers a contract claim they can accept or correct in one pass. The patch can still be wrong on performance or style, but the argument is about a named export and a named bump. Engineering work stays in reproduce, patch, and test; the model only pressure-tests the written claim after those stages are already green.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>git</category>
      <category>testing</category>
      <category>python</category>
    </item>
    <item>
      <title>Declare the Behavior Delta Before Maintainers Open an OSS Bugfix</title>
      <dc:creator>Blake Yang</dc:creator>
      <pubDate>Fri, 18 Sep 2026 07:11:15 +0000</pubDate>
      <link>https://dev.to/datars_7274/declare-the-behavior-delta-before-maintainers-open-an-oss-bugfix-1gmm</link>
      <guid>https://dev.to/datars_7274/declare-the-behavior-delta-before-maintainers-open-an-oss-bugfix-1gmm</guid>
      <description>&lt;p&gt;A contributor cloned a popular CLI, reproduced a parser crash, and typed a confident patch in one sitting. The pull request touched a helper, two tests, and a changelog line that promised a complete fix. Maintainers opened the diff and still could not tell which captured outputs were supposed to change. Screenshots arrived later, then a second patch, then a request for logs the contributor had already discarded.&lt;/p&gt;

&lt;p&gt;That stall is common when a bugfix is treated as a narrative instead of a measurable delta. Reviewers need the command, the before output, the after output, and a short allowlist of intended change. Without those four pieces, a green local run is only a private memory of one machine. The workflow below turns that memory into files a distant maintainer can replay without extra archaeology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the patch as a declared behavior delta
&lt;/h2&gt;

&lt;p&gt;An OSS bugfix is not finished when the process exits zero on one laptop. The finished unit is a declared delta: old behavior, new behavior, and the exact invocation that produces both. Code review then checks whether the git hunks are necessary for that delta, rather than guessing intent from renamed helpers. This framing also limits accidental drive-by refactors that hide inside a supposedly small fix.&lt;/p&gt;

&lt;p&gt;A useful delta statement is boring, local, and specific enough to fail in public. It names the binary or test target, the fixture, and the lines that must differ after the patch. It also names the outputs that must stay byte-identical so collateral churn cannot hide. Maintainers can reject a patch that cannot produce that statement in a few quiet minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The oracle packet
&lt;/h2&gt;

&lt;p&gt;Keep the packet beside the worktree, not inside a chat log that will rot. A simple directory is enough for most CLI tools and library bugs that fail in user space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;oracle/
  README.md
  invoke.sh
  before.txt
  after.txt
  before.exit
  after.exit
  allowlist.txt
  observed.diff
  check_allowlist.py
  check_oracle.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file has one job, and mixing those jobs is how packets become essays. &lt;code&gt;invoke.sh&lt;/code&gt; is the only entry point a stranger should need to execute. &lt;code&gt;before.txt&lt;/code&gt; and &lt;code&gt;after.txt&lt;/code&gt; are raw captured bytes, not edited summaries of what the contributor remembers. &lt;code&gt;allowlist.txt&lt;/code&gt; lists the fragments that are allowed to differ, and &lt;code&gt;check_oracle.sh&lt;/code&gt; fails when the live diff escapes that list.&lt;/p&gt;

&lt;h3&gt;
  
  
  README.md as the human index
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Oracle packet: parse crash on empty --config&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Upstream issue: #4182
&lt;span class="p"&gt;-&lt;/span&gt; Failing commit used for the before capture: 9f3c1aa
&lt;span class="p"&gt;-&lt;/span&gt; Invocation: ./oracle/invoke.sh
&lt;span class="p"&gt;-&lt;/span&gt; Intended delta: stderr gains a one-line usage error; process status becomes 2
&lt;span class="p"&gt;-&lt;/span&gt; Forbidden delta: stdout of &lt;span class="sb"&gt;`--help`&lt;/span&gt; and the JSON fixture under tests/data/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The README is an index so a maintainer can skip archaeology, not a second design document. Link the issue, pin the commit, and state the delta in one plain sentence. Leave motivation and design opinions in the pull request body, where discussion belongs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: freeze the failing invocation
&lt;/h2&gt;

&lt;p&gt;Do not start in the editor. Write the invocation that currently fails, including working directory and environment variables that the tool actually reads. If the bug needs a fixture, generate that fixture in the same script so the packet stays closed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# oracle/invoke.sh&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/.."&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cd&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PYTHONUNBUFFERED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="c"&gt;# Status is recorded below; do not abort the script on the expected failure.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; +e
python &lt;span class="nt"&gt;-m&lt;/span&gt; tools.parser &lt;span class="nt"&gt;--config&lt;/span&gt; tests/data/empty.toml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;oracle/stdout.txt 2&amp;gt;oracle/stderr.txt
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; oracle/exit_code.txt
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record status, stdout, and stderr as separate streams when those streams matter to the bug. Mixing them in a terminal screenshot is how reviews lose the only signal they can replay. If a test runner can target one case, prefer that invocation over a manual CLI session with hidden shell history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: capture the before side without editing it
&lt;/h2&gt;

&lt;p&gt;Run the frozen invocation on the parent commit that still contains the bug. Save the streams before any local patch exists in that tree. Resist the urge to trim timestamps or absolute paths by hand, because silent edits make the after file incomparable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch &lt;span class="nt"&gt;--detach&lt;/span&gt; 9f3c1aa
./oracle/invoke.sh
&lt;span class="nb"&gt;cp &lt;/span&gt;oracle/stderr.txt oracle/before.txt
&lt;span class="nb"&gt;cp &lt;/span&gt;oracle/exit_code.txt oracle/before.exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If logs embed clocks, hostnames, or random request ids, freeze those sources in &lt;code&gt;invoke.sh&lt;/code&gt; before treating the files as oracles. A packet that cannot be replayed tomorrow is a diary entry, not evidence. Characterization of the failure belongs in the captured bytes, not in a paraphrase of a stack trace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: apply the smallest patch that should move the delta
&lt;/h2&gt;

&lt;p&gt;Copy &lt;code&gt;before.txt&lt;/code&gt; and &lt;code&gt;before.exit&lt;/code&gt; to a safe path if the working tree will rerun the same script. Then restore a writable branch and change only what the issue asked to change. Do not fold formatter noise, comment rewrites, or unrelated helper cleanups into the same commit, because those extra hunks make the allowlist dishonest even when the crash is gone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch &lt;span class="nt"&gt;--create&lt;/span&gt; fix/empty-config 9f3c1aa
&lt;span class="c"&gt;# edit tools/parser.py and the focused test only&lt;/span&gt;
git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A short self-check before capture keeps the later allowlist honest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every edited path is named in the issue or required by the failing invocation.&lt;/li&gt;
&lt;li&gt;No lockfiles, generated docs, or IDE metadata slipped into &lt;code&gt;git status&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The changelog line, if required by the project, matches the declared delta and nothing else.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: capture the after side with the same invocation
&lt;/h2&gt;

&lt;p&gt;Use the identical &lt;code&gt;invoke.sh&lt;/code&gt;. If the command line changes, the packet is invalid and the README must be rewritten first. Copy the new streams into &lt;code&gt;after.txt&lt;/code&gt; and &lt;code&gt;after.exit&lt;/code&gt;, then produce a unified diff the checker can read.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./oracle/invoke.sh
&lt;span class="nb"&gt;cp &lt;/span&gt;oracle/stderr.txt oracle/after.txt
&lt;span class="nb"&gt;cp &lt;/span&gt;oracle/exit_code.txt oracle/after.exit
diff &lt;span class="nt"&gt;-u&lt;/span&gt; oracle/before.txt oracle/after.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; oracle/observed.diff &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read &lt;code&gt;observed.diff&lt;/code&gt; as a product artifact, not as debug scrap from a local terminal. If the diff is empty, the patch did not change the failing behavior and review is premature. If the diff is huge, the patch changed more than the issue asked for and the allowlist will not save it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: publish an allowlist, not a vibe
&lt;/h2&gt;

&lt;p&gt;The allowlist is the original technical artifact of this workflow. It states which observed changes are load-bearing for the issue. Everything else is a defect in the packet, the invocation, or the patch itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# oracle/allowlist.txt
# One fragment per line. Lines starting with # are comments.
# EXIT: lines record an intended status change.
+error: empty --config is not a valid document
-Traceback (most recent call last):
EXIT: 1 -&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The checker below is a &lt;strong&gt;proposal&lt;/strong&gt; for local use, not a harvested suite from production CI. It treats uncovered unified-diff lines as a failed packet, which is stricter than a glance at &lt;code&gt;git diff&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Fail if oracle/observed.diff contains lines not covered by allowlist.txt.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;
&lt;span class="n"&gt;observed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;observed.diff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;replace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;exit_rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;raw_line&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;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowlist.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;raw_line&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="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EXIT:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;exit_rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;allow&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="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;uncovered&lt;/span&gt; &lt;span class="o"&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;raw&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;observed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+++&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;raw&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="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;pat&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pat&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;uncovered&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="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;before_exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;before.exit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;after_exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after.exit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&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;exit_rule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exit_rule&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="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="mi"&gt;1&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="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# e.g. "1 -&amp;gt; 2"
&lt;/span&gt;    &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;before_exit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;after_exit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit allowlist expected &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;, got &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;before_exit&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;after_exit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit code changed but allowlist.txt has no EXIT: rule&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;uncovered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;oracle allowlist missed these diff lines:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uncovered&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;oracle allowlist covered the observed diff&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;Wrap the checker so a maintainer runs one script after cloning the branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# oracle/check_oracle.sh&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&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="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; before.txt
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; after.txt
python3 check_allowlist.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust the exit-code rule to the issue rather than copying the sample. Some fixes must keep the same status and only change a message, and the allowlist should say so in words the checker can enforce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: review the packet against the git hunks
&lt;/h2&gt;

&lt;p&gt;Once the files exist, a second reader can compare three artifacts that humans often keep in separate windows. The first is &lt;code&gt;observed.diff&lt;/code&gt;. The second is &lt;code&gt;allowlist.txt&lt;/code&gt;. The third is &lt;code&gt;git diff&lt;/code&gt; for the actual source change. Contradictions among those three are the review, not whether the patch looks tidy in isolation.&lt;/p&gt;

&lt;p&gt;A narrow prompt keeps that second reader on the packet. The block below is a &lt;strong&gt;template&lt;/strong&gt;, not a transcript of a run performed for this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are reviewing an OSS bugfix packet, not writing new code.
Inputs: issue excerpt, git diff, oracle/before.txt, oracle/after.txt,
oracle/allowlist.txt, oracle/observed.diff, oracle/invoke.sh.
Report only:
1. Allowlist claims that do not appear in observed.diff
2. Observed.diff lines that the allowlist does not mention
3. Git hunks that cannot be tied to the declared delta
4. Steps in invoke.sh that look non-deterministic (time, net, random)
Do not suggest extra features. Do not rewrite the patch.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach. Free model access can run that constrained pass over the packet, and the free server option can replay &lt;code&gt;invoke.sh&lt;/code&gt; plus &lt;code&gt;check_oracle.sh&lt;/code&gt; on a machine that is not already loaded with the contributor's daemons. The packet remains the useful artifact if both of those options are skipped.&lt;/p&gt;

&lt;p&gt;Local caches, language shims, and half-installed extras are a frequent source of unreproducible fixes that only exist on one laptop. A clean clone that reproduces &lt;code&gt;before.txt&lt;/code&gt; and then &lt;code&gt;after.txt&lt;/code&gt; is part of the proof. If a shared server is used for that clone, scrub host paths, tokens, and customer fixtures from the oracle files before they leave the machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table for the packet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal in the packet&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Action before opening a PR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;observed.diff&lt;/code&gt; is empty&lt;/td&gt;
&lt;td&gt;The patch did not move the failing behavior&lt;/td&gt;
&lt;td&gt;Keep debugging; do not request review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diff is large, allowlist is short&lt;/td&gt;
&lt;td&gt;Hidden refactors or noisy logs&lt;/td&gt;
&lt;td&gt;Split the commit or quiet the invocation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allowlist mentions lines absent from the diff&lt;/td&gt;
&lt;td&gt;The declaration is aspirational&lt;/td&gt;
&lt;td&gt;Rewrite the allowlist against real bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exit code unchanged when the issue needs a status change&lt;/td&gt;
&lt;td&gt;Incomplete fix&lt;/td&gt;
&lt;td&gt;Add an &lt;code&gt;EXIT:&lt;/code&gt; rule and recapture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invocation embeds timestamps or absolute home paths&lt;/td&gt;
&lt;td&gt;Replay will rot on another host&lt;/td&gt;
&lt;td&gt;Fix &lt;code&gt;invoke.sh&lt;/code&gt; before any model pass&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;This workflow assumes a deterministic invocation. Flaky tests, live network calls, and clocks inside log lines will poison &lt;code&gt;before.txt&lt;/code&gt; and &lt;code&gt;after.txt&lt;/code&gt; on the second run. Binary fixtures and huge snapshot dumps also make the packet hard to review, so a focused assertion beats megabytes of pretty-printed JSON.&lt;/p&gt;

&lt;p&gt;The allowlist checker is string oriented on purpose. It can miss semantic changes that keep the same text, and it can flag harmless path reordering that still confuses a reviewer. Contributors still need a human pass on the git hunks, especially around public API and error-code stability. A model will not see uncommitted files, private credentials in environment dumps, or project policy on breaking changes.&lt;/p&gt;

&lt;p&gt;Do not paste secrets into a shared server or a model prompt. Oracle files often contain host paths, tokens from failed auth, or fixtures that should never be public. If the bug only reproduces with proprietary data, a public before-and-after packet is the wrong shape for the proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should skip this approach
&lt;/h2&gt;

&lt;p&gt;Maintainers of one-line typo fixes do not need an oracle directory sitting in the review. Security patches that should not advertise exploit details in before and after logs should use a private disclosure channel instead of this packet. Contributors without a failing invocation, including design debates and API proposals, should write a decision record rather than invent a fake output pair.&lt;/p&gt;

&lt;p&gt;Teams that already have a golden-test harness covering the same invocation can point the pull request at that harness and skip the extra files. The principle remains even then: declare the delta, prove it on both sides of the patch, and keep the proof next to the diff. Chat summaries disappear; replayable bytes do not.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>git</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
