<?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: Parth Gupta</title>
    <description>The latest articles on DEV Community by Parth Gupta (@parth_gupta_23e13d0b1b826).</description>
    <link>https://dev.to/parth_gupta_23e13d0b1b826</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%2F3888690%2F1f206e61-04fe-4d49-b814-d80b17a84327.png</url>
      <title>DEV Community: Parth Gupta</title>
      <link>https://dev.to/parth_gupta_23e13d0b1b826</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/parth_gupta_23e13d0b1b826"/>
    <language>en</language>
    <item>
      <title>I built CI for prompts, and the first bug was in the tests</title>
      <dc:creator>Parth Gupta</dc:creator>
      <pubDate>Sun, 30 Aug 2026 14:19:08 +0000</pubDate>
      <link>https://dev.to/parth_gupta_23e13d0b1b826/i-built-ci-for-prompts-and-the-first-bug-was-in-the-tests-3jg2</link>
      <guid>https://dev.to/parth_gupta_23e13d0b1b826/i-built-ci-for-prompts-and-the-first-bug-was-in-the-tests-3jg2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Sentinel&lt;/strong&gt; is a prompt regression gate. It runs an eval suite against both versions of a&lt;br&gt;
changed prompt, accounts for run-to-run noise, and stops before merge. Built in a week for&lt;br&gt;
the Agent Harness Hackathon (WeMakeDevs × TrueFoundry × Qodo).&lt;br&gt;
Repo: &lt;a href="https://github.com/ParthGupta1304/sentinal" rel="noopener noreferrer"&gt;https://github.com/ParthGupta1304/sentinal&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The job we gave the agent
&lt;/h2&gt;

&lt;p&gt;ORCHESTRA is a multi-agent hackathon judge. Its clarity prompt is a real file,&lt;br&gt;
&lt;code&gt;backend/prompts/clarity-judge.md&lt;/code&gt;. When that file changes, nothing in CI notices. &lt;br&gt;
The output is a qualitative assessment, so regressions are invisible: JSON still parses, the&lt;br&gt;
score still looks plausible, and &lt;code&gt;chiefJudge&lt;/code&gt; quietly keys its confidence off a fallback&lt;br&gt;
sentence that is no longer there.&lt;/p&gt;

&lt;p&gt;Sentinel’s job: read the PR, run 10 cases against both versions, N=3, and only call a drop&lt;br&gt;
a regression when it &lt;strong&gt;exceeds&lt;/strong&gt; the spread observed on the unchanged prompt. Then stop.&lt;br&gt;
A human merges.&lt;/p&gt;

&lt;h2&gt;
  
  
  What TrueForge handled
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub MCP&lt;/strong&gt; — read the PR, read the file at both refs, comment, merge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox&lt;/strong&gt; — generated assertion code and result files. Writes outside the working
directory are rejected (&lt;code&gt;/tmp&lt;/code&gt; fails on purpose).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval&lt;/strong&gt; — &lt;code&gt;merge_pull_request&lt;/code&gt; and &lt;code&gt;pull_request_review_write&lt;/code&gt; only. The harness
default of &lt;code&gt;@write&lt;/code&gt; would have paused us before posting the findings, which defeats the
product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagents&lt;/strong&gt; — one batch of cases each. They return &lt;code&gt;{case_id, scores, median, spread}&lt;/code&gt;,
never raw output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sessions&lt;/strong&gt; — close the tab, reopen, the turn is still there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill&lt;/strong&gt; — &lt;code&gt;sentinel-scoring&lt;/code&gt;, the noise-floor protocol, loaded into the sandbox.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We wrote the evals, the variance math, and a dashboard that says “This change made 2 tests worse” instead of a lab plot.&lt;/p&gt;

&lt;h2&gt;
  
  
  What broke along the way
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The judge could not see the submission.&lt;/strong&gt; We sent it the criterion and the output.&lt;br&gt;
Any rubric that mentioned “the input” was unanswerable. The judge said so in its own justification rather than guessing, and we scored it down for being honest. Fix: pass the case input. Blindness is about &lt;em&gt;which version&lt;/em&gt; produced the output, not about hiding the&lt;br&gt;
fixed case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;temperature&lt;/code&gt; is rejected by &lt;code&gt;claude-sonnet-5&lt;/code&gt;.&lt;/strong&gt; The first calibration pass failed every rubric case with HTTP 400. Stability comes from disabling thinking, not from temperature 0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Four criteria demanded behaviour the prompt never promised.&lt;/strong&gt; Including one that punished the judge for returning its documented fallback on empty input. Those are bad cases, not discovered bugs. Deleted or rewritten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The subject, not the judge, flickered.&lt;/strong&gt; &lt;code&gt;gpt-4o-mini&lt;/code&gt; returns an empty &lt;code&gt;improvements&lt;/code&gt; array on roughly one run in three with no prompt change. Noise floor 0.80 on a 0–1 scale: no drop could ever exceed it. Deleted the rubric rather than keep a check that can never&lt;br&gt;
produce a verdict.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A self-gate is not a gate.&lt;/strong&gt; An early instruction said “do not merge.” The model dutifully refused. No &lt;code&gt;tool.approval_required&lt;/code&gt; event ever fired. The human never saw a checkpoint. The instructions now say: when a human asks you to merge, &lt;em&gt;call the tool&lt;/em&gt;.&lt;br&gt;
The harness holds it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An unknown &lt;code&gt;--case&lt;/code&gt; used to exit 0.&lt;/strong&gt; Compare ran zero cases, wrote &lt;code&gt;verdict: clean&lt;/code&gt;, and would have passed CI. Calibrate already rejected the typo. Compare now does too.&lt;/p&gt;

&lt;h2&gt;
  
  
  The demo regression
&lt;/h2&gt;

&lt;p&gt;Someone “tightens” the prompt by deleting the line that says: if there is nothing to evaluate, return score 0 with a fixed sentence. JSON still parses. Production would look&lt;br&gt;
fine — ORCHESTRA’s parser even strips code fences and can send broken JSON to GPT-4o to repair. Sentinel asserts on the &lt;strong&gt;raw&lt;/strong&gt; string.&lt;/p&gt;

&lt;p&gt;Measured: empty submission 1.00 → 0.80, no-problem-statement 1.00 → 0.67, eight tests flat. Exit 2. On a cheap re-run, the new prompt scored the empty submission &lt;strong&gt;16&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is the whole product in one number.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we would do next
&lt;/h2&gt;

&lt;p&gt;A GitHub App instead of a laptop runner. A suite that grows from production traffic.&lt;br&gt;
The eval cases are the asset that does not move to a competitor.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
