<?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: Quinn Zhu</title>
    <description>The latest articles on DEV Community by Quinn Zhu (@gitgo_5662).</description>
    <link>https://dev.to/gitgo_5662</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%2F4064033%2F3b8164f8-c06e-456b-a431-d2555ccc9ea9.png</url>
      <title>DEV Community: Quinn Zhu</title>
      <link>https://dev.to/gitgo_5662</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gitgo_5662"/>
    <language>en</language>
    <item>
      <title>Let the Existing Tests Choose Your First PR</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Tue, 27 Oct 2026 13:22:48 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/let-the-existing-tests-choose-your-first-pr-1in6</link>
      <guid>https://dev.to/gitgo_5662/let-the-existing-tests-choose-your-first-pr-1in6</guid>
      <description>&lt;p&gt;Your first pull request should be chosen by a test, not by curiosity.&lt;/p&gt;

&lt;p&gt;Curiosity sends you to the files that are fun to read. Tests send you to the files that are safe to change. On day one you cannot tell those apart by reading alone.&lt;/p&gt;

&lt;p&gt;This drill takes about an hour. It ends with one small PR and a baseline you can actually trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0 — Fix your question in one sentence
&lt;/h2&gt;

&lt;p&gt;Write the question down before you open a single source file.&lt;/p&gt;

&lt;p&gt;A usable question looks like this: "Does &lt;code&gt;invoice_total()&lt;/code&gt; include tax on refunds?" A useless one looks like: "How does billing work?" The first can be answered by a test. The second can absorb your whole week.&lt;/p&gt;

&lt;p&gt;Keep the question where you will see it. A line at the top of your scratch branch is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Map which tests already name your file
&lt;/h2&gt;

&lt;p&gt;Pick one candidate file. Then let git tell you who already checks its behavior.&lt;/p&gt;

&lt;p&gt;Save this as &lt;code&gt;name-the-test.sh&lt;/code&gt; in your scratch clone:&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;# name-the-test.sh — find the tests that already mention a file you want to change.&lt;/span&gt;
&lt;span class="c"&gt;# usage: ./name-the-test.sh src/billing/invoice.py&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;target&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;:?usage:&lt;span class="p"&gt; name-the-test.sh &amp;lt;path/to/file&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;stem&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;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"--- test files mentioning '&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;stem&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' ---"&lt;/span&gt;
git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&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;stem&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;'*test*'&lt;/span&gt; &lt;span class="s1"&gt;'*spec*'&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"(none)"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"--- tracked files in the same family ---"&lt;/span&gt;
git ls-files | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&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;stem&lt;/span&gt;&lt;span class="k"&gt;}&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;-i&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; spec &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"(none)"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"--- last three commits touching the file ---"&lt;/span&gt;
git log &lt;span class="nt"&gt;-3&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;short &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'%h %ad %s'&lt;/span&gt; &lt;span class="nt"&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;target&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;Run it against three candidate files, not one. You want options, not a commitment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./name-the-test.sh src/billing/invoice.py
./name-the-test.sh src/billing/refund.py
./name-the-test.sh src/billing/tax_rules.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a file returns zero test references, drop it. A file nobody tests is a file where your mistake is invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Run only those tests, and save the output
&lt;/h2&gt;

&lt;p&gt;Do not guess the test command. Copy it from the repository's own CI config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;-A3&lt;/span&gt; &lt;span class="s1"&gt;'run:'&lt;/span&gt; .github/workflows/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; pytest &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'npm test'&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'go test'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the single file you found, and write the output to disk:&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/billing/test_invoice.py &lt;span class="nt"&gt;-q&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tee&lt;/span&gt; /tmp/baseline.txt
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5 /tmp/baseline.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That file is now your baseline. Green or red, you know the starting state. Most first-PR confusion comes from never having captured it.&lt;/p&gt;

&lt;p&gt;If the run fails on import errors rather than assertions, stop. You have an environment problem, not a code problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Turn your question into one assertion
&lt;/h2&gt;

&lt;p&gt;Add a single test that answers your Step 0 sentence. Not three tests. One.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_refund_total_excludes_tax&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;invoice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refunded&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;assert&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;total&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it. It should fail, and the failure message should be readable enough for a stranger.&lt;/p&gt;

&lt;p&gt;If the assertion cannot be written without mocking five collaborators, your question is too big. Shrink it until the test fits on one screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Make the smallest change that flips the test
&lt;/h2&gt;

&lt;p&gt;One rule keeps first PRs reviewable: at most three files change, and one of them is the test.&lt;/p&gt;

&lt;p&gt;If the fix needs a fourth file, split the ticket. State the split in the PR description rather than expanding scope quietly. Reviewers forgive small PRs and small questions; they rarely forgive a surprise refactor.&lt;/p&gt;

&lt;p&gt;Re-run the baseline file after the change. Compare with &lt;code&gt;/tmp/baseline.txt&lt;/code&gt; and confirm you moved only the test you meant to move.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — When your laptop cannot run the suite
&lt;/h2&gt;

&lt;p&gt;Some first days die on environment setup. Python 3.6 on a work laptop, an ARM machine, a Windows shell against a Linux-only suite. The drill above stalls at Step 2 through no fault of yours.&lt;/p&gt;

&lt;p&gt;This is where I keep a disposable workspace instead of a permanent one. MonkeyCode offers free model access and a free server option, which is enough for a single-file test run and a failure explanation. Disclosure: This article was prepared as part of MonkeyCode's product outreach.&lt;/p&gt;

&lt;p&gt;Two habits make that safe:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send the &lt;strong&gt;failure output&lt;/strong&gt;, not the whole file. Paste the traceback and the test name into the model. Ask "what does this assertion say about the code?" not "rewrite this module."&lt;/li&gt;
&lt;li&gt;Keep the free server &lt;strong&gt;ephemeral&lt;/strong&gt;. Clone, run, copy the log back, throw the workspace away. Anything you would not put in a public gist does not belong there.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am deliberately not quoting quota numbers or machine specs. Free tiers move, and a number printed in a blog post is stale within weeks. Check the project's own page on the day you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision table
&lt;/h2&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 clone&lt;/th&gt;
&lt;th&gt;Free server workspace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Suite runs in under 2 minutes&lt;/td&gt;
&lt;td&gt;Use local&lt;/td&gt;
&lt;td&gt;Unnecessary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suite needs a Linux-only binary&lt;/td&gt;
&lt;td&gt;Skip&lt;/td&gt;
&lt;td&gt;Reasonable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repo has secrets in &lt;code&gt;.env&lt;/code&gt; fixtures&lt;/td&gt;
&lt;td&gt;Use local only&lt;/td&gt;
&lt;td&gt;Do not use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You only need one test file&lt;/td&gt;
&lt;td&gt;Use local&lt;/td&gt;
&lt;td&gt;Fine either way&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need a long-lived CI replacement&lt;/td&gt;
&lt;td&gt;Build real CI&lt;/td&gt;
&lt;td&gt;Not this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want to read a stack trace with help&lt;/td&gt;
&lt;td&gt;Use local&lt;/td&gt;
&lt;td&gt;Acceptable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Treat the free server as a place to answer one question. The moment it becomes your only way to run tests, you have a dependency, not a tool.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;name-the-test.sh&lt;/code&gt; is a grep heuristic. Dynamic imports, string-built module names, and reflection-based frameworks will hide tests from it. If it returns &lt;code&gt;(none)&lt;/code&gt; for a file you know is covered, trust the code and check by hand.&lt;/p&gt;

&lt;p&gt;It also assumes a test suite exists. Repositories with no tests need a different first hour, and that is a fair reason to ask your mentor before starting.&lt;/p&gt;

&lt;p&gt;Finally, this drill will not teach you architecture. It teaches you where the safety net is. Reading the module top-to-bottom still has to happen, just not before you know which behavior someone already promised to protect.&lt;/p&gt;

&lt;p&gt;If you try one thing from this post, try the ordered steps: question, grep, baseline, one assertion, one small diff. If your machine fights you on step two, the free server option is the lowest-stakes place to start.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>testing</category>
      <category>git</category>
      <category>ai</category>
    </item>
    <item>
      <title>Score the File, Not the Prompt: A Week-One Triage Table for AI-Assisted PRs</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Mon, 26 Oct 2026 11:54:16 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/score-the-file-not-the-prompt-a-week-one-triage-table-for-ai-assisted-prs-1djl</link>
      <guid>https://dev.to/gitgo_5662/score-the-file-not-the-prompt-a-week-one-triage-table-for-ai-assisted-prs-1djl</guid>
      <description>&lt;p&gt;Give the model a ticket only after you score the file.&lt;/p&gt;

&lt;p&gt;Most juniors do it backwards. They paste the ticket, accept a patch, then try to understand it. On day one that order costs you your rollback.&lt;/p&gt;

&lt;p&gt;This post gives you a small triage script, a decision table, and a baseline test loop. You run all three inside your first hour. The artifact is the point, not the opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  The risky window is week one
&lt;/h2&gt;

&lt;p&gt;The tooling changed fast this year. Juniors now open real tickets with an agent in the loop from day two. That is fine, if you gate the loop with evidence.&lt;/p&gt;

&lt;p&gt;My rule is simple. Score the file before you score the prompt. A patch is only as safe as the code it touches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Measure the blast radius
&lt;/h2&gt;

&lt;p&gt;Run this on the file you plan to edit. It uses only &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, and &lt;code&gt;find&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# triage.sh - rate a file's blast radius before you take the ticket&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;file&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;:?usage:&lt;span class="p"&gt; triage.sh path/to/file [since]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;since&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;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;90&lt;/span&gt;&lt;span class="p"&gt;.days.ago&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;stem&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;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;churn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$since&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;%H &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&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;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;owners&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$since&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;%ae &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&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;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;refs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-RIl&lt;/span&gt; &lt;span class="nt"&gt;--exclude-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.git &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'*.ts'&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'*.js'&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'*.py'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$stem&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&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;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-path&lt;/span&gt; ./.git &lt;span class="nt"&gt;-prune&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;stem&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;*test*"&lt;/span&gt; &lt;span class="nt"&gt;-print&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&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;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'file=%s\nchurn=%s\nowners=%s\nreferences=%s\ntest_files=%s\n'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$churn&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$owners&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$refs&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$tests&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable and run it on your candidate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x triage.sh
./triage.sh src/billing/invoice.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sample output from a small service I worked in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file=src/billing/invoice.ts
churn=14
owners=5
references=9
test_files=2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read it like this. High churn means the file moves under you. Many owners means no single reviewer knows the whole file. Many references means your typo becomes someone else's outage.&lt;/p&gt;

&lt;p&gt;Treat the script as a rough instrument. It measures motion, not correctness. Zero test files is the loudest signal in the output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Turn the numbers into a decision
&lt;/h2&gt;

&lt;p&gt;Do not negotiate with yourself. Map the score to one of three lanes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signals&lt;/th&gt;
&lt;th&gt;Lane&lt;/th&gt;
&lt;th&gt;Who edits&lt;/th&gt;
&lt;th&gt;Evidence before PR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tests &amp;gt;= 1, owners &amp;lt;= 2, references &amp;lt;= 3&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;You, with a model draft&lt;/td&gt;
&lt;td&gt;Baseline test log, diff under 60 lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tests &amp;gt;= 1, but owners &amp;gt;= 3 or references &amp;gt;= 6&lt;/td&gt;
&lt;td&gt;Amber&lt;/td&gt;
&lt;td&gt;Model drafts, you rewrite&lt;/td&gt;
&lt;td&gt;Named reviewer, per-hunk explanation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tests = 0, or references &amp;gt;= 10, or churn is spiking&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;Senior pairs with you&lt;/td&gt;
&lt;td&gt;Written rollback plan first&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Red does not mean forbidden. It means you do not learn on the expensive file. Take a green ticket first, then ask for the red one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Write the ticket contract in one paragraph
&lt;/h2&gt;

&lt;p&gt;Before any prompt, write five lines in the ticket. File, function, expected behaviour, test command, and what must not change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File: src/billing/invoice.ts
Function: applyDiscount()
Expected: rounding stays half-up, no new exports
Test: npm test -- invoice
Must not change: public signature, error messages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the model gets a boundary, not a wish. If it returns code that violates line five, you reject it in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Prove the loop before the edit
&lt;/h2&gt;

&lt;p&gt;Run the test command and save the output. This is your baseline, and it is the only honest reference you have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; invoice 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tee&lt;/span&gt; /tmp/base.log
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'passing|failing'&lt;/span&gt; /tmp/base.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the suite is already red, stop. A red baseline hides your regression inside someone else's failure.&lt;/p&gt;

&lt;p&gt;After the patch, run the same command against the same log target. Compare counts, not vibes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; invoice 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tee&lt;/span&gt; /tmp/after.log
diff &amp;lt;&lt;span class="o"&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;'passing|failing'&lt;/span&gt; /tmp/base.log&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &amp;lt;&lt;span class="o"&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;'passing|failing'&lt;/span&gt; /tmp/after.log&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identical counts plus your new test passing is a shippable result. Anything else is a conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Set the hunk budget and the rollback line
&lt;/h2&gt;

&lt;p&gt;Cap the diff before you open the editor. Forty lines for a first ticket is plenty. Sixty is the ceiling on green files.&lt;/p&gt;

&lt;p&gt;Write the revert command in the PR description. It takes ten seconds and saves an hour.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git revert &lt;span class="nt"&gt;--no-commit&lt;/span&gt; &amp;lt;sha&amp;gt;
git diff &lt;span class="nt"&gt;--cached&lt;/span&gt; &lt;span class="nt"&gt;--stat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you cannot name the sha you would revert, you do not understand the patch yet. Read the diff again before you request review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where free model access and a free server actually help
&lt;/h2&gt;

&lt;p&gt;A junior needs volume, and volume is where budgets bite. Explaining unfamiliar files, drafting a failing test, and re-reading your own diff are high-frequency, low-risk uses. This is exactly the workload free model access fits.&lt;/p&gt;

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

&lt;p&gt;Two operator-supplied details matter here. The project offers free model access, and it offers a free server option. The operator also describes a free allowance of 10 million tokens; confirm the current terms yourself, because allowances change and I am not quoting a benchmark. I have not measured speed, model quality, or uptime, and I am not claiming any.&lt;/p&gt;

&lt;p&gt;The free server option helps in one concrete way. Your laptop keeps its toolchain, and the build-and-test loop runs elsewhere. That is a real convenience when &lt;code&gt;npm install&lt;/code&gt; fights your local Node version.&lt;/p&gt;

&lt;p&gt;One rule, no exceptions. Do not paste secrets, customer data, or internal credentials into any hosted model. Read your employer's policy before your first prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and who should skip this
&lt;/h2&gt;

&lt;p&gt;This workflow is honest about what it cannot do.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Churn is not risk. A quiet file can still hold the payment path.&lt;/li&gt;
&lt;li&gt;The script misses dynamic references: reflection, string lookups, config-driven wiring.&lt;/li&gt;
&lt;li&gt;Test file counts lie in monorepos with shared fixtures.&lt;/li&gt;
&lt;li&gt;Free tiers change. Re-verify terms on the day you rely on them.&lt;/li&gt;
&lt;li&gt;A model draft is not a review. You still own every line you commit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Skip this approach if your repo has no test command at all. Fix that first; a model will only make the chaos faster.&lt;/p&gt;

&lt;p&gt;Skip it too if you cannot read the language fluently yet. Learn the file by hand for a week, then add the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your first-hour checklist
&lt;/h2&gt;

&lt;p&gt;Run the script on two candidate files. Pick the green one. Write the five-line contract. Capture the baseline log. Draft with the model, then rewrite at least one hunk yourself.&lt;/p&gt;

&lt;p&gt;That last step is the whole method. You are not shipping model output. You are shipping a change you can explain, test, and revert.&lt;/p&gt;

&lt;p&gt;If you run the triage table on your own repo, keep your real thresholds in the PR description. The next junior will thank you for the numbers.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>ai</category>
      <category>git</category>
      <category>testing</category>
    </item>
    <item>
      <title>Rehearse the Rollback Before You Ship the Patch: A Day-One Git Drill</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Tue, 20 Oct 2026 10:04:29 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/rehearse-the-rollback-before-you-ship-the-patch-a-day-one-git-drill-59mj</link>
      <guid>https://dev.to/gitgo_5662/rehearse-the-rollback-before-you-ship-the-patch-a-day-one-git-drill-59mj</guid>
      <description>&lt;h1&gt;
  
  
  Rehearse the Rollback Before You Ship the Patch
&lt;/h1&gt;

&lt;p&gt;Your first pull request should be one you can undo in five minutes.&lt;/p&gt;

&lt;p&gt;Most onboarding advice stops at "get the build running." That is step zero. The step that protects you is a rollback rehearsal. You practice undoing a patch while nobody is on call.&lt;/p&gt;

&lt;p&gt;This drill uses git, a throwaway remote, and one small patch. You measure time-to-green on three undo paths. You leave with a table, not a feeling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why rehearse undoing work you have not shipped
&lt;/h2&gt;

&lt;p&gt;Patches arrive fast now. Reviewing an agent patch is one skill. Undoing it is a different skill, and a calmer one.&lt;/p&gt;

&lt;p&gt;If your team already merges agent-generated patches, you will be asked to revert one eventually. First-time reverts under pressure teach the wrong lesson. A sandbox branch teaches the right one.&lt;/p&gt;

&lt;p&gt;The drill also exposes something useful about your new repo. You learn which test command is real, how long green takes, and where the seams are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Define "green" before you touch anything
&lt;/h2&gt;

&lt;p&gt;Copy the exact command CI runs. Do not invent your own.&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;# .drill/test-command&lt;/span&gt;
./scripts/test.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that command takes longer than ten minutes, subset it. A drill that costs an hour never gets repeated. Pick the fastest command that still fails when the patch breaks behavior.&lt;/p&gt;

&lt;p&gt;Write the command down before the drill. Changing it midway invalidates every number you collect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Move the drill onto a disposable remote
&lt;/h2&gt;

&lt;p&gt;Never rehearse in the repo your team deploys from. A scratch clone is the minimum. A scratch remote is better.&lt;/p&gt;

&lt;p&gt;This is where a free server option fits. Treat it as a sandbox for throwaway branches. Assume it can vanish, and assume it is not a place for secrets.&lt;/p&gt;

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

&lt;p&gt;MonkeyCode offers free model access and a free server option, and its team describes it as an open-source project. That is how you can generate the patch and host the scratch remote here. Delete every MonkeyCode mention and the git commands below still work unchanged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Generate one small, believable patch
&lt;/h2&gt;

&lt;p&gt;Ask for a bounded change. A 30-line diff reverts cleanly. A 400-line diff teaches you conflict resolution, not rollback.&lt;/p&gt;

&lt;p&gt;Prompt template you can reuse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Change exactly one function in &amp;lt;file&amp;gt;.
Constraints: no new dependencies, no more than 30 changed lines.
Output a unified diff only, no prose.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the output as &lt;code&gt;patch.diff&lt;/code&gt;. Reject it if it touches more than two files. Reject it again if it adds a dependency. Small patches keep the drill honest.&lt;/p&gt;

&lt;p&gt;The patch does not need to be good. It needs to apply, pass tests, and be reversible. That is the whole bar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Script the rehearsal
&lt;/h2&gt;

&lt;p&gt;Save this as &lt;code&gt;rollback-drill.sh&lt;/code&gt;. Run it from anywhere except a worktree you care about.&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;# rollback-drill.sh &amp;lt;repo-url&amp;gt; &amp;lt;patch-file&amp;gt;&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;REPO_URL&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;:?repo&lt;span class="p"&gt; url required&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;PATCH&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;2&lt;/span&gt;:?patch&lt;span class="p"&gt; file required&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;TEST_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TEST_CMD&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;./scripts/test.sh&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;WORK&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;&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="nv"&gt;$WORK&lt;/span&gt;&lt;span class="s2"&gt;/timings.md"&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'| path | result |\n|---|---|\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

timed&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c"&gt;# timed &amp;lt;label&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; start end
  &lt;span class="nv"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEST_CMD&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="nv"&gt;$WORK&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;.log"&lt;/span&gt; 2&amp;gt;&amp;amp;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'| %s | %ss to green |\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;end &lt;span class="o"&gt;-&lt;/span&gt; start&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'| %s | RED (see %s.log) |\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 50 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORK&lt;/span&gt;&lt;span class="s2"&gt;/repo"&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;$WORK&lt;/span&gt;&lt;span class="s2"&gt;/repo"&lt;/span&gt;
git config user.email drill@example.com
git config user.name drill

git switch &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; drill/base
timed baseline

git switch &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; drill/patch
git apply &lt;span class="nt"&gt;--3way&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PATCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
git add &lt;span class="nt"&gt;-A&lt;/span&gt;
git commit &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"drill: apply patch"&lt;/span&gt;
timed patched

&lt;span class="c"&gt;# Path A: revert the commit, history stays readable&lt;/span&gt;
git switch &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; drill/revert drill/patch
git revert &lt;span class="nt"&gt;--no-edit&lt;/span&gt; HEAD &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
timed revert

&lt;span class="c"&gt;# Path B: drop the commit entirely&lt;/span&gt;
git switch &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; drill/reset drill/patch
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt; drill/base
timed reset

&lt;span class="c"&gt;# Path C: kill switch, code stays where it is&lt;/span&gt;
git switch &lt;span class="nt"&gt;--quiet&lt;/span&gt; drill/patch
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FEATURE_AGENT_PATCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;off
timed flag_off

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&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;"logs in &lt;/span&gt;&lt;span class="nv"&gt;$WORK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two notes before you run it. Path C only means something if the patch sits behind a flag. If there is no flag, drop that block and record &lt;code&gt;n/a&lt;/code&gt; in your table. And &lt;code&gt;--depth 50&lt;/code&gt; keeps a monorepo clone tolerable; remove it if your repo needs full history to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Run each path three times
&lt;/h2&gt;

&lt;p&gt;One run measures your laptop, not your repo. Three runs show you the noise floor.&lt;/p&gt;

&lt;p&gt;If baseline swings by more than a minute, stop. Your suite is flaky, and every later number is decoration. Fix the flake or pick a narrower test command.&lt;/p&gt;

&lt;p&gt;Expected shape of the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| path      | result          |
|-----------|-----------------|
| baseline  | 42s to green    |
| patched   | 44s to green    |
| revert    | 45s to green    |
| reset     | 41s to green    |
| flag_off  | RED (see flag_off.log) |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A red &lt;code&gt;flag_off&lt;/code&gt; row is a real finding. The kill switch does not fully disable the change, or your test command ignores the flag. Both are worth knowing on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Read the table like a reviewer
&lt;/h2&gt;

&lt;p&gt;Compare paths on the same machine only. Wall-clock seconds are not portable across hardware.&lt;/p&gt;

&lt;p&gt;Look for two signals. First, does any undo path take longer than the patch took to write? Second, does &lt;code&gt;reset&lt;/code&gt; beat &lt;code&gt;revert&lt;/code&gt; by a wide margin? If yes, you now know why people reach for dangerous commands under pressure.&lt;/p&gt;

&lt;p&gt;That gap is the real lesson. &lt;code&gt;revert&lt;/code&gt; preserves history and costs conflict resolution. &lt;code&gt;reset&lt;/code&gt; is fast and throws work away.&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;Situation&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;th&gt;Watch out&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Patch is already pushed to a shared branch&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git revert&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Others keep a readable history&lt;/td&gt;
&lt;td&gt;Later commits on the same lines conflict&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patch is local and unpushed&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git reset --hard base&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fastest clean tree&lt;/td&gt;
&lt;td&gt;Silently discards uncommitted work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patch sits behind a flag&lt;/td&gt;
&lt;td&gt;flip the flag&lt;/td&gt;
&lt;td&gt;Seconds, no deploy&lt;/td&gt;
&lt;td&gt;Flag debt, and the off-path is untested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patch includes a migration&lt;/td&gt;
&lt;td&gt;neither, escalate&lt;/td&gt;
&lt;td&gt;Code revert is not data revert&lt;/td&gt;
&lt;td&gt;You need a restore plan first&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Print this table into your onboarding notes. Rewrite it when your repo proves it wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failure modes that make the numbers lie
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Migrations.&lt;/strong&gt; Reverting code leaves the schema changed. If &lt;code&gt;patch.diff&lt;/code&gt; touches a migration, the drill measures the wrong thing entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cached artifacts.&lt;/strong&gt; A stale build directory makes &lt;code&gt;reset&lt;/code&gt; look faster than it is. Clear the cache before each run, or run baseline twice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uncommitted work.&lt;/strong&gt; &lt;code&gt;reset --hard&lt;/code&gt; does not ask. Run the script in the temp clone, never in your working tree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrong test command.&lt;/strong&gt; If the drill's command differs from CI, you are timing a rehearsal of a rehearsal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and who should skip this
&lt;/h2&gt;

&lt;p&gt;You need a test command that finishes in minutes and fails for the right reasons. Without one, build a smoke test first. This drill will not save you.&lt;/p&gt;

&lt;p&gt;Skip it if policy forbids pushing repo content to third-party hosts. Run everything locally instead; the script works the same. Skip it if your rollback procedure is a documented incident process with named owners. Training must not shadow the real runbook.&lt;/p&gt;

&lt;p&gt;Skip it in monorepos you cannot clone cheaply. A partial clone is fine. A forty-minute clone is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terms snapshot you should verify yourself
&lt;/h2&gt;

&lt;p&gt;Operator-supplied and not independently verified: free model access, a free server option, and a listed allowance of 10 million tokens. Quotas and terms change without notice. Read the project's current page before you plan any workflow around them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Close the loop
&lt;/h2&gt;

&lt;p&gt;Run the drill once. Keep the timing table in your onboarding notes.&lt;/p&gt;

&lt;p&gt;If you try it on a throwaway remote, the free server option saves you from polluting your laptop. Paste your slowest undo path in the comments. A five-minute revert is a team asset, and now you know yours.&lt;/p&gt;

</description>
      <category>git</category>
      <category>ai</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Day One: Prove the Build Before You Take the Ticket</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Mon, 19 Oct 2026 08:43:48 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/day-one-prove-the-build-before-you-take-the-ticket-45cf</link>
      <guid>https://dev.to/gitgo_5662/day-one-prove-the-build-before-you-take-the-ticket-45cf</guid>
      <description>&lt;p&gt;Your first hour should prove the build. It should not be reading source code.&lt;/p&gt;

&lt;p&gt;Most juniors start onboarding by opening files. That feels productive. It produces opinions, not evidence.&lt;/p&gt;

&lt;p&gt;A build that fails on your machine tells you nothing about the code. It tells you about your machine. The fix belongs in a written environment probe, not in a chat thread.&lt;/p&gt;

&lt;p&gt;This post gives you that probe. It takes about twenty minutes. It ends with your first PR and a rehearsed rollback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the probe comes first
&lt;/h2&gt;

&lt;p&gt;A failing test on day one has three possible owners. The repo, the toolchain, or you.&lt;/p&gt;

&lt;p&gt;You cannot tell them apart from memory. You can tell them apart from a log with versions, commands, and exit codes.&lt;/p&gt;

&lt;p&gt;Write the log once. Reuse it for every future "works on my machine" argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Build a disposable workspace
&lt;/h2&gt;

&lt;p&gt;Do not probe inside your real clone. Use a throwaway directory or a temporary sandbox.&lt;/p&gt;

&lt;p&gt;This is where a free server option is genuinely useful. A disposable host gives you a clean OS with no leftover global installs.&lt;/p&gt;

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

&lt;p&gt;MonkeyCode offers free model access and a free server option, per the operator. I am not asserting specs, quotas, uptime, or permanence here. Treat both as conveniences, not guarantees.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/probe &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/probe
git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 &amp;lt;repo-url&amp;gt; app
&lt;span class="nb"&gt;cd &lt;/span&gt;app
git rev-parse &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD   &lt;span class="c"&gt;# record this in your notes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record the commit hash. A probe without a commit hash is a rumor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Write &lt;code&gt;probe.sh&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is a template. It is not tested against your repo. Adjust the install and test commands to match your &lt;code&gt;README&lt;/code&gt; and CI config.&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;# probe.sh - day-one environment probe (template)&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;OUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"env-probe.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="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
log&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&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; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

log &lt;span class="s2"&gt;"== commit: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; =="&lt;/span&gt;
log &lt;span class="s2"&gt;"== time:   &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +%FT%TZ&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; =="&lt;/span&gt;
log &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;-srm&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
log &lt;span class="s2"&gt;"shell:  &lt;/span&gt;&lt;span class="nv"&gt;$BASH_VERSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;bin &lt;span class="k"&gt;in &lt;/span&gt;git node npm python3 go java docker&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  if &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$bin&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$bin&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="nv"&gt;$bin&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--version&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;log &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$bin&lt;/span&gt;&lt;span class="s2"&gt;: MISSING"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done

&lt;/span&gt;log &lt;span class="s2"&gt;"== install =="&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; package-lock.json &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;npm ci &lt;span class="nt"&gt;--no-audit&lt;/span&gt; &lt;span class="nt"&gt;--no-fund&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 20 | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;log &lt;span class="s2"&gt;"== test (300s cap) =="&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; +e
&lt;span class="nb"&gt;timeout &lt;/span&gt;300 npm &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--silent&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 40 | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PIPESTATUS&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
log &lt;span class="s2"&gt;"test exit: &lt;/span&gt;&lt;span class="nv"&gt;$code&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

log &lt;span class="s2"&gt;"== end =="&lt;/span&gt;
&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two design choices matter here. The &lt;code&gt;timeout&lt;/code&gt; cap stops a hung watcher from eating your morning. The &lt;code&gt;tail&lt;/code&gt; cap keeps the log small enough to read and share.&lt;/p&gt;

&lt;p&gt;The script always exits zero. It is a reporter, not a gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Read the verdict, not the vibes
&lt;/h2&gt;

&lt;p&gt;Run it and classify the result before you ask anyone for help.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x probe.sh &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./probe.sh
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'MISSING|test exit'&lt;/span&gt; env-probe.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;test exit&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Missing tools&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Your next action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;Take the ticket, link &lt;code&gt;env-probe.txt&lt;/code&gt; in it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;non-zero&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Amber&lt;/td&gt;
&lt;td&gt;Reproduce once in the sandbox, then compare logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;one or more&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;Fix the toolchain first, do not touch code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Green is common and boring. Good. Boring means the repo is not your problem today.&lt;/p&gt;

&lt;p&gt;Amber is the interesting case. It means the failure is real and reproducible, which makes it a legitimate ticket.&lt;/p&gt;

&lt;p&gt;Red is a setup bug wearing a code bug costume. Half of "the tests are broken" reports die here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Delegate only the log reading
&lt;/h2&gt;

&lt;p&gt;The slow part of onboarding is not typing commands. It is squinting at 40 lines of noise.&lt;/p&gt;

&lt;p&gt;This is a reasonable place to use free model access. The task is bounded, the input is small, and a wrong answer is cheap to detect.&lt;/p&gt;

&lt;p&gt;Do not ask for a patch. Ask for a classification.&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 triaging a build log. Do not propose code changes.
Input: the last 40 lines below.
Output exactly three lines:
FAILURE_CLASS: &amp;lt;missing-tool | dependency | test-assert | network | unknown&amp;gt;
FIRST_BAD_LINE: &amp;lt;verbatim line&amp;gt;
NEXT_COMMAND: &amp;lt;one shell command to run&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the &lt;code&gt;NEXT_COMMAND&lt;/code&gt; yourself. If it does not move the log forward, the classification was wrong and you learned that in one step.&lt;/p&gt;

&lt;p&gt;Keep the model's output in your notes with the commit hash. Unlabeled model output is not evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Make the probe your first PR
&lt;/h2&gt;

&lt;p&gt;Your first PR should be small, reversible, and additive. &lt;code&gt;probe.sh&lt;/code&gt; plus &lt;code&gt;env-probe.txt&lt;/code&gt; is all three.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; chore/env-probe
git add probe.sh env-probe.txt
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: add day-one environment probe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the PR body, state three things. The commit hash you probed. The verdict from the table. The one command a reviewer should run to confirm.&lt;/p&gt;

&lt;p&gt;Do not bundle a source change into this PR. Reviewers forgive a noisy artifact. They do not forgive a mixed diff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Rehearse the rollback now
&lt;/h2&gt;

&lt;p&gt;You will need a rollback eventually. Practice it while the stakes are zero.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git revert &lt;span class="nt"&gt;--no-edit&lt;/span&gt; &amp;lt;merge-or-commit-sha&amp;gt;
git push origin chore/env-probe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If CI rejects the probe script, revert it and say so in the thread. That is a successful onboarding step, not a failure.&lt;/p&gt;

&lt;p&gt;You now know the revert command, the review path, and the CI turnaround time. That knowledge is worth more than the script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and who should skip this
&lt;/h2&gt;

&lt;p&gt;A sandbox probe proves a fresh environment. It does not prove production behavior, data shape, or service dependencies.&lt;/p&gt;

&lt;p&gt;The free server option suits exploration. It is not a substitute for a pinned CI runner or a reproducible container image your team controls.&lt;/p&gt;

&lt;p&gt;Skip this approach if any of the following is true.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your repo needs credentials or production data to build. Do not paste those into a shared sandbox.&lt;/li&gt;
&lt;li&gt;Your organization forbids sending logs to hosted models. Ask first, and use a local model if approved.&lt;/li&gt;
&lt;li&gt;Your build needs GPUs, large services, or hours of compilation. Use the team's real CI instead.&lt;/li&gt;
&lt;li&gt;You need guaranteed capacity. Free tiers change; plan around that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also skip the model step entirely if the log is short. Ten lines of output do not need triage help.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you actually learned
&lt;/h2&gt;

&lt;p&gt;You learned the build before the code. You learned the revert before the mistake.&lt;/p&gt;

&lt;p&gt;That order is deliberate. Juniors who learn rollback first take bigger, safer steps later.&lt;/p&gt;

&lt;p&gt;If you want a zero-cost place to run the probe, MonkeyCode's free model access and free server option are a reasonable starting point. Verify the current terms yourself before you depend on them.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Timebox Your First PR: A 90-Minute Onboarding Log for New Repos</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Fri, 16 Oct 2026 05:26:26 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/timebox-your-first-pr-a-90-minute-onboarding-log-for-new-repos-3p1e</link>
      <guid>https://dev.to/gitgo_5662/timebox-your-first-pr-a-90-minute-onboarding-log-for-new-repos-3p1e</guid>
      <description>&lt;p&gt;Most first PRs fail for process reasons, not coding reasons.&lt;/p&gt;

&lt;p&gt;The fix is cheap. Log your first 90 minutes in a new repo. Then attach that log to your first pull request.&lt;/p&gt;

&lt;p&gt;This post gives you a small bash script, a timebox table, and explicit stop rules. It also explains where a free cloud box fits when your laptop cannot reproduce CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why hour one decides your first PR
&lt;/h2&gt;

&lt;p&gt;You join a repo you have never run. You read code for two hours. You patch something small. Tests pass locally, then fail during review.&lt;/p&gt;

&lt;p&gt;The reviewer asks one question. "What was the baseline?" You do not know.&lt;/p&gt;

&lt;p&gt;That is the entire failure. The order was wrong, not your skill.&lt;/p&gt;

&lt;p&gt;So flip the order. Record first, patch second. Your log becomes evidence a reviewer can replay.&lt;/p&gt;

&lt;p&gt;Agent tooling keeps improving. Onboarding discipline has not kept up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The artifact: a JSONL onboarding log
&lt;/h2&gt;

&lt;p&gt;Save this file as &lt;code&gt;onboard-log.sh&lt;/code&gt; on a scratch 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;# onboard-log.sh - append JSONL breadcrumbs during your first repo day.&lt;/span&gt;
&lt;span class="c"&gt;# Usage:&lt;/span&gt;
&lt;span class="c"&gt;#   ./onboard-log.sh fingerprint&lt;/span&gt;
&lt;span class="c"&gt;#   TEST_CMD="npm test" ./onboard-log.sh baseline&lt;/span&gt;
&lt;span class="c"&gt;#   ./onboard-log.sh note "auth tests need redis on 6379"&lt;/span&gt;
&lt;span class="c"&gt;#   ./onboard-log.sh report&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-uo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;LOG&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;ONBOARD_LOG&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;onboard&lt;/span&gt;&lt;span class="p"&gt;.jsonl&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;PHASE&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;report&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="nv"&gt;TEST_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TEST_CMD&lt;/span&gt;&lt;span class="k"&gt;:-}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;BASELINE_LOG&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;TMPDIR&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;/tmp&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/onboard.baseline.log"&lt;/span&gt;

iso&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +&lt;span class="s2"&gt;"%Y-%m-%dT%H:%M:%SZ"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
sha&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; git rev-parse &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;no-git&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

emit&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;              &lt;span class="c"&gt;# $1 phase, then raw key=value pairs&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;phase&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;shift
  local &lt;/span&gt;&lt;span class="nv"&gt;extra&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;kv &lt;span class="k"&gt;in&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$kv&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;extra&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$extra&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;kv&lt;/span&gt;&lt;span class="p"&gt;%%=*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;kv&lt;/span&gt;&lt;span class="p"&gt;#*=&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;done
  &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'{"at":"%s","phase":"%s","head":"%s"%s}\n'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;iso&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$phase&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;sha&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$extra&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PHASE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
  &lt;/span&gt;fingerprint&lt;span class="p"&gt;)&lt;/span&gt;
    emit fingerprint &lt;span class="s2"&gt;"bash=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_VERSION&lt;/span&gt;&lt;span class="p"&gt;%%(*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"node=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;node &lt;span class="nt"&gt;-v&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;none&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;;;&lt;/span&gt;
  baseline&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEST_CMD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"set TEST_CMD first"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;2&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;t0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;
    bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEST_CMD&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="nv"&gt;$BASELINE_LOG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;&amp;amp;1
    &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
    emit baseline &lt;span class="s2"&gt;"exit=&lt;/span&gt;&lt;span class="nv"&gt;$code&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"secs=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; t0 &lt;span class="k"&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;"baseline exit=&lt;/span&gt;&lt;span class="nv"&gt;$code&lt;/span&gt;&lt;span class="s2"&gt;  log=&lt;/span&gt;&lt;span class="nv"&gt;$BASELINE_LOG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;;;&lt;/span&gt;
  note&lt;span class="p"&gt;)&lt;/span&gt;
    emit note &lt;span class="s2"&gt;"note=&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="s2"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;;;&lt;/span&gt;
  report&lt;span class="p"&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;$LOG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"no log yet"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="s1"&gt;'{for(i=1;i&amp;lt;=NF;i++) if($i=="phase") print $(i+2)}'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
    &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"phases: fingerprint baseline note report"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;2 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four phases, four commands. Run them in this order.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fingerprint the machine before you read any code.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./onboard-log.sh fingerprint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Branch from main and record the baseline on a clean checkout.
&lt;/li&gt;
&lt;/ol&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;-c&lt;/span&gt; onboard/scratch main
&lt;span class="nv"&gt;TEST_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"npm test"&lt;/span&gt; ./onboard-log.sh baseline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Write notes while reading. Do not edit product code yet.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./onboard-log.sh note &lt;span class="s2"&gt;"auth suite needs redis on 6379"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Print the summary before you open the PR.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./onboard-log.sh report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The report prints one count per phase plus the last entry. A reviewer can replay your first hour in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timebox the day in five windows
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Window&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Exit condition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0-20 min&lt;/td&gt;
&lt;td&gt;fingerprint + find the test entry point&lt;/td&gt;
&lt;td&gt;you can name the test command&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20-35 min&lt;/td&gt;
&lt;td&gt;baseline on a clean checkout&lt;/td&gt;
&lt;td&gt;exit code written to the log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;35-55 min&lt;/td&gt;
&lt;td&gt;write one failing test&lt;/td&gt;
&lt;td&gt;it fails for the right reason&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;55-80 min&lt;/td&gt;
&lt;td&gt;patch the smallest path&lt;/td&gt;
&lt;td&gt;new test passes, baseline still passes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80-90 min&lt;/td&gt;
&lt;td&gt;open the PR with the log&lt;/td&gt;
&lt;td&gt;reviewer sees one behavior change&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Stop at the window boundary. Say what you finished and what comes next. That message beats a rushed patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ways this goes wrong
&lt;/h2&gt;

&lt;p&gt;Baseline is red on a clean checkout. Stop immediately and report it. Do not fix it in your first PR.&lt;/p&gt;

&lt;p&gt;Baseline is green only on your machine. Your fingerprint line will show a different runtime. Fix the environment, not the test.&lt;/p&gt;

&lt;p&gt;Your log has no baseline entry. The PR cannot be judged. Skipped steps are invisible, so leave a note instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where a hosted box fits
&lt;/h2&gt;

&lt;p&gt;Some repos will not build on a laptop. Old Node versions, native modules, a database you cannot install locally.&lt;/p&gt;

&lt;p&gt;That is the honest use case for a remote environment. Run the fingerprint and baseline steps on a free hosted box, then copy &lt;code&gt;onboard.jsonl&lt;/code&gt; back into your branch.&lt;/p&gt;

&lt;p&gt;MonkeyCode is an open-source coding-agent project that, per its maintainers, offers free model access and a free server option. Its site currently lists a free token allowance; treat that figure as current-at-writing and verify it on the project's own page before you plan around it.&lt;/p&gt;

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

&lt;p&gt;The value here is narrow and testable. The remote box removes environment noise from step 2. Free model access helps only with small questions, like "which fixture seeds this table?" Keep those answers in your notes.&lt;/p&gt;

&lt;p&gt;Do not route security review or architecture decisions through a chat box. That work stays with you.&lt;/p&gt;

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

&lt;p&gt;The script needs bash 4 or newer and a repo with one test command. Monorepos with per-package commands need one baseline entry per package.&lt;/p&gt;

&lt;p&gt;Notes containing quotes get mangled by the simple escape used here. Keep notes plain ASCII, or store them elsewhere.&lt;/p&gt;

&lt;p&gt;Skip this if your repo holds regulated or proprietary code and you have not read the hosting terms. Skip it if your team already has a trusted CI baseline. Skip it if you need a decision today, because a log costs 90 minutes.&lt;/p&gt;

&lt;p&gt;If you want a box for step 2 without provisioning one, MonkeyCode's free tier is one option to evaluate. The log file is the part that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to take away
&lt;/h2&gt;

&lt;p&gt;Record before you patch. Timebox every window. Stop when the log tells you to stop.&lt;/p&gt;

&lt;p&gt;Your first PR should be small, explainable, and replayable. This log makes all three true.&lt;/p&gt;

</description>
      <category>git</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>career</category>
    </item>
    <item>
      <title>Your First Hour in a New Repo: Build a Reading Order from Git History</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Thu, 15 Oct 2026 11:29:37 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/your-first-hour-in-a-new-repo-build-a-reading-order-from-git-history-4l5j</link>
      <guid>https://dev.to/gitgo_5662/your-first-hour-in-a-new-repo-build-a-reading-order-from-git-history-4l5j</guid>
      <description>&lt;h2&gt;
  
  
  Conclusion first: do not read a new repo alphabetically
&lt;/h2&gt;

&lt;p&gt;You join a repo on Monday. Nobody has time to walk you through it. So you open the file tree and start at the top.&lt;/p&gt;

&lt;p&gt;That is the slowest path through a codebase. Files that change together belong together. Git already recorded which files move as one unit.&lt;/p&gt;

&lt;p&gt;Read the coupled files first and the architecture appears faster. This workflow has three steps: extract co-change pairs, expand them into a reading order, then use an agent to cover what you cannot read in time. Setup costs about fifteen minutes.&lt;/p&gt;

&lt;p&gt;The scripts below are templates. Run them in your own clone and treat the ranking as a hypothesis to verify.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Extract co-change pairs from commit history
&lt;/h2&gt;

&lt;p&gt;A commit that touches &lt;code&gt;checkout.ts&lt;/code&gt; and &lt;code&gt;cart.ts&lt;/code&gt; is evidence of a relationship. Repeat that across a year of history and the strong edges stand out from the noise.&lt;/p&gt;

&lt;p&gt;Limit the window to 12–18 months. Older commits describe code that no longer exists.&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;# Dump one commit per NUL byte, followed by the file names it touched.&lt;/span&gt;
git log &lt;span class="nt"&gt;--no-merges&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"18 months ago"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%x00'&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/cochange.log

&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /tmp/cochange.log   &lt;span class="c"&gt;# sanity check: is this file absurdly large?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now count the pairs.&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;# cochange.py — rank file pairs by how often they change together
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;

&lt;span class="n"&gt;IGNORE&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;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;node_modules/&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;dist/&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;third_party/&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;.lock&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;raw&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;log&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;--no-merges&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;--since=18 months ago&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;--pretty=format:%x00&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="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="n"&gt;stdout&lt;/span&gt;

&lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Counter&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="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Counter&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;chunk&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="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="se"&gt;\x00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunk&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;f&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;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&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;f&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="n"&gt;IGNORE&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;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&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;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;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;touched&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="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;combinations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;files&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;pairs&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;d&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;a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  &amp;lt;-&amp;gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check two things before you trust the output. First, generated files and lockfiles dominate raw counts, so keep the ignore list honest. Second, squash-merged history turns every commit into a whole feature, which flattens the pair counts.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--no-merges&lt;/code&gt; flag hides merge commits. That is usually what you want. If your team merges feature branches without squashing, drop the flag and compare the two outputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Expand one seed into a reading order
&lt;/h2&gt;

&lt;p&gt;The top pair is a starting point, not a plan. Expand outward from the most frequently touched file and stop after roughly a dozen files.&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;# Continue in the same script: walk the coupling graph.
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;

&lt;span class="n"&gt;neighbors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;neighbors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="n"&gt;neighbors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;

&lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;touched&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;most_common&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;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;while&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;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;best&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:]:&lt;/span&gt;            &lt;span class="c1"&gt;# weight the last few picks
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;neighbors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cand&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;best&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="n"&gt;order&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;best&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;best&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;reading order:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&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="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;i&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;d&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;f&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Greedy expansion is a heuristic. It can wander into a test-only cluster and stall there. If the list looks wrong, change the seed to a file you already know matters.&lt;/p&gt;

&lt;p&gt;Then write the plan down with a stop condition for each block.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Stop when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0:00–0:20&lt;/td&gt;
&lt;td&gt;top 3 coupled files&lt;/td&gt;
&lt;td&gt;you can name the entry point and its caller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0:20–1:00&lt;/td&gt;
&lt;td&gt;full pair list&lt;/td&gt;
&lt;td&gt;you can draw five arrows between modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1:00–2:00&lt;/td&gt;
&lt;td&gt;one end-to-end test&lt;/td&gt;
&lt;td&gt;the test passes locally and you know what it asserts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2:00–3:00&lt;/td&gt;
&lt;td&gt;agent summaries of the rest&lt;/td&gt;
&lt;td&gt;every claim is checked against code or a test&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The third row matters most. A reading order you cannot run is still a guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Use an agent for the files you cannot reach
&lt;/h2&gt;

&lt;p&gt;You will not read 200 files on day one. Hand the ranked list to a coding agent and ask for narrow, checkable answers.&lt;/p&gt;

&lt;p&gt;MonkeyCode offers free model access and a free server option, which makes this step cheap to try from a work laptop. Disclosure: This article was prepared as part of MonkeyCode's product outreach.&lt;/p&gt;

&lt;p&gt;Keep the prompt narrow. Broad questions produce broad guesses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For each file listed below, answer in at most four lines:
1. Which files in this repo reference it? Give file:line, or "not found".
2. What does it return or mutate?
3. Which test exercises it? Give the test name, or "no test found".
4. What would break if this file were deleted?

Files:
&amp;lt;paste the reading order here&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Not found" and "no test found" are the most useful answers. They mark the edges of the repo's documented behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Verify before you believe
&lt;/h2&gt;

&lt;p&gt;Agent output is a hypothesis, not a fact. Three commands settle most of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Does the caller really exist?&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"parseCheckout"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.ts"&lt;/span&gt; src/ | &lt;span class="nb"&gt;head&lt;/span&gt;

&lt;span class="c"&gt;# Is this file actually alive?&lt;/span&gt;
git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'%h %ad %an'&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;short &lt;span class="nt"&gt;--&lt;/span&gt; src/cart.ts

&lt;span class="c"&gt;# Does the claimed test exist, and does it pass?&lt;/span&gt;
npm &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--testPathPattern&lt;/span&gt; cart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the grep finds nothing, the agent invented the caller. If the last commit is four years old, the file is probably dead code, not core logic.&lt;/p&gt;

&lt;p&gt;Record each verified fact in one note file. That note becomes the onboarding document for the next hire, which is a better gift than a Slack summary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your first PR comes from the gaps
&lt;/h2&gt;

&lt;p&gt;The "no test found" list is your backlog. Pick one small function and add the missing test. It is a real contribution, it is low risk, and it forces you to run the code.&lt;/p&gt;

&lt;p&gt;Do not refactor anything in week one. You do not yet know which odd-looking code is load-bearing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and who should skip this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repos under about 40 files: just read them all in one sitting.&lt;/li&gt;
&lt;li&gt;Squash-merge-only history: co-change counts flatten, so pair ranking gets weak.&lt;/li&gt;
&lt;li&gt;Heavy vendoring or generated code: your ignore list does most of the work.&lt;/li&gt;
&lt;li&gt;Teams without a working local test command: verify by reading code instead.&lt;/li&gt;
&lt;li&gt;Anyone who cannot review agent output critically: skip Step 3 entirely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not hand security-critical paths to an agent on day one. Read those yourself, slowly.&lt;/p&gt;

&lt;p&gt;The pair list also says nothing about runtime behavior. Two files can co-change because a formatter touches them together, not because they are coupled. Skim the commit messages for the top pairs before you build a mental model on them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do next
&lt;/h2&gt;

&lt;p&gt;Run Step 1 on the repo you joined this week. Paste the top ten pairs into your notes. You now have a reading order, a verification habit, and a first PR candidate.&lt;/p&gt;

&lt;p&gt;If your laptop cannot spare the cycles for Step 3, MonkeyCode's free server option is one way to move that work off your machine.&lt;/p&gt;

</description>
      <category>git</category>
      <category>onboarding</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Scan the Diff Before You Request Agent Review</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Tue, 13 Oct 2026 02:28:31 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/scan-the-diff-before-you-request-agent-review-2j17</link>
      <guid>https://dev.to/gitgo_5662/scan-the-diff-before-you-request-agent-review-2j17</guid>
      <description>&lt;p&gt;Do not request review on an agent patch yet.&lt;br&gt;
A leaked secret outlives a bad function name.&lt;br&gt;
Scan the diff, then write a replay note.&lt;/p&gt;
&lt;h2&gt;
  
  
  Start from the review gate
&lt;/h2&gt;

&lt;p&gt;You are the new engineer on this repo.&lt;br&gt;
Your first pull request should stay very small.&lt;br&gt;
An agent may draft the patch for you.&lt;/p&gt;

&lt;p&gt;You still decide what reviewers are allowed to see.&lt;br&gt;
Treat the agent summary as an unverified claim.&lt;br&gt;
Every claim needs a command you can rerun.&lt;/p&gt;

&lt;p&gt;A confident paragraph is not evidence at all.&lt;br&gt;
You need a command log beside that paragraph.&lt;br&gt;
Git output beats a polished explanation every time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Keep this hour narrow
&lt;/h2&gt;

&lt;p&gt;Change only one behavior during this first hour.&lt;br&gt;
Touch only the files that this behavior needs.&lt;br&gt;
Leave lockfiles and migrations alone unless the ticket names them.&lt;/p&gt;

&lt;p&gt;Do not explore the whole tree on this branch.&lt;br&gt;
Do not ask the agent to clean unrelated files.&lt;br&gt;
Wide diffs hide secrets and unrelated edits together.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Freeze the base ref
&lt;/h2&gt;

&lt;p&gt;Pick the base branch that reviewers already trust.&lt;br&gt;
Write that ref down before you edit anything.&lt;br&gt;
Do not guess the base ref from memory later.&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 rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD
git merge-base HEAD origin/main
git status &lt;span class="nt"&gt;--short&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stop if your working tree is not clean.&lt;br&gt;
Stop if the base ref is missing locally.&lt;br&gt;
A dirty tree makes this scan meaningless now.&lt;/p&gt;

&lt;p&gt;Replace origin/main if your default branch name differs.&lt;br&gt;
Ask a teammate for the real base name.&lt;br&gt;
Do not invent a base just to pass.&lt;/p&gt;

&lt;p&gt;The three-dot diff starts at the merge base.&lt;br&gt;
It shows changes your branch introduced, not upstream noise.&lt;br&gt;
A two-dot diff can blame files you never edited.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Keep secrets out of the prompt
&lt;/h2&gt;

&lt;p&gt;Never paste env file contents into a chat.&lt;br&gt;
Never paste private keys, tokens, or customer rows.&lt;br&gt;
Name the file path when the agent must avoid it.&lt;/p&gt;

&lt;p&gt;Say which files the agent is allowed to touch.&lt;br&gt;
Say which commands the agent is allowed to run.&lt;br&gt;
Say that unknown files must stay completely untouched.&lt;/p&gt;

&lt;p&gt;A free model does not make a secret safer.&lt;br&gt;
The secret already left your machine in that paste.&lt;br&gt;
Treat every prompt as a copy you may not recall.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Run a diff scan before review
&lt;/h2&gt;

&lt;p&gt;This script is only a proposal for you.&lt;br&gt;
It is an unexecuted example for your branch.&lt;br&gt;
Adapt the base ref and path rules first.&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;# Unexecuted example. Review it before you run it.&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; git rev-parse &lt;span class="nt"&gt;--verify&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="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&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;"FAIL: base ref not found"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;files&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 diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="s2"&gt;"&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;...HEAD"&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="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$files&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;"FAIL: empty diff against &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;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"FILES:"&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;blocked&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'(^|/)(\.env|\.env\..*|id_rsa|id_ed25519|.*\.pem|.*\.p12|.*\.key|credentials\.json|secrets\.ya?ml)$'&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$files&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="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$blocked&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;"FAIL: sensitive path in diff"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY-----|ghp_[A-Za-z0-9]{20,}|xox[baprs]-[A-Za-z0-9-]{10,}'&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;git diff &lt;span class="nt"&gt;--unified&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="s2"&gt;"&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;...HEAD"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pattern&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;"FAIL: possible secret text in diff"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Do not print the match in a shared log."&lt;/span&gt;
  &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;"PASS: no blocked path or obvious token pattern"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the script outside the repository if possible.&lt;br&gt;
Run it with the base ref as its argument.&lt;br&gt;
Read each failure before you silence the script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash scan-first-diff.sh origin/main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A pass is not a full security audit.&lt;br&gt;
It catches obvious paths and a few token shapes.&lt;br&gt;
Your team scanner still matters when you have one.&lt;/p&gt;

&lt;p&gt;The failure path can still reveal a secret nearby.&lt;br&gt;
Run the scan in a private terminal, not a shared log.&lt;br&gt;
If a real secret appears, rotate it with the owner.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: Use a decision table
&lt;/h2&gt;

&lt;p&gt;Read this table before you push the branch.&lt;br&gt;
Act on the row that you actually hit.&lt;br&gt;
Do not blur two rows into a maybe.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scan result&lt;/th&gt;
&lt;th&gt;What you do&lt;/th&gt;
&lt;th&gt;What you do not do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sensitive path listed&lt;/td&gt;
&lt;td&gt;Remove that file from the branch&lt;/td&gt;
&lt;td&gt;Ask the model to ignore it in prose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token-like text in the diff&lt;/td&gt;
&lt;td&gt;Tell the credential owner and rotate&lt;/td&gt;
&lt;td&gt;Hide the line and hope review misses it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty diff&lt;/td&gt;
&lt;td&gt;Stop and restate the one behavior&lt;/td&gt;
&lt;td&gt;Open review only to show effort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass, but a hunk is unexplained&lt;/td&gt;
&lt;td&gt;Drop that hunk or ask a human&lt;/td&gt;
&lt;td&gt;Ship the model explanation as your own&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass, and you can replay the test&lt;/td&gt;
&lt;td&gt;Write the replay note next&lt;/td&gt;
&lt;td&gt;Add extra files for completeness&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A shared branch needs a teammate before any rewrite.&lt;br&gt;
This table does not teach you to force-push.&lt;br&gt;
Ask the owner before you rewrite any public history.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Fix a failure without hiding it
&lt;/h2&gt;

&lt;p&gt;Do not delete the failing line from the log.&lt;br&gt;
Copy the flagged path, then remove it from the branch.&lt;br&gt;
Commit that removal before you rerun the scan.&lt;/p&gt;

&lt;p&gt;If the file is new, delete it from the branch.&lt;br&gt;
If the file is tracked, restore the base version with help.&lt;br&gt;
Do not hide a flagged path inside gitignore.&lt;/p&gt;

&lt;p&gt;Rerun the same script after that fix lands.&lt;br&gt;
A second pass still needs the replay note.&lt;br&gt;
Do not request review from a failing log.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Write the replay note
&lt;/h2&gt;

&lt;p&gt;Put this note in the pull request body.&lt;br&gt;
A reviewer should rerun your checks without guessing.&lt;br&gt;
Keep each line short enough to verify quickly.&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;## Replay note&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Base ref: origin/main
&lt;span class="p"&gt;-&lt;/span&gt; Branch: your-branch-name
&lt;span class="p"&gt;-&lt;/span&gt; One behavior: one sentence you can defend
&lt;span class="p"&gt;-&lt;/span&gt; Allowed paths: list only those paths
&lt;span class="p"&gt;-&lt;/span&gt; Command run: the exact test command
&lt;span class="p"&gt;-&lt;/span&gt; Scan result: pass or fail, plus script name
&lt;span class="p"&gt;-&lt;/span&gt; Not run: anything you skipped on purpose
&lt;span class="p"&gt;-&lt;/span&gt; Model claim you rejected: one sentence, or none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fill every line using your own words only.&lt;br&gt;
Do not paste an agent summary over those lines.&lt;br&gt;
If any line is unknown, the review is early.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Use a remote run only as a tool
&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 offers free model access and a free server option.&lt;br&gt;
Both are availability claims supplied for this article, not measured results.&lt;br&gt;
Current quotas, hardware, and time limits are not stated.&lt;/p&gt;

&lt;p&gt;Check the current product docs before you rely on either.&lt;br&gt;
Those offers can change, and this article will not track them.&lt;br&gt;
Do not plan a deadline around an unverified limit.&lt;/p&gt;

&lt;p&gt;Use the free model to draft replay note wording.&lt;br&gt;
You still type the commands and read the output.&lt;br&gt;
Use a free server only when your team allows that workspace.&lt;/p&gt;

&lt;p&gt;Do not upload secrets so a remote scan looks better.&lt;br&gt;
The scan should see the diff, not your password store.&lt;br&gt;
If that workspace is unclear, run the script locally.&lt;/p&gt;

&lt;p&gt;Read the current MonkeyCode docs before any remote run.&lt;br&gt;
Try the scan on a branch you can delete.&lt;br&gt;
Stop if the docs disagree with this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Reject a yes from the model
&lt;/h2&gt;

&lt;p&gt;Ask the agent which checks it actually skipped.&lt;br&gt;
A short approval line is not a real scan.&lt;br&gt;
Compare its file list with git diff output.&lt;/p&gt;

&lt;p&gt;If those lists differ, believe git every time.&lt;br&gt;
If the agent reports no secrets, rerun the script.&lt;br&gt;
If you cannot explain a line, drop that line.&lt;/p&gt;

&lt;p&gt;This is the habit you want on later reviews.&lt;br&gt;
Your first review is where that habit starts.&lt;br&gt;
Reviewers teach faster when your note stays honest.&lt;/p&gt;

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

&lt;p&gt;Skip this if CI already blocks secret paths.&lt;br&gt;
Follow that gate instead of a second unofficial script.&lt;br&gt;
Skip this if you cannot open pull requests yet.&lt;/p&gt;

&lt;p&gt;Skip this flow during an active production incident.&lt;br&gt;
Incident work needs the on-call owner, not a first-hour test.&lt;br&gt;
Skip this if the ticket requires production credentials.&lt;/p&gt;

&lt;p&gt;That ticket needs a human owner, not an agent run.&lt;br&gt;
You are still learning the review path on purpose.&lt;br&gt;
An incident is the wrong classroom for this script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits you should say out loud
&lt;/h2&gt;

&lt;p&gt;The pattern list misses many private token formats.&lt;br&gt;
It misses secrets that are split across lines.&lt;br&gt;
It misses tokens that do not match these shapes.&lt;/p&gt;

&lt;p&gt;The path list misses custom secret file names.&lt;br&gt;
Add the secret names your repository actually uses.&lt;br&gt;
Do not delete a team rule to match this example.&lt;/p&gt;

&lt;p&gt;The script does not rotate any credential for you.&lt;br&gt;
The script does not prove that your test passed.&lt;br&gt;
The script does not make the agent accountable.&lt;/p&gt;

&lt;p&gt;This example was not run against your repository.&lt;br&gt;
Treat the listing as a starting point only.&lt;br&gt;
Change it until a teammate accepts the blocked paths.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you request review
&lt;/h2&gt;

&lt;p&gt;Run the scan and keep the last lines.&lt;br&gt;
Paste the replay note in your own words.&lt;br&gt;
Read the full diff with the agent closed.&lt;/p&gt;

&lt;p&gt;Request review only when all three answers hold.&lt;br&gt;
You can name the base ref from the command output.&lt;br&gt;
You can name the exact test command you ran.&lt;/p&gt;

&lt;p&gt;You can name every file you would defend.&lt;br&gt;
If one answer fails, keep the branch in draft.&lt;br&gt;
Fix that gap, or close the branch and start smaller.&lt;/p&gt;

&lt;p&gt;A delayed first review is cheaper than a leaked key.&lt;br&gt;
Leave the draft closed until those answers are easy.&lt;br&gt;
Your name is on the pull request, not the model's.&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Score Every Hunk Before Your First Agent PR</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Sun, 11 Oct 2026 21:57:16 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/score-every-hunk-before-your-first-agent-pr-i6l</link>
      <guid>https://dev.to/gitgo_5662/score-every-hunk-before-your-first-agent-pr-i6l</guid>
      <description>&lt;p&gt;You should not open your first agent pull request blind. Score every changed hunk before you request human review. A fluent model reply is not evidence of safety.&lt;/p&gt;

&lt;p&gt;You joined this repo as a junior during hour one. You still lack a map of risky paths. An agent can still draft a wide patch quickly.&lt;/p&gt;

&lt;p&gt;This hour is for a gate, not for a demo. You will build a packet you can defend. You will refuse the pull request when a score fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hold the boundary first
&lt;/h2&gt;

&lt;p&gt;Keep the agent run off your real pull request branch. Bring back a diff, a test note, and a revert line. Leave secrets, tokens, and production configs out of the prompt.&lt;/p&gt;

&lt;p&gt;Do not allow edits under CI workflows during this pass. Do not allow lockfile edits or migration files either. Those paths need a senior review, not a first hour guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Name the tool without inflating it
&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 here as one place to run that first pass. The operator supplied two availability claims for this draft. Those claims are free model access and a free server option.&lt;/p&gt;

&lt;p&gt;This draft does not name any specific model. This draft does not state a token quota. It also does not state hardware, duration, or uptime.&lt;/p&gt;

&lt;p&gt;Check the project docs on the day you run the tool. If the docs disagree with this article, trust the docs. A review habit should not pretend to be a product spec.&lt;/p&gt;

&lt;p&gt;Use the free server so your laptop clone stays untouched. Use free model access so a bounded retry stays cheap. Still copy the patch home and score it locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shape the prompt before the call
&lt;/h2&gt;

&lt;p&gt;Write the prompt as four short constraints, not a story. Name the ticket line, the allowed files, the forbidden paths, and the test command. Refuse any reply that skips one of those four.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ticket: reject empty names in parseName.
Allowed: src/parseName.js src/parseName.test.js
Forbidden: .github migrations package-lock.json .env
Test: npm test -- src/parseName.test.js
Output: a patch only. Do not commit.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep that prompt in the scratch notes beside the packet. If you change the prompt, change the notes too. A later reviewer should see the exact ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a local score script
&lt;/h2&gt;

&lt;p&gt;Save the checker below before you call any model. This script is a proposal, not an executed benchmark. Adapt the blocked path list to your repository.&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 junior gate for an agent diff&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;MAX_FILES&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;MAX_FILES&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;8&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;MAX_LINES&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;MAX_LINES&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;200&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

git rev-parse &lt;span class="nt"&gt;--is-inside-work-tree&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
&lt;span class="nv"&gt;FILES&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 diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="s2"&gt;"&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;...HEAD"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;COUNT&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;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'/^$/d'&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&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;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;STAT&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 diff &lt;span class="nt"&gt;--numstat&lt;/span&gt; &lt;span class="s2"&gt;"&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;...HEAD"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;ADDED&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;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STAT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{s+=$1} END {print s+0}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;DELETED&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;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STAT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{s+=$2} END {print s+0}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;LINES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;ADDED &lt;span class="o"&gt;+&lt;/span&gt; DELETED&lt;span class="k"&gt;))&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"files=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; lines=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LINES&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COUNT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MAX_FILES&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;"FAIL too many files for hour one"&lt;/span&gt;
  &lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="k"&gt;fi
if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LINES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MAX_LINES&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;"FAIL diff too large for hour one"&lt;/span&gt;
  &lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;BLOCK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'(^|/)(\.github/workflows/|migrations/|.*lock$|\.env|credentials?)'&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILES&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="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BLOCK&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;"FAIL blocked path present in diff"&lt;/span&gt;
  &lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="k"&gt;fi

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; REVIEW_PACKET.md &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;"FAIL missing REVIEW_PACKET.md"&lt;/span&gt;
  &lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s1"&gt;'^Revert: '&lt;/span&gt; REVIEW_PACKET.md &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"FAIL missing Revert line"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s1"&gt;'^Test: '&lt;/span&gt; REVIEW_PACKET.md &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"FAIL missing Test line"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s1"&gt;'^Unknown hunks: 0$'&lt;/span&gt; REVIEW_PACKET.md &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"FAIL unknown hunks remain"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;fi

&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;$fail&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the checker from the scratch branch after you pull the patch. Pass the base ref your team actually uses. Do not open a pull request when the exit code is nonzero.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x scripts/score-agent-diff.sh
&lt;span class="nv"&gt;MAX_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8 &lt;span class="nv"&gt;MAX_LINES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;200 ./scripts/score-agent-diff.sh origin/main
git diff &lt;span class="nt"&gt;--stat&lt;/span&gt; origin/main...HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the stat output even when the script passes. A rename can still hide a large rewrite. Your own eyes still have to close the gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write the packet yourself
&lt;/h2&gt;

&lt;p&gt;Create REVIEW_PACKET.md in the scratch branch before review. You write every line in that packet yourself. Do not accept an agent-written packet as your own note.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Ticket: ISSUE-123
Test: npm test -- workspace/foo.test.js
Revert: git revert &lt;span class="nt"&gt;&amp;lt;merge-sha&amp;gt;&lt;/span&gt;
Unknown hunks: 0
Risk: parser change only, no schema edit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test line must name a command you actually ran. If you have not run it, write Test not run and stop. A missing run is a failed gate, not a minor note.&lt;/p&gt;

&lt;p&gt;The revert line must be a command you understand today. If revert would need a data backfill, stop the pull request. Hour one is the wrong time for that class of change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow these eight steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Copy the ticket acceptance line into your prompt notes.&lt;/li&gt;
&lt;li&gt;Create a scratch branch that is not your pull request branch.&lt;/li&gt;
&lt;li&gt;Start the agent on the free server option, without secrets.&lt;/li&gt;
&lt;li&gt;Limit the prompt to files the ticket actually needs.&lt;/li&gt;
&lt;li&gt;Pull the patch back and run the score script locally.&lt;/li&gt;
&lt;li&gt;Run the test command and record the real result.&lt;/li&gt;
&lt;li&gt;Set unknown hunks to zero only after you explain each hunk.&lt;/li&gt;
&lt;li&gt;Open the pull request only when the script exits zero.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Stop the run if the agent edits a file you did not name. Stop again if the summary mentions a file absent from the diff. Those mismatches mean the packet is not ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use this decision table
&lt;/h2&gt;

&lt;p&gt;Do not bargain with a failed row during hour one. Split the work now or discard the scratch branch. Ask a senior when the row is outside your map.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Your move&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Eight files or fewer&lt;/td&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;td&gt;Continue to the test line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;More than 200 changed lines&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;Split the patch or discard it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocked path in the diff&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;Reset the scratch branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test command not run by you&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;Run it, or do not open the PR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unknown hunk count above zero&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;Read again or drop that hunk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Revert line you cannot explain&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;Write a real revert or stop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New dependency or workflow edit&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;Hand the ticket to a senior&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A passing size score is not a passing meaning score. You still need to read each hunk in order. Opaque code stays a fail until you can teach it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Walk one sample hunk
&lt;/h2&gt;

&lt;p&gt;Imagine the ticket says the parser should reject an empty name. The agent changes parseName and also reformats the README file. You score the parser hunk as related to the ticket.&lt;/p&gt;

&lt;p&gt;You score the README hunk as unknown, then you drop it. That parser hunk matches the ticket, so it can stay. You still run the named test before you open any pull request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- if (!name) return null;
&lt;/span&gt;&lt;span class="gi"&gt;+ if (!name || !name.trim()) throw new Error("empty name");
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treat this diff as an illustration, not as a result from your repo. Replace the function names with the files your ticket names. Keep the same pass or fail questions on every hunk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read hunks in a fixed order
&lt;/h2&gt;

&lt;p&gt;Open the diff one file at a time. Ask what user-visible behavior changed for this ticket. If the answer needs a guess, mark that hunk unknown.&lt;/p&gt;

&lt;p&gt;Watch for formatter noise spread across unrelated files. Watch for a new helper that the ticket never requested. Watch for a comment that hides a behavior change.&lt;/p&gt;

&lt;p&gt;Compare the agent summary with the name-only diff output. Every file in the summary should appear in that list. Every file in the list should appear in your notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the free options in their lane
&lt;/h2&gt;

&lt;p&gt;The free server is only for the noisy first pass. Keep private fixtures and credentials off that machine. Copy a patch back, not a live environment.&lt;/p&gt;

&lt;p&gt;Free model access can make a second prompt cheap. Change the constraint before you retry the same ask. A retry without a new limit is usually noise.&lt;/p&gt;

&lt;p&gt;This article states no token total and no expiry date. Those facts were not supplied as verified numbers. Read the current docs before you plan a long session.&lt;/p&gt;

&lt;p&gt;If your team bans external coding agents, stop here. Do not treat a free tier as a policy workaround. Ask your lead before you send the first prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Know the checker limits
&lt;/h2&gt;

&lt;p&gt;The block regex is a starter, not a complete risk map. Add your real danger paths before you trust a pass. A green script can still miss a risky file name.&lt;/p&gt;

&lt;p&gt;Numstat sums ignore binary files and some renames. Run git diff stat when those numbers look too small. Trust the strange stat over the cheerful summary.&lt;/p&gt;

&lt;p&gt;A free server may lack your private test fixtures. A pass on that server can still fail in CI. Prefer the pinned CI command when you can run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip this flow in these cases
&lt;/h2&gt;

&lt;p&gt;Skip the flow when the ticket needs production data. Skip it when you cannot read the language yet. Skip it when the change is a release or a migration.&lt;/p&gt;

&lt;p&gt;Skip it when you need a guaranteed quota or support contract. This draft does not establish either of those promises. Use an approved internal tool when the ticket is urgent.&lt;/p&gt;

&lt;p&gt;Skip it when the diff is already on a shared branch. Hour one should not repair a public mistake with another agent pass. Revert first, then review the result with a human.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leave with a defendable pull request
&lt;/h2&gt;

&lt;p&gt;Your first pull request should stay small enough to explain aloud. The score script is the defense you can show. The model only drafted the patch you scored.&lt;/p&gt;

&lt;p&gt;If you use MonkeyCode for that first pass, read the current notes. Confirm the free-access terms on the day you actually run it. Then run the local gate before you ask anyone for review.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>git</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>Gate Your First Agent Patch on a Stable Failure Log</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Sat, 10 Oct 2026 18:42:54 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/gate-your-first-agent-patch-on-a-stable-failure-log-7j0</link>
      <guid>https://dev.to/gitgo_5662/gate-your-first-agent-patch-on-a-stable-failure-log-7j0</guid>
      <description>&lt;p&gt;Save the failing command before any agent edits your repo. A first PR should start from a bundle, not a chat guess. That bundle holds a script, two logs, and a base SHA.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start from the failure
&lt;/h2&gt;

&lt;p&gt;You join the repo and the ticket already sounds urgent. Someone suggests an agent can patch the bug before lunch. You paste the issue text and accept the first diff.&lt;/p&gt;

&lt;p&gt;The reviewer cannot replay that chat on their machine. You also cannot defend a rollback if main breaks later. Hour one should prove the failure, not invent the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you leave behind
&lt;/h2&gt;

&lt;p&gt;You will finish the hour with a small repro directory. It contains a script, two logs, a SHA, and a note. The script must fail the same way on two clean runs.&lt;/p&gt;

&lt;p&gt;You do not open a pull request during this hour. You do not let an agent write files before those runs.&lt;/p&gt;

&lt;p&gt;Keep the names stable so a reviewer can find them fast. Do not rename logs after you paste one into a prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;repro/
  START_SHA
  NOTE
  run.sh
  run-1.log
  run-2.log
  log.diff
  PROMPT_LOG
  run-3.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Freeze the starting SHA
&lt;/h2&gt;

&lt;p&gt;Clone the repository into a new directory on a clean host. Do not reuse a laptop checkout full of old builds. Check out the default branch your team already documents.&lt;/p&gt;

&lt;p&gt;Record the commit SHA before you install extra tools. That file is your anchor if the patch needs a revert. Do not update the SHA after you start the two runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; repro
git rev-parse HEAD | &lt;span class="nb"&gt;tee &lt;/span&gt;repro/START_SHA
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"ticket: &amp;lt;id&amp;gt;"&lt;/span&gt; &lt;span class="s2"&gt;"command: &amp;lt;paste from CI&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/NOTE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the branch moves, start the bundle over from clone. A moved base makes the later diff harder to explain.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Copy the command, not the story
&lt;/h2&gt;

&lt;p&gt;Open the ticket and the newest failing CI log. Copy the exact command that failed, including its working directory. Do not shorten the command so the run feels faster.&lt;/p&gt;

&lt;p&gt;Pin package scripts if CI called those scripts by name. Write unknown flags down instead of guessing their meaning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/run.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
cd "&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="sh"&gt;/.."
# Replace the next line with the exact CI command.
npm test -- workspace/parser
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x repro/run.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treat that file as a template until the real command lands. If the log names a setup step, put that step first. Keep secrets out of the script and out of the note.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Run the script twice on a clean host
&lt;/h2&gt;

&lt;p&gt;A laptop cache can hide the bug you are chasing. Run both attempts on a throwaway host instead. A clean host is enough for this narrow check.&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. Use that server only as the clean host for these two runs.&lt;/p&gt;

&lt;p&gt;Use free model access only after the logs match. Do not assume a model name, a quota, or a machine size. Those details are not stated here because they can change.&lt;/p&gt;

&lt;p&gt;Read the current product docs before you depend on access. Confirm the live limits before you store anything there. Treat current access as optional, not as a lasting promise.&lt;/p&gt;

&lt;p&gt;Run the script once and keep every line of output. The true fallback keeps the shell alive after a failed test. You still want the log when the command exits non-zero.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./repro/run.sh &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/run-1.log 2&amp;gt;&amp;amp;1 &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;Wait a minute, then run the same script again. Save the second log beside the first one. Diff the logs before you decide the failure is real.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./repro/run.sh &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/run-2.log 2&amp;gt;&amp;amp;1 &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; repro/run-1.log repro/run-2.log &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/log.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;Stop when the logs disagree in a meaningful way. A flaky failure is a bad target for your first PR.&lt;/p&gt;

&lt;p&gt;Write the mismatch in the ticket and ask a human. Do not ask a model to hide flake with retries.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Read the log before you prompt
&lt;/h2&gt;

&lt;p&gt;Read the log from the bottom, not from the top. Find the first error that names a file and a line. Ignore warnings that also appear on a green main build.&lt;/p&gt;

&lt;p&gt;If you cannot tie the error to a file, stop here. A vague failure needs a human, not a generated patch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 40 repro/run-2.log &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/PROMPT_LOG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Ask for a patch only after the logs match
&lt;/h2&gt;

&lt;p&gt;Open a chat only after the two logs agree. Attach the script, the SHA, and the second log. Ask for a patch that makes this script pass.&lt;/p&gt;

&lt;p&gt;Ask for the file list before you ask for code. Reject any reply that ignores the script you saved. Keep the prompt short so a free model can answer.&lt;/p&gt;

&lt;p&gt;Trim the saved log before you paste it into a chat. Forty lines is a starting cap, not a measured limit. Never paste tokens, customer rows, or private URLs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Base SHA: &amp;lt;paste repro/START_SHA&amp;gt;
Command: ./repro/run.sh
Failure log: &amp;lt;paste repro/PROMPT_LOG&amp;gt;
Constraint: change the smallest set of files.
Do not add dependencies.
Return a file list, a patch, and one short reason.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the ticket needs those, use the private runner. Treat the answer as an unexecuted proposal, not a result. You still have to apply it and rerun the script.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Apply it on a branch and rerun
&lt;/h2&gt;

&lt;p&gt;Create a branch from the SHA you already recorded. Apply a short patch by hand so you see each hunk. Do not apply a patch that adds new dependencies.&lt;/p&gt;

&lt;p&gt;Run the same script and save a third log. Compare the second log with the third log yourself. The old error text should be gone in the third log.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; junior/repro-fix &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;repro/START_SHA&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# Apply the reviewed patch by hand, then:&lt;/span&gt;
./repro/run.sh &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; repro/run-3.log 2&amp;gt;&amp;amp;1 &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;Other tests in that command should not start failing. If they fail, revert the branch and keep the bundle. Map every hunk to a line in the failure log.&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; &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;repro/START_SHA&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a hunk has no story, the patch is too wide. Cut the extra files and ask for a smaller patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Write the PR so a stranger can replay it
&lt;/h2&gt;

&lt;p&gt;Open the PR only when you can narrate the diff. Put the script path and the base SHA in the body.&lt;/p&gt;

&lt;p&gt;Name the command you ran and the log you compared. Invite review of the bundle, not praise of the agent.&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;## Repro&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Base SHA: &lt;span class="nt"&gt;&amp;lt;paste&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Script: repro/run.sh
&lt;span class="p"&gt;-&lt;/span&gt; Compared: repro/run-2.log and repro/run-3.log

&lt;span class="gu"&gt;## What changed&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;file&amp;gt;&lt;/span&gt;: &lt;span class="nt"&gt;&amp;lt;one&lt;/span&gt; &lt;span class="na"&gt;sentence&lt;/span&gt; &lt;span class="na"&gt;tied&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt; &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Rollback&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Revert this branch if a hunk cannot be explained.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Roll back the same day if the story breaks
&lt;/h2&gt;

&lt;p&gt;Roll back the same day if review exposes a gap. A clean revert is better than a clever unexplained patch. Follow your team's revert rule if the merge was squashed.&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;# Use your team's documented revert path after merge.&lt;/span&gt;
git revert &lt;span class="nt"&gt;--no-edit&lt;/span&gt; &amp;lt;merged-commit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave the bundle in the ticket after the revert. The next person can rerun it without your laptop. Do not delete the logs just because the PR closed.&lt;/p&gt;

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

&lt;p&gt;Use this table as a gate before you push. It is a checklist, not a scoreboard for speed.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Two logs match and name one error&lt;/td&gt;
&lt;td&gt;Ask for a small patch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logs differ, or the run hangs&lt;/td&gt;
&lt;td&gt;Stop and ask a human about flake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patch touches files outside the stack&lt;/td&gt;
&lt;td&gt;Reject it and re-ask with a file cap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script passes but one hunk has no story&lt;/td&gt;
&lt;td&gt;Revert and do not merge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ticket includes secrets or production data&lt;/td&gt;
&lt;td&gt;Do not use an external host or chat&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Print the table and keep it next to the ticket. If a row says stop, stop before you prompt again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits to say out loud
&lt;/h2&gt;

&lt;p&gt;This method fits one failing command with a stable log. It does not fit races, load tests, or hardware bugs. Two matching runs do not prove a rare crash is gone.&lt;/p&gt;

&lt;p&gt;A free server may sleep, throttle, or disappear later. Do not call that host your team's continuous integration. Do not store credentials or production dumps on it.&lt;/p&gt;

&lt;p&gt;Free model access may reject a very long log. Trim to the failing section and send that slice only. The commands in this article are an unexecuted example.&lt;/p&gt;

&lt;p&gt;They are a workflow to adapt, not a measured benchmark. No timings, pass rates, or hardware claims belong here.&lt;/p&gt;

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

&lt;p&gt;Skip this if your team forbids external code hosts. Skip this if the bug needs a private dataset. Skip this if you are on call for a live incident.&lt;/p&gt;

&lt;p&gt;Senior engineers chasing a multi-service outage need another plan. New hires with a documented unit-test failure are the fit. If your mentor already owns the patch, pair with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Close the hour
&lt;/h2&gt;

&lt;p&gt;Hour one ends with a bundle, not a hero patch. Save the SHA, the script, and two matching logs.&lt;/p&gt;

&lt;p&gt;Ask for a patch only after that evidence exists. If the diff outruns your explanation, revert it today.&lt;/p&gt;

&lt;p&gt;If you already have that free server, run the two checks there. Keep the prompt tied to the saved logs only. Check the docs your team trusts before you rely on availability.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>git</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>Classify Repo Paths Before Your First Agent Prompt</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Fri, 09 Oct 2026 15:02:39 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/classify-repo-paths-before-your-first-agent-prompt-20cc</link>
      <guid>https://dev.to/gitgo_5662/classify-repo-paths-before-your-first-agent-prompt-20cc</guid>
      <description>&lt;h1&gt;
  
  
  Classify Repo Paths Before Your First Agent Prompt
&lt;/h1&gt;

&lt;p&gt;Your first agent prompt needs a written path map. A junior can leak secrets with one careless paste. Classify every path before any model sees the repo.&lt;/p&gt;

&lt;p&gt;This hour is about refusal, not about shipping a fix. You will build a small path classifier first. You will not prompt until that map is green.&lt;/p&gt;

&lt;h2&gt;
  
  
  What hour one can break
&lt;/h2&gt;

&lt;p&gt;You just cloned a repo you barely know. The agent offers to look around and fix tests. That browse can read tokens and customer fixtures.&lt;/p&gt;

&lt;p&gt;A hosted model may retain what you upload. A free server is still someone else's computer. Treat both as untrusted until policy says otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three buckets, one decision
&lt;/h2&gt;

&lt;p&gt;Give every path one bucket before you prompt. Read-only context may be summarized, not edited. The sandbox is the only tree the agent may change.&lt;/p&gt;

&lt;p&gt;Forbidden paths never enter the prompt or the upload. Env files, key files, and prod configs belong there. If you feel unsure, mark the path forbidden.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Freeze a toy tree
&lt;/h2&gt;

&lt;p&gt;Do not point this drill at a production clone. Use a fixture repo your lead already approved. Create a branch that nobody will merge today.&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;-c&lt;/span&gt; onboard/path-map
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; sandbox fixtures/secrets docs
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'Toy repo for a path-map drill.\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; README.md
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'print("ok")\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; sandbox/hello.py
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'TOKEN=replace-me\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; fixtures/secrets/.env
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'Not a real secret.\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docs/notes.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those sample files are examples, not live secrets. Delete the fixture when the drill is done. Never copy a live credential into this tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Write the rule file
&lt;/h2&gt;

&lt;p&gt;Keep rules in the repo only with lead approval. Otherwise store the map in your private notes. Start from a plain text file named path-map.txt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# path-map.txt - example rules, edit before use
read_only:
  README.md
  docs/
sandbox:
  sandbox/
forbidden:
  .env
  .env.*
  fixtures/secrets/
  *.pem
  infra/prod/
local_tool:
  path-map.txt
  classify-paths.sh
  path-report.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put one rule on each line for easy review. A glob you cannot explain should stay forbidden. Ask your buddy before you widen the sandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Run a local classifier
&lt;/h2&gt;

&lt;p&gt;Read this script before you execute a single line. It does not call a network or an agent. It only prints a bucket for each file path.&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;# Unexecuted example. Prefix checks only. No network calls.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

find &lt;span class="nb"&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;-path&lt;/span&gt; &lt;span class="s1"&gt;'./.git/*'&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s#^./##'&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; rel&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;$rel&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    .env|.env.&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;/.env|&lt;span class="k"&gt;*&lt;/span&gt;/.env.&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;fixtures/secrets/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.pem|infra/prod/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"forbidden &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    sandbox/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"sandbox &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    README.md|docs/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"read_only &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    path-map.txt|classify-paths.sh|path-report.txt&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"local_tool &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"unmapped &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&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;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treat the script as an unexecuted example first. An unmapped file should block the prompt completely. You do not guess a bucket under time pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Fail closed on gaps
&lt;/h2&gt;

&lt;p&gt;Count the report lines before you continue today. An unmapped count above zero stops the session. A forbidden count tells you what never gets uploaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash classify-paths.sh | &lt;span class="nb"&gt;tee &lt;/span&gt;path-report.txt
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/^unmapped /{c++} END{print c+0}'&lt;/span&gt; path-report.txt
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/^forbidden /{c++} END{print c+0}'&lt;/span&gt; path-report.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the unmapped count is not zero, fix the map. Keep every forbidden path out of the prompt text. Then rerun both counts and save the report.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Pick a machine with a table
&lt;/h2&gt;

&lt;p&gt;Use this table before you choose a machine. Your written company policy beats every row below. When policy is silent, do not upload the repo.&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. This article does not name models, quotas, or duration.&lt;/p&gt;

&lt;p&gt;Those terms change, so read the current product page. Do not paste the sample token into any prompt. Do not upload payroll files to a free server.&lt;/p&gt;

&lt;p&gt;A free tier is not a data-processing agreement. Check retention terms before you type a prompt. Stop if those terms conflict with your handbook.&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;Where to run&lt;/th&gt;
&lt;th&gt;What you may upload&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Policy forbids external models&lt;/td&gt;
&lt;td&gt;Approved laptop only&lt;/td&gt;
&lt;td&gt;Nothing leaves the machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Policy allows a hosted spike&lt;/td&gt;
&lt;td&gt;Free server, if still offered&lt;/td&gt;
&lt;td&gt;Toy repo or redacted sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want a hosted model&lt;/td&gt;
&lt;td&gt;Free model access, if offered&lt;/td&gt;
&lt;td&gt;Same allowlist, no forbidden paths&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live credentials sit on disk&lt;/td&gt;
&lt;td&gt;Do not start the agent&lt;/td&gt;
&lt;td&gt;Stop and ask your lead&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  6. Lock a prompt contract
&lt;/h2&gt;

&lt;p&gt;Paste the contract above the task, not below it. Keep the task limited to one sandbox file. Refuse any request to scan the whole repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Path contract:
- Edit only sandbox/hello.py.
- Do not open fixtures/secrets or any env file.
- Do not add dependencies.
- Stop if a needed file is unmapped.
Task: add a one-line comment that says hello.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You review the diff yourself after the run. You do not merge from the agent summary alone. If the diff touches a forbidden path, discard the branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Reset before any pull request
&lt;/h2&gt;

&lt;p&gt;This drill ends in a reset, not a merge. You are proving you can undo agent edits. You are not shipping product code on day one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status &lt;span class="nt"&gt;--short&lt;/span&gt;
git diff &lt;span class="nt"&gt;--&lt;/span&gt; sandbox/hello.py
git restore &lt;span class="nt"&gt;--&lt;/span&gt; sandbox/hello.py
&lt;span class="c"&gt;# Switch back to the branch you started from, then:&lt;/span&gt;
git branch &lt;span class="nt"&gt;-D&lt;/span&gt; onboard/path-map
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm the sandbox file matches the original bytes. Confirm the secret fixture never entered a commit. Then tell your buddy what you refused to upload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits you should say aloud
&lt;/h2&gt;

&lt;p&gt;This classifier is a text filter, not a boundary. A model can still infer secrets from pasted logs. The sample globs are narrow on purpose today.&lt;/p&gt;

&lt;p&gt;The script does not follow symlinks or submodules. It will miss a renamed env file easily. You still need human review on every diff.&lt;/p&gt;

&lt;p&gt;Free model access can change or disappear later. A free server may retain prompts under its terms. Neither offer replaces your team's vendor review.&lt;/p&gt;

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

&lt;p&gt;Skip this if a sealed devcontainer is already required. Skip this if no redacted fixture is allowed. Skip this if you cannot name the editable file.&lt;/p&gt;

&lt;p&gt;Staff with a written agent policy need stricter controls. This drill is for hour one, not production automation. Do not point it at a live customer tenant.&lt;/p&gt;

&lt;h2&gt;
  
  
  After the map is green
&lt;/h2&gt;

&lt;p&gt;Ask your buddy to spot-check the path report. If they approve a hosted spike, open the MonkeyCode terms. Confirm the free options still match team policy.&lt;/p&gt;

&lt;p&gt;Run the same contract on the toy repo only. Your first real PR waits until you can explain every line.&lt;/p&gt;

&lt;p&gt;The path map is the note you keep nearby. Repeat that map on the next ticket before prompting.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Show your lead a receipt
&lt;/h2&gt;

&lt;p&gt;Bring a short receipt to your onboarding lead. Include the branch name and the report counts. Include the list of paths you refused to upload.&lt;/p&gt;

&lt;p&gt;Say which machine ran the classifier and why. Say whether any prompt left your laptop today. If a prompt left, attach the exact contract text.&lt;/p&gt;

&lt;p&gt;If no prompt left, say that in one line. Ask which bucket was wrong before the next ticket.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>git</category>
      <category>ai</category>
      <category>career</category>
    </item>
    <item>
      <title>Move the First Agent Run Off Your Laptop Clone</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Thu, 08 Oct 2026 10:30:27 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/move-the-first-agent-run-off-your-laptop-clone-1pcm</link>
      <guid>https://dev.to/gitgo_5662/move-the-first-agent-run-off-your-laptop-clone-1pcm</guid>
      <description>&lt;p&gt;Do not let your first agent edit land in the laptop clone. Run that first session on a remote sandbox instead. Bring back one reviewed patch after the checks pass.&lt;/p&gt;

&lt;p&gt;You joined this repository with a thin map of its risks. A coding agent can still draft a small change for you. That speed is not a safe first pull request.&lt;/p&gt;

&lt;p&gt;Keep the default branch untouched during this first hour. Explain every changed line before you request review. Treat the steps below as a proposal you must adapt.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Write the Contract Before You Open a Chat
&lt;/h2&gt;

&lt;p&gt;Write a one-page brief before you open an agent chat. The brief is the only contract for this hour. If the brief feels vague, do not start the session.&lt;/p&gt;

&lt;p&gt;Lock five facts in that brief before you type a prompt. Name the ticket and the one behavior you will change. Also name allowed paths, the CI test command, and the base SHA.&lt;/p&gt;

&lt;p&gt;Do not ask the agent to invent those facts for you. You write them from the repository and the ticket. The agent may work only inside that written fence.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Record the Base Commit Before Any Agent Prompt
&lt;/h2&gt;

&lt;p&gt;Your first commands should only read local repository state. They should not create an agent branch on this clone. Save the default-branch SHA where you can find it later.&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 status &lt;span class="nt"&gt;--short&lt;/span&gt;
git rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD
git rev-parse origin/main
git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt; origin/main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write that SHA into a note outside the work tree. If this repository uses master, record that name instead. This note is your return point if the session goes wide.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rev-parse origin/main &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/hour-one-base.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not commit that personal note into the repository. Do not push it to the remote by mistake either. It is a personal checkpoint, not a project file.&lt;/p&gt;

&lt;p&gt;Confirm the work tree is clean before you continue. A dirty clone will mix your scraps with the agent patch. Stash or drop those scraps before you record the base.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Pick a Sandbox That Is Not Your Clone
&lt;/h2&gt;

&lt;p&gt;You need a place the agent can edit without touching your clone. A free server can be that place when the offer includes one. A local virtual machine remains a valid substitute here.&lt;/p&gt;

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

&lt;p&gt;MonkeyCode is only one route to free model access and a free server. Treat both items as availability claims that you must recheck today. This article does not name models, token caps, hardware, or duration.&lt;/p&gt;

&lt;p&gt;Those details change, and this draft did not measure them. Open the current product page before you depend on any limit. If the free server is absent, keep the same brief locally.&lt;/p&gt;

&lt;p&gt;Use that server only for this first reviewed patch. Do not place production secrets on that remote machine. Do not point the session at private customer data.&lt;/p&gt;

&lt;p&gt;If the repository is private, read the server terms first. If those terms are unclear, skip the remote option entirely. A company ban on outside models also ends this path.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Copy a Narrow Brief Onto the Sandbox
&lt;/h2&gt;

&lt;p&gt;Create a file named SESSION_BRIEF.md on the sandbox before prompting. Keep that file short enough to reread in two minutes. The sample below is an unexecuted template, not a real run.&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;# Session brief&lt;/span&gt;
Ticket: https://example.test/tickets/123
Change: Adjust empty-state copy in web/src/Empty.tsx only.
Allow: web/src/Empty.tsx and web/src/Empty.test.tsx
Outside scope: workflows, lockfiles, migrations, and infra
Test: npm test -- Empty.test.tsx
Done: that test passes, and no other file changes.
Stop: if a new dependency is required, stop.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the brief as your first message to the agent. Tell the agent to stop when the change leaves those files. Tell it not to push or open a pull request.&lt;/p&gt;

&lt;p&gt;Tell it not to amend commits or rewrite history. If the agent leaves the allowed files, discard the sandbox. Do not salvage a wide diff on your first day.&lt;/p&gt;

&lt;p&gt;Start again later with a smaller allowed file list. Watch the session for scope creep in the chat replies. A request to update a lockfile is a stop signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Export One Patch and Leave the Sandbox
&lt;/h2&gt;

&lt;p&gt;On the sandbox, read status before you export anything. You want a single patch file copied to your laptop. You do not want a surprise push to the team remote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status &lt;span class="nt"&gt;--short&lt;/span&gt;
git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;
git diff &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/hour-one.patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy that patch home through your normal file transfer step. Remove any secrets you typed into the sandbox session. Stop or destroy that server when the product lets you.&lt;/p&gt;

&lt;p&gt;Do not keep a forgotten remote checkout for later experiments. Hour one ends when the reviewed patch is home. A living sandbox is not a second source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Apply the Patch on a Named Ticket Branch
&lt;/h2&gt;

&lt;p&gt;Return to the laptop clone after the patch is home. Create a branch that names the ticket, not the tool. Test the patch with an apply check before you apply it.&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; ticket-123-empty-state origin/main
git apply &lt;span class="nt"&gt;--check&lt;/span&gt; /tmp/hour-one.patch
git apply /tmp/hour-one.patch
git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the default branch moved, do not rebase alone. Ask a human owner before you replay the patch. If the apply check fails, stop and do not hand-merge.&lt;/p&gt;

&lt;p&gt;A confused patch is a failed hour, not a puzzle. Rerun the sandbox session with a smaller written brief. Leave the laptop clone clean while you do that rerun.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Run the Named Test and Read Every Hunk
&lt;/h2&gt;

&lt;p&gt;Run only the test command you wrote in the brief. A full local suite can wait for CI on this pass. You need proof that this patch matches the ticket text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; Empty.test.tsx
git diff &lt;span class="nt"&gt;--&lt;/span&gt; web/src/Empty.tsx web/src/Empty.test.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace that npm command with the one CI already runs. Do not invent a friendlier command just for the agent. If CI uses a task runner, pin that exact task in the brief.&lt;/p&gt;

&lt;p&gt;Write a reviewer note in your own words after the test. Use the checklist below before you open any pull request. The checklist is an unexecuted proposal, not a team form.&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="p"&gt;-&lt;/span&gt; [ ] I can name the user-visible change in one sentence.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] I can name the test that now covers that change.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] No lockfile, workflow, or migration file changed.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] No new dependency appeared in the diff.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] I can delete this branch without touching main.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you cannot check a box, do not open the pull request. Shrink the patch or drop it and restart from the brief. Silence is better than a review you cannot defend.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Use a Decision Table Before You Continue
&lt;/h2&gt;

&lt;p&gt;This table is a proposal, not an official team policy. Read the row that matches the diff you actually have. Then do that action, even if the agent sounded confident.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you see&lt;/th&gt;
&lt;th&gt;What you do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Only allowed files changed, and the named test passes&lt;/td&gt;
&lt;td&gt;Open a draft pull request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The patch touches files outside the brief&lt;/td&gt;
&lt;td&gt;Discard the sandbox result and restart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A new dependency or workflow edit appears&lt;/td&gt;
&lt;td&gt;Stop and ask the code owner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The patch does not apply on the base&lt;/td&gt;
&lt;td&gt;Do not hand-merge; rerun a smaller brief&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You cannot explain one hunk&lt;/td&gt;
&lt;td&gt;Do not request review&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Confidence in the chat transcript is not evidence for you. The diff on disk is the evidence you can defend. Your short note is what the reviewer will actually trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Open the First Pull Request as a Draft
&lt;/h2&gt;

&lt;p&gt;Push only the ticket branch from the laptop clone. Open the pull request as a draft, not as ready review. Paste the brief, the test command, and the base SHA.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write that body yourself after you finish reading the diff. Do not paste the agent transcript as the description text. Reviewers need the change, the test, and the risk.&lt;/p&gt;

&lt;p&gt;They do not need the full chat log in the body. They need to see that you understood each hunk. A short body beats a long generated summary every time.&lt;/p&gt;

&lt;p&gt;Request review only after the draft checks are green. If CI uses a different command, trust the pipeline. Update the brief, rerun that command, and then ask.&lt;/p&gt;

&lt;p&gt;Do not argue with the pipeline on your first day. Do not weaken a check just to make the patch green. Ask the code owner before you touch any workflow file.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Close a Bad Draft Without Extra Story
&lt;/h2&gt;

&lt;p&gt;Some drafts should die before anyone spends review time. Close the pull request and delete the ticket branch. Then confirm your clone still matches the fetched default branch.&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 main
git fetch origin
git status &lt;span class="nt"&gt;--short&lt;/span&gt;
git push origin &lt;span class="nt"&gt;--delete&lt;/span&gt; ticket-123-empty-state
git branch &lt;span class="nt"&gt;-D&lt;/span&gt; ticket-123-empty-state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do this when the patch grew past the written brief. Do this when a reread still leaves one hunk unexplained. A closed draft is a clean outcome, not a failure story.&lt;/p&gt;

&lt;p&gt;If you already merged, follow your team revert rule instead. This article does not invent a revert policy for shared history. Ask the owner before you rewrite commits on the default branch.&lt;/p&gt;

&lt;p&gt;Confirm the default branch SHA before you delete local work. If origin main moved, fetch and read the new log first. Never reset a shared branch to your hour-one note.&lt;/p&gt;

&lt;h2&gt;
  
  
  Respect Limits Before You Trust Free Access
&lt;/h2&gt;

&lt;p&gt;This workflow fits a small, reversible text or copy change. It does not fit migrations, auth changes, or billing code. It does not fit code you cannot place on a third-party server.&lt;/p&gt;

&lt;p&gt;Skip the free server when private-repo terms are still unclear. Skip free model access when your company bans outside models. A local editor plus the same brief is enough in that case.&lt;/p&gt;

&lt;p&gt;Free access can change or disappear without prior notice. Do not plan a week of work on an unpaid server. Do not assume a token grant, machine size, or time limit.&lt;/p&gt;

&lt;p&gt;Verify those facts on the current product page yourself. The sample test command is generic on purpose here. Your repo may use pytest, go test, or a task runner.&lt;/p&gt;

&lt;p&gt;Pin the command your CI configuration already runs today. Do not invent a new command so the agent looks fast. A green command that CI ignores is not a valid signal.&lt;/p&gt;

&lt;p&gt;The template paths are fiction for this teaching example. Replace them with a real file named in your ticket. If you have no ticket, do not invent work for the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip This Path When the Fit Is Wrong
&lt;/h2&gt;

&lt;p&gt;Skip this path if you cannot read a unified diff yet. Pair with a human before you invite an agent in. An agent does not replace that first reading hour.&lt;/p&gt;

&lt;p&gt;Skip this path for production hotfixes and incident channels. Skip it for mass edits across issues you do not understand. A first contribution still needs the project guide and the license.&lt;/p&gt;

&lt;p&gt;Skip the remote sandbox if it would hide work from review. The patch still comes home to your laptop clone. Your name stays on the pull request either way.&lt;/p&gt;

&lt;p&gt;Do not use this flow to bypass code owner rules. Do not use it to skip a required design note. If the ticket lacks checks, write them with your mentor first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try One Ticket and Then Stop Cold
&lt;/h2&gt;

&lt;p&gt;If those free options are still listed, try exactly one ticket. Keep the written brief tighter than the prompt you want. If that offer is gone, use a local virtual machine instead.&lt;/p&gt;

&lt;p&gt;Stop after one reviewed draft leaves your laptop. Hour one builds a habit, not a batch of agent pulls. Tomorrow, repeat the brief before you touch a second file.&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>ai</category>
    </item>
    <item>
      <title>Keep Hour-One Exploration Off Your First PR Branch</title>
      <dc:creator>Quinn Zhu</dc:creator>
      <pubDate>Thu, 08 Oct 2026 08:06:50 +0000</pubDate>
      <link>https://dev.to/gitgo_5662/keep-hour-one-exploration-off-your-first-pr-branch-5hcn</link>
      <guid>https://dev.to/gitgo_5662/keep-hour-one-exploration-off-your-first-pr-branch-5hcn</guid>
      <description>&lt;p&gt;Do not let an agent edit your first pull request branch. Explore on a separate clone or a free server. Bring notes back and leave the surprise diff behind.&lt;/p&gt;

&lt;p&gt;You just joined, so the repository still feels opaque. An agent can read faster than you can judge. That speed becomes a liability on your first pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure you are preventing
&lt;/h2&gt;

&lt;p&gt;The agent edits the same clone you plan to push. You skim a wide diff and approve your own confusion. Reviewers then ask why an unrelated file moved.&lt;/p&gt;

&lt;p&gt;Rollback turns into a search instead of a known sequence. Your first hour should prevent that search entirely. Pins come first, and generated patches come later.&lt;/p&gt;

&lt;p&gt;A junior pull request fails in a quiet way. The code may even pass a local check. The author still cannot explain the change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pin three facts before any prompt
&lt;/h2&gt;

&lt;p&gt;You need three written facts before the first prompt. Keep them in a local note beside the clone. Do not let the agent edit that note.&lt;/p&gt;

&lt;p&gt;Store that note outside the branch you will ship. A committed pin can be rewritten by the next edit. Your copy should survive a reset.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Capture the branch contract
&lt;/h3&gt;

&lt;p&gt;Run these commands from the clone you control. Save the raw output before you interpret it. Confirm the default branch before you create work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
git status &lt;span class="nt"&gt;--short&lt;/span&gt; &lt;span class="nt"&gt;--branch&lt;/span&gt;
git symbolic-ref &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD
git rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; origin/HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If origin HEAD is unset, ask a teammate before guessing. Do not assume main when the repo tracks trunk. A wrong base branch wastes the entire first review.&lt;/p&gt;

&lt;p&gt;Record the remote name next to the default branch. Later commands fail when you hard-code origin. That one line saves a messy recovery.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Name the review surface
&lt;/h3&gt;

&lt;p&gt;List the files you must reread before any push. Start with entry points, config, and auth boundaries. Add each path your ticket names in writing.&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;# review-surface.md&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; default_branch:
&lt;span class="p"&gt;-&lt;/span&gt; base_remote:
&lt;span class="p"&gt;-&lt;/span&gt; must_reread:
&lt;span class="p"&gt;  -&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; checks_i_will_run:
&lt;span class="p"&gt;  -&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; out_of_scope:
&lt;span class="p"&gt;  -&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You fill this file yourself, and the agent does not. If a path is unclear, leave the bullet blank. A blank line is safer than invented certainty.&lt;/p&gt;

&lt;p&gt;Name one check you can run without extra setup. A test command you cannot find is not a plan. Ask where the project documents that command.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Write the rollback card before the diff
&lt;/h3&gt;

&lt;p&gt;Write the revert sequence before any agent edit. Use placeholders until a real merge SHA exists. A card you cannot find is not a plan.&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;# Proposal only. Fill the SHA after the PR merges.&lt;/span&gt;
&lt;span class="c"&gt;# Do not run this until you intend to revert.&lt;/span&gt;
git switch &amp;lt;default-branch&amp;gt;
git pull &lt;span class="nt"&gt;--ff-only&lt;/span&gt;
git revert &lt;span class="nt"&gt;--no-edit&lt;/span&gt; &amp;lt;merge-sha&amp;gt;
git push origin HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Label the card as a proposal, not a result. Do not invent a SHA just to look ready. The sequence matters more than a guessed hash.&lt;/p&gt;

&lt;p&gt;Keep the card next to the review surface. If you need help, you can show both. A reviewer can correct the sequence early.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explore away from the branch you will ship
&lt;/h2&gt;

&lt;p&gt;You can read the repo with MonkeyCode free model access. A free server option can host that reading session. Disclosure: This article was prepared as part of MonkeyCode's product outreach.&lt;/p&gt;

&lt;p&gt;Confirm the current offer in the product before you rely on it. Do not assume a model name, a token quota, or a machine size. Treat availability as something you recheck, not a permanent promise.&lt;/p&gt;

&lt;p&gt;Use that session to map the ticket, not to push. Do not paste secrets, tokens, or production environment files. Do not add the server remote to your pull request branch.&lt;/p&gt;

&lt;p&gt;Copy notes back in words you can defend aloud. Retype any small patch you decide to keep. A pasted agent diff is not yet your change.&lt;/p&gt;

&lt;p&gt;If the free server is unavailable, use a second local clone. The boundary matters more than the hosting choice. Your pull request branch stays untouched either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  A reading prompt, labeled as a proposal
&lt;/h2&gt;

&lt;p&gt;This is a reading prompt, not a license to edit. Paste it only inside the separate explore session. Replace the ticket line before you send it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map this ticket. Do not edit files. Do not propose a full patch.
Ticket: &amp;lt;paste the ticket title only&amp;gt;
Return:
1. Files I should reread.
2. Commands I should run locally.
3. Risks if I change the wrong file.
Stop if you need secrets or production data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reject any reply that includes a commit or a push. Reject any reply that asks you to paste credentials. Keep the map, then do the reading on your clone.&lt;/p&gt;

&lt;p&gt;Treat the reply as a hint list, not as truth. Open each named file and confirm it exists. Drop any path the repository does not contain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table: what may cross back
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Cross back?&lt;/th&gt;
&lt;th&gt;Rule you apply&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Notes you rewrote&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;You can explain each line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command output&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Strip tokens, emails, and host secrets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generated patch&lt;/td&gt;
&lt;td&gt;Only after retype&lt;/td&gt;
&lt;td&gt;You run the listed checks yourself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Env files or keys&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Stop and rotate if they were copied&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unrequested lockfile edits&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Leave them out of the first PR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suggested commit message&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;You write the message after the diff&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the table before you copy anything home. If a row says no, delete that content locally. When unsure, keep the note and drop the patch.&lt;/p&gt;

&lt;p&gt;A useful map names files, risks, and local commands. A risky map includes secrets or a ready-made branch. Choose the map you can repeat without the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hour-one steps you can repeat
&lt;/h2&gt;

&lt;p&gt;Follow this order on the day you join. Do not skip to a prompt because the ticket looks small. Small tickets can still touch shared project files.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repository into a path you control.&lt;/li&gt;
&lt;li&gt;Run the branch-contract commands and store the output.&lt;/li&gt;
&lt;li&gt;Fill review-surface.md before you write a prompt.&lt;/li&gt;
&lt;li&gt;Write the rollback card with placeholders only.&lt;/li&gt;
&lt;li&gt;Open the explore session away from that clone.&lt;/li&gt;
&lt;li&gt;Ask for a file map of the ticket, not a patch.&lt;/li&gt;
&lt;li&gt;Bring rewritten notes back and update the surface file.&lt;/li&gt;
&lt;li&gt;Create the pull request branch only after those pins exist.&lt;/li&gt;
&lt;li&gt;Limit the diff to files you listed as in scope.&lt;/li&gt;
&lt;li&gt;Run the checks you named, then open the pull request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Stop at the first step you cannot complete honestly. Hour one can end with pins and no pull request. That outcome is still a successful join day.&lt;/p&gt;

&lt;h2&gt;
  
  
  How you know the notes are yours
&lt;/h2&gt;

&lt;p&gt;Read each note aloud before you trust it. If you stumble, the line is not ready to ship. Rewrite that line or drop it from the pull request.&lt;/p&gt;

&lt;p&gt;Check three questions before you create the branch. Can you name the default branch without looking it up? Can you name the check you will run?&lt;/p&gt;

&lt;p&gt;Can you point to the rollback card on disk? If any answer is no, stay in hour one. Do not open the real pull request yet today.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you put in the first pull request
&lt;/h2&gt;

&lt;p&gt;You write the pull request body in your own words. Name the ticket, the files, and the check you ran. State what you left unchanged and why that was right.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## What changed&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt;

&lt;span class="gu"&gt;## What I ran&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt;

&lt;span class="gu"&gt;## Out of scope&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt;

&lt;span class="gu"&gt;## Rollback&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; revert the merge commit on the default branch if this must come out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Link the ticket your team already assigned to you. Do not let the agent invent acceptance criteria. If the ticket is vague, stop and ask a human.&lt;/p&gt;

&lt;p&gt;Keep the first diff inside the files you listed. Extra files are a signal to pause, not to push. Explain a wider diff only after a teammate agrees.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rehearse the exit before the real pull request
&lt;/h2&gt;

&lt;p&gt;Before the real change, rehearse how you exit. Create a throwaway branch and one empty commit. Open a draft pull request, then close it unmerged.&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;-c&lt;/span&gt; scratch/hour-one-exit
git commit &lt;span class="nt"&gt;--allow-empty&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: rehearse pull request exit"&lt;/span&gt;
&lt;span class="c"&gt;# Open a draft with your team's normal command, then close it.&lt;/span&gt;
git switch &amp;lt;default-branch&amp;gt;
git branch &lt;span class="nt"&gt;-D&lt;/span&gt; scratch/hour-one-exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This drill is not a change you intend to ship. Close the draft and delete the local scratch branch. You want the exit path in memory, not an open request.&lt;/p&gt;

&lt;p&gt;If your team forbids empty commits, skip the commit. Still practice creating the branch and switching back. The goal is a calm exit, not a clever history.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small failure you can recognize
&lt;/h2&gt;

&lt;p&gt;Imagine the agent edits a lockfile you never requested. Your review surface did not list that file. The decision table says that edit stays out.&lt;/p&gt;

&lt;p&gt;Reset that path on the pull request branch only. Do not reset the whole clone if other work is present. Ask for help if you cannot see what changed.&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;--&lt;/span&gt; &amp;lt;path&amp;gt;
git restore &lt;span class="nt"&gt;--source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;default-branch&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; &amp;lt;path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the named check after the restore finishes. Then explain the remaining diff in the pull request body. If you still cannot explain it, do not push.&lt;/p&gt;

&lt;p&gt;Another failure is a note full of unfamiliar names. That note did not become knowledge by crossing back. Reread the file, or leave the change for later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations you should say out loud
&lt;/h2&gt;

&lt;p&gt;This workflow does not review the code for you. It only separates exploration from the branch you own. A free server can still leak data if you paste secrets.&lt;/p&gt;

&lt;p&gt;These steps do not replace your team's written policy. A local pin file cannot override CODEOWNERS or branch protection. You still need a human reviewer on the first pull request.&lt;/p&gt;

&lt;p&gt;I did not execute these commands against your repository. Treat every snippet as a proposal you must adapt. Replace origin if your remote uses another name.&lt;/p&gt;

&lt;p&gt;Free model access does not guarantee a correct map. Models miss local scripts, generated code, and private docs. Your reread is the check that matters.&lt;/p&gt;

&lt;p&gt;This also will not teach the whole codebase in one hour. It teaches a boundary you can reuse tomorrow. Depth comes from the next ticket, not a bigger prompt.&lt;/p&gt;

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

&lt;p&gt;Skip this if you already maintain the service yourself. Skip it when your team forbids external coding tools. Skip it when the ticket touches secrets or production data.&lt;/p&gt;

&lt;p&gt;Use the approved internal environment in those cases. A junior onboarding path is not an access bypass. If policy is unclear, ask before you open any session.&lt;/p&gt;

&lt;p&gt;Skip the separate server if the repo cannot leave the laptop. A second local clone still gives you the same split. Do not weaken security to follow a hosting tip.&lt;/p&gt;

&lt;h2&gt;
  
  
  After the pins exist
&lt;/h2&gt;

&lt;p&gt;If a free MonkeyCode server is already available, use it for the map only. Then return to your pinned clone and open the pull request yourself.&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>github</category>
    </item>
  </channel>
</rss>
