<?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: Sai Ram Dash</title>
    <description>The latest articles on DEV Community by Sai Ram Dash (@ewwhardik).</description>
    <link>https://dev.to/ewwhardik</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%2F4109572%2F171c45ae-030a-4544-9128-282b34acdbd2.jpg</url>
      <title>DEV Community: Sai Ram Dash</title>
      <link>https://dev.to/ewwhardik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ewwhardik"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Sai Ram Dash</dc:creator>
      <pubDate>Thu, 01 Oct 2026 05:04:48 +0000</pubDate>
      <link>https://dev.to/ewwhardik/-41p4</link>
      <guid>https://dev.to/ewwhardik/-41p4</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ewwhardik/one-sql-update-reopened-a-closed-hackathon-the-checker-still-exited-0-afh" class="crayons-story__hidden-navigation-link"&gt;One SQL Update Reopened a Closed Hackathon. The Checker Still Exited 0.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/ewwhardik" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4109572%2F171c45ae-030a-4544-9128-282b34acdbd2.jpg" alt="ewwhardik profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ewwhardik" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Sai Ram Dash
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Sai Ram Dash
                
                
              
              &lt;div id="story-author-preview-content-4780520" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ewwhardik" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4109572%2F171c45ae-030a-4544-9128-282b34acdbd2.jpg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Sai Ram Dash&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ewwhardik/one-sql-update-reopened-a-closed-hackathon-the-checker-still-exited-0-afh" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 1&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ewwhardik/one-sql-update-reopened-a-closed-hackathon-the-checker-still-exited-0-afh" id="article-link-4780520"&gt;
          One SQL Update Reopened a Closed Hackathon. The Checker Still Exited 0.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dogfoodhack"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dogfoodhack&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/sairamdash"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;sairamdash&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hardikdash"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hardikdash&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hackathonraptors"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hackathonraptors&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ewwhardik/one-sql-update-reopened-a-closed-hackathon-the-checker-still-exited-0-afh" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;20&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ewwhardik/one-sql-update-reopened-a-closed-hackathon-the-checker-still-exited-0-afh#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            13 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>One SQL Update Reopened a Closed Hackathon. The Checker Still Exited 0.</title>
      <dc:creator>Sai Ram Dash</dc:creator>
      <pubDate>Thu, 01 Oct 2026 04:41:17 +0000</pubDate>
      <link>https://dev.to/ewwhardik/one-sql-update-reopened-a-closed-hackathon-the-checker-still-exited-0-afh</link>
      <guid>https://dev.to/ewwhardik/one-sql-update-reopened-a-closed-hackathon-the-checker-still-exited-0-afh</guid>
      <description>&lt;p&gt;A closed hackathon accepted a submission with HTTP 200.&lt;/p&gt;

&lt;p&gt;The fixture event was closed. The official checker tried to submit to it anyway, and the server was supposed to refuse. This was meant to be the boring part of Manak, the hackathon judging portal I built.&lt;/p&gt;

&lt;p&gt;The cause was in my demo seed. While opening community voting, I had used one parameter for two deadlines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="s2"&gt;`update event set voting_mode = 'open', voting_open_at = :o,
 voting_close_at = :c, voting_credits = 100,
 submissions_close_at = :c where id = :e`&lt;/span&gt;

&lt;span class="c1"&gt;// The same :c binding served both deadlines.&lt;/span&gt;
&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;systemClock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3600000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two deadlines, one binding. The closed fixture event got another 48 hours, the stored window allowed the submission, and the server did what its data told it to. I had written the data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpl9bruvuuiqlorcrr3qc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpl9bruvuuiqlorcrr3qc.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Historical regression and repair. Reusing a deadline binding changed which submissions the event allowed. &lt;a href="https://github.com/ewwhardik/manak/blob/main/tools/seed-dogfood-full.ts" rel="noopener noreferrer"&gt;Current seed implementation&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Six probes passed. The closed-event probe failed, taking the first-tier acceptance gate with it. The checker still exited with code zero. The report contained the answer; the process status did not carry it. An old green report and a successfully completed command were both poor substitutes for reading what the running demo had actually done.&lt;/p&gt;

&lt;p&gt;I changed the seed to read the imported submission deadline and bind it separately. The completed fixture showcase keeps its voting window closed too. The corrected official receipt reads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T1  gallery is public ................. PASS
T1  project from fixtures shown ....... PASS
T1  closed event refuses submissions .. PASS
T2  judge sees own scores ............. PASS
T2  judge cannot see peer scores ...... PASS
T2  participant blocked ............... PASS
T2  csv export works .................. PASS

claimed T1 T2 T3 T4, verified T1 T2
note: claimed but not verified: T3 T4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seven passing probes, two verified tiers. Both belong in the description of that result.&lt;/p&gt;

&lt;p&gt;An interactive demo needs its own event state. Its convenience settings cannot rewrite the canonical fixture's rules. That small repair also explains the larger build: a judging system has to preserve the conditions under which a decision is valid. The first condition I had broken was the deadline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the event around the score
&lt;/h2&gt;

&lt;p&gt;Manak—मानक, “standard”—takes an event from submissions to signed awards. Organizers define tracks and a versioned weighted rubric. Teams submit projects. Eligible judges receive assignments, keep private drafts and submit scores. Organizers publish a frozen result revision, record award decisions and issue signed certificates.&lt;/p&gt;

&lt;p&gt;That sequence became the useful unit of design. Calculating a score is one stage. Getting the right evidence into it, deciding when it becomes official and retaining what that decision meant are the surrounding stages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fypc9a57hza7pqq6fcdml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fypc9a57hza7pqq6fcdml.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The runtime uses Node's HTTP, SQLite, crypto and test APIs, native TypeScript stripping and server-rendered HTML. There are zero runtime npm packages; TypeScript and Node type definitions remain development dependencies. The main forms work without browser JavaScript. The enhanced editor and offline verifier use it.&lt;/p&gt;

&lt;p&gt;A declared command registry feeds capabilities, validation and OpenAPI, although some transport routes sit outside it. I also wrote the request schema layer: the same field declarations drive validation, JSON Schema and form rendering. URL-encoded forms can opt into converting strings to numbers; JSON clients must send typed numbers. Unknown fields are refused. A form's &lt;code&gt;"5"&lt;/code&gt; and a JSON client's &lt;code&gt;5&lt;/code&gt; need a deliberate contract before either reaches a score column. The package graph is small. The amount of application behavior I own is less cooperative. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/api/schema.ts" rel="noopener noreferrer"&gt;Request schema&lt;/a&gt;, &lt;a href="https://github.com/ewwhardik/manak#readme" rel="noopener noreferrer"&gt;stack and setup&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg1utc9lq5o2494wk7doz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg1utc9lq5o2494wk7doz.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A spreadsheet leaves deadlines, permissions and publication snapshots to a process. A live ranking page makes the latest ordering easy to see, but still needs a rule about what later edits do to an announced result. I put those obligations into explicit application state. The cost is more transitions, migrations and tests. The benefit is being able to ask the code where a rule is enforced.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;What it makes easy&lt;/th&gt;
&lt;th&gt;What still needs an owner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Spreadsheet and manual process&lt;/td&gt;
&lt;td&gt;Inspecting and changing scores&lt;/td&gt;
&lt;td&gt;Permissions, deadline enforcement, snapshots and award records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live ranking page&lt;/td&gt;
&lt;td&gt;Showing the latest ordering&lt;/td&gt;
&lt;td&gt;Deciding whether later edits should move a published result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manak's explicit workflow&lt;/td&gt;
&lt;td&gt;Enforcing transitions and retaining decision context&lt;/td&gt;
&lt;td&gt;Application state, migrations, tests and operational maintenance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvcvtkftuivpsh7kdt2ey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvcvtkftuivpsh7kdt2ey.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Design tradeoffs, not a benchmark or a claim about every competing product. Each approach leaves a different part of the judging process for someone to maintain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is why the portal is larger than a score form and a sort. Team ownership, a judge's conflict, a rubric edit and an organizer's correction all change which actions should be possible. Giving each one a visible state costs code, but it also gives the next stage something more precise than an assumption to work with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the rule where the write happens
&lt;/h2&gt;

&lt;p&gt;My governing rule is: if breaking a rule would invalidate a decision, enforce it at the write boundary and keep the evidence needed to inspect it later.&lt;/p&gt;

&lt;p&gt;This is the database trigger for submission timestamps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;trigger&lt;/span&gt; &lt;span class="n"&gt;project_submission_window&lt;/span&gt; &lt;span class="k"&gt;before&lt;/span&gt; &lt;span class="k"&gt;update&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;submitted_at&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'submitted'&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;submitted_at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;submissions_open_at&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;submitted_at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;submissions_close_at&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'project submission timestamp outside event window'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It checks the supplied timestamp against the stored window. It cannot establish that the window itself is correct. Once my seed moved the deadline, the trigger had a perfectly valid reason to allow the submission. Constraints, authorized state transitions and fixture setup have separate jobs; the opening bug crossed the gap between them. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/db/migrations/016_invariant_triggers.sql" rel="noopener noreferrer"&gt;Invariant triggers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Refusals needed a boundary too. A denied write should leave no audit-ledger effects. My isolation check sends requests through actual sockets: 102 operations, six witnesses and two renderings make 1,224 requests. It records 674 refusals, including 418 writes, with zero ledger appends from refused requests and zero chain breaks.&lt;/p&gt;

&lt;p&gt;The test also rejects an easy false positive. A parser error or rate-limit response cannot stand in for an authorization refusal. Otherwise I could congratulate the permission check for a request that never reached it. The proof covers the declared command matrix; transport exceptions remain outside that coverage. &lt;a href="https://github.com/ewwhardik/manak/blob/main/docs/proof/isolation.md" rel="noopener noreferrer"&gt;Isolation proof&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collect evidence the model can compare
&lt;/h2&gt;

&lt;p&gt;Judges see subsets of projects. Scheduling therefore changes what the statistical model can know.&lt;/p&gt;

&lt;p&gt;If two panels judge disjoint groups, a low-scoring panel might be stricter, or its projects might be weaker. Scores alone cannot identify the relative panel offsets. No amount of arithmetic supplies the missing connection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpc9lr0ccafyj2w3zxvtw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpc9lr0ccafyj2w3zxvtw.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The scheduler starts with the most constrained projects and assigns work to eligible judges carrying lighter loads. It then uses augmenting paths to fill slots that a local placement can leave stranded. An existing assignment can move to make room for another, provided every edge remains eligible and every capacity still holds. If the requested coverage is impossible, the shortfall stays visible. Quietly relaxing a conflict would make the schedule look complete by changing what “complete” meant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2r7u085r1acjqevtqzbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2r7u085r1acjqevtqzbd.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For small cases, I can give the scheduler an unusually stubborn reviewer: enumerate every answer. The test covers all 512 eligibility graphs for three projects and three judges, targets of one and two reviews, and capacities of &lt;code&gt;[1, 2, 1]&lt;/code&gt;. It compares the result with every admissible edge subset. This is practical at that size and avoids making the oracle another copy of the scheduling algorithm. It establishes those small cases, without pretending to prove every possible event. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/judging/assign.ts" rel="noopener noreferrer"&gt;Scheduler&lt;/a&gt;, &lt;a href="https://github.com/ewwhardik/manak/blob/main/tests/assignment-completeness.test.ts" rel="noopener noreferrer"&gt;completeness test&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Collecting the right evidence also means keeping working state out of it. The loader selects submitted ballots for the resolved published rubric version and excludes memberships whose evidence has been excluded. Drafts cannot move the fit. A submitted ballot must cover every criterion, and scores retain their rubric version. Once a version has scores, database triggers reject adding, editing or deleting its criteria. Otherwise a later rubric edit could change the meaning of an earlier judgment without the judge touching it. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/db/repo/judging.ts" rel="noopener noreferrer"&gt;Evidence loader&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the model compete with simpler answers
&lt;/h2&gt;

&lt;p&gt;The rubric model fits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;score(project, judge)
  = grand mean + project effect + judge offset + residual
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also estimates each judge's scale and shrinks it toward one. A judge who gives every project the same score carries little ordering information. Dividing by a tiny spread should not turn that into a powerful opinion. Scale floors and information weights handle that case. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/judging/normalize.ts" rel="noopener noreferrer"&gt;Model implementation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The machinery then owes a comparison. I tested raw means, per-judge z-scores and the fitted model against planted rankings in synthetic events. The displayed regimes quantize and clamp scores to 1–5. The full sweep covers 59 configurations over 20 seeds, or 1,180 event runs.&lt;/p&gt;

&lt;p&gt;The balanced case uses the production scheduler. The correlated cases deliberately substitute assignments in which judges are grouped by leniency and projects increasingly prefer one judge cohort. Planted project quality is generated independently. The experiment changes which judge groups see which projects; it does not establish a true ranking for a real event.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assignment regime&lt;/th&gt;
&lt;th&gt;Raw mean&lt;/th&gt;
&lt;th&gt;Per-judge z-score&lt;/th&gt;
&lt;th&gt;Fitted model&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Balanced&lt;/td&gt;
&lt;td&gt;0.7865&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.8369&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.7935&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mildly correlated&lt;/td&gt;
&lt;td&gt;0.7630&lt;/td&gt;
&lt;td&gt;0.8564&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.8942&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strongly correlated&lt;/td&gt;
&lt;td&gt;0.7046&lt;/td&gt;
&lt;td&gt;0.8565&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.8907&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3bqndoiphm207rdmbzon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3bqndoiphm207rdmbzon.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The balanced row spoils the clean story: the simpler z-score baseline wins. The fitted model's worst balanced seed is &lt;strong&gt;0.6147&lt;/strong&gt;. Its lead in the two displayed correlated regimes is an advantage under particular assignment conditions, which is more useful than declaring normalization solved.&lt;/p&gt;

&lt;p&gt;Production ranking uses the fitted model. The normalization sandbox exposes alternative calculations for comparison, including raw means and within-reviewer z-scores, but is read-only; it does not select a different publication method. That makes the losing balanced result relevant to the system I actually built. The comparison is there to inspect the choice, not to make its cost disappear. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/api/commands/results.ts" rel="noopener noreferrer"&gt;Production ranking&lt;/a&gt;, &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/judging/sandbox.ts" rel="noopener noreferrer"&gt;sandbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The bundled fixtures answer a different question. They contain 41 projects, 30 registered judges and 126 imported ballots. Dry Relay moves from raw rank four to adjusted rank one; Slow Trail moves from six to nineteen. There is no known true ranking in those fixtures. Movement shows that the model changes decisions, not that it improves them. The import's equal criterion weights are an implementation choice, not an asserted organizer rule. &lt;a href="https://github.com/ewwhardik/manak/blob/main/docs/proof/fixtures.md" rel="noopener noreferrer"&gt;Fixture report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Giving the fit more computation produced another awkward result. Three outer rounds with a 200-iteration inner cap did not converge on the fixture data. Twelve rounds with a 1,000-iteration cap settled the fit. In the separate holdout check, which keeps some ballots out of fitting and predicts them, weighted-score RMSE increased from &lt;strong&gt;1.017 to 1.038&lt;/strong&gt;. The optimizer was more settled. Its predictions were slightly worse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0kmlt1lyci9ehjwephxb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0kmlt1lyci9ehjwephxb.png" alt=" " width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The larger iteration budget is the production default. It does not guarantee convergence on another event, so the warning still matters. Settling the fit and testing its predictions remain separate jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep a second kind of judgment in its own model
&lt;/h2&gt;

&lt;p&gt;Rubric judging asks how a project performed on weighted criteria. Pairwise judging asks which of two projects a reviewer prefers. Those observations can both be useful without sharing a numerical scale.&lt;/p&gt;

&lt;p&gt;Manak uses a separate Bradley–Terry model for pairwise evidence. Its fitted strengths describe relative preference. They are not rubric-score units, so adding them to a normalized rubric result would manufacture a conversion the observations do not supply. A skipped comparison is excluded from the pairwise input rather than quietly counted as evidence for either project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3zk6k05iw1jwcbri8or.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3zk6k05iw1jwcbri8or.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connectivity matters here too. A set of preferences inside one group does not establish its position relative to an unconnected group. Missing, disconnected or nonconverged pairwise evidence must not produce confident finalist probabilities. The implementation keeps those checks between the fit and the recommendation.&lt;/p&gt;

&lt;p&gt;The same restraint applies to uncertainty in rubric results. Overlapping approximate 95% bands can call for more evidence; they do not establish that the projects are equivalent. A request for another review is a useful output when the current evidence cannot support the precision of the proposed decision. Another decimal place is cheaper to generate, but it answers a different question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give publication an explicit boundary
&lt;/h2&gt;

&lt;p&gt;A live dashboard should reflect new evidence. A ceremony needs a stable account of the decision that was actually made.&lt;/p&gt;

&lt;p&gt;Manak stores a publication revision with the rubric version, algorithm and options, evidence digest, ledger head and report. The publication command builds the report and stores the revision in a transaction. The outer transaction uses SQLite's &lt;code&gt;BEGIN IMMEDIATE&lt;/code&gt;; nested operations use savepoints. Evidence is hashed in stable primary-key order while the write lock is held, and the mutation and ledger append commit together. The report, digest and revision therefore share a transaction instead of being separately committed descriptions of a moving event. Public results and explanations read the stored report.&lt;/p&gt;

&lt;p&gt;The regression test is deliberately rude to this boundary: publish revision one, then change a ballot. The published project results must stay fixed. An explicit second publication creates revision two, and award decisions attached to revision one stop applying. Carrying them forward would attach a decision to evidence the organizer had never approved. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/db/publication.ts" rel="noopener noreferrer"&gt;Publication code&lt;/a&gt;, &lt;a href="https://github.com/ewwhardik/manak/blob/main/tests/audit-regressions.test.ts" rel="noopener noreferrer"&gt;regression tests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6uacrq81hbjy7n8fm7hm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6uacrq81hbjy7n8fm7hm.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The audit ledger uses a linear SHA-256 hash chain. That makes continuity inspectable. Someone with database write access can still recompute the whole chain, so detecting that rewrite requires a head anchor retained independently. The anchor is part of the design's trust condition; the local chain alone cannot make the database tamper-proof.&lt;/p&gt;

&lt;p&gt;Awards are explicit organizer decisions attached to a publication revision. Only those decisions can mint placement certificates. A sorted list supplies evidence. The organizer still owns the award.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build an ending that survives the server
&lt;/h2&gt;

&lt;p&gt;A certificate record becomes a canonical ordered field array, then a SHA-256 digest and an Ed25519 signature. The signed fields bind the issuer key, publication revision and evidence digest. Version three also binds the template presentation and logo hash. A certificate can look convincing while its record is wrong, so the signed content needs its own verification path.&lt;/p&gt;

&lt;p&gt;An offline browser or a standard-library Python verifier can check the signature. Both need an independent reason to trust the issuer public key. Neither can discover a later revocation, establish an external identity or prove the award was deserved. Those limits determine what the verification result means. &lt;a href="https://github.com/ewwhardik/manak/blob/main/src/db/cert.ts" rel="noopener noreferrer"&gt;Certificate implementation&lt;/a&gt;, &lt;a href="https://github.com/ewwhardik/manak/blob/main/tools/verify_record.py" rel="noopener noreferrer"&gt;Python verifier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The tests check an original certificate, change its recipient name and require verification to fail. A different public key must fail too. A separate test issues legacy, v2 and v3 records, including Unicode, and invokes the Python CLI against them. The valid records pass; altering the v3 recipient name makes the CLI exit one. That tests the handoff between the issuer and a second implementation of the verifier. &lt;a href="https://github.com/ewwhardik/manak/blob/main/tests/cert.test.ts" rel="noopener noreferrer"&gt;Signature tests&lt;/a&gt;, &lt;a href="https://github.com/ewwhardik/manak/blob/main/tests/verify-record.test.ts" rel="noopener noreferrer"&gt;Python verifier tests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftfpym2j3zhd4b6wlld9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftfpym2j3zhd4b6wlld9w.png" alt=" " width="800" height="512"&gt;&lt;/a&gt;&lt;br&gt;
Data needs an exit too. The archive roundtrip proof exports 162 rows across 33 table files, imports them, exports again and finds zero differing files. It also feeds the importer eleven damaged archives. All are refused, with zero rows committed by those refusals. A failed import that leaves half an event behind would be a rather expensive interpretation of “failed.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6u7rxk37lalj5zrc7bz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6u7rxk37lalj5zrc7bz8.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The difficult part is making the stages agree
&lt;/h2&gt;

&lt;p&gt;Several of these choices trade convenience for a decision that retains its meaning:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;What it preserves&lt;/th&gt;
&lt;th&gt;What it costs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Keep conflicts and capacities hard&lt;/td&gt;
&lt;td&gt;Eligible judging evidence&lt;/td&gt;
&lt;td&gt;Coverage may remain incomplete&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wait for community voting to close before publishing&lt;/td&gt;
&lt;td&gt;A completed evidence window&lt;/td&gt;
&lt;td&gt;Publication must wait&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bind awards to publication revisions&lt;/td&gt;
&lt;td&gt;The result the organizer approved&lt;/td&gt;
&lt;td&gt;Decide again after republishing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Require an explicit placement decision&lt;/td&gt;
&lt;td&gt;Organizer ownership of the award&lt;/td&gt;
&lt;td&gt;Record the placement before minting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Withhold unsupported pairwise probabilities&lt;/td&gt;
&lt;td&gt;An honest account of the evidence&lt;/td&gt;
&lt;td&gt;Sometimes collect another review&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Testing those choices meant pushing on the connections: enumerate assignments, change a ballot after publication, damage an archive, inspect the ledger after a refused write. The full 15-stage API lifecycle then joins the pieces, including refusing publication while voting is open and allowing it after voting closes.&lt;/p&gt;

&lt;p&gt;On 1 October 2026, the local checks ran again with Node 24.18 on Windows, including the official checker against a clean seeded local demo. Keeping the scope beside the count makes the results easier to use:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Recorded result&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Official acceptance after repairs&lt;/td&gt;
&lt;td&gt;7 probes pass; T1/T2 verified&lt;/td&gt;
&lt;td&gt;T3/T4 remain unverified by this checker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project-authored extended checker&lt;/td&gt;
&lt;td&gt;18 verified, 0 failed, 7 partial, 3 blocked&lt;/td&gt;
&lt;td&gt;Additional probes, not official tier acceptance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test suite&lt;/td&gt;
&lt;td&gt;608 tests: 607 pass, 0 fail, 1 skip&lt;/td&gt;
&lt;td&gt;Local run; skipped Windows SIGTERM-related case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integrated API workflow&lt;/td&gt;
&lt;td&gt;15 stages pass&lt;/td&gt;
&lt;td&gt;Local lifecycle, including the voting/publication boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command isolation&lt;/td&gt;
&lt;td&gt;1,224 requests; 674 refusals; 418 refused writes; 0 refused-request ledger appends&lt;/td&gt;
&lt;td&gt;Declared command matrix through sockets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assignment enumeration&lt;/td&gt;
&lt;td&gt;512 eligibility graphs, two target values&lt;/td&gt;
&lt;td&gt;Three projects, three judges, fixed capacities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Normalization sweep&lt;/td&gt;
&lt;td&gt;1,180 synthetic events&lt;/td&gt;
&lt;td&gt;Rank recovery against planted truth under constructed assumptions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archive roundtrip&lt;/td&gt;
&lt;td&gt;162 rows; 33 table files; 0 export differences&lt;/td&gt;
&lt;td&gt;Exported payloads; 11 damaged archives refused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript check&lt;/td&gt;
&lt;td&gt;Passes without diagnostics&lt;/td&gt;
&lt;td&gt;Development compiler, separate from runtime dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc4x55h5nxzxay8bdojm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc4x55h5nxzxay8bdojm1.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The extended checker is mine. Its ledger probe checks links and the head, rather than independently rehashing every payload. Its webhook probe covers payload generation, rather than establishing receiver delivery and retry behavior. Those are reasons to keep the deeper tests and proof reports, not to relabel a partial probe as a complete workflow. Some blocked probes concern voting and shuffle on the fixture whose voting window is closed—the completed state preserved by the opening repair.&lt;/p&gt;

&lt;p&gt;The proof reports are reproducible too. This command checks the isolation report against its committed result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run prove:isolation -- --check
prove:isolation OK — 1224 requests, 6 witnesses, 674 refusals, none of which appended to the ledger; docs/proof/isolation.md reproduced byte for byte.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A report that can disagree with the code is more useful than another green badge.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/ewwhardik/856168-differential-checks-later-what-it-actually-takes-to-delete-your-dependencies-4763"&gt;previous write-up&lt;/a&gt;, I looked at the responsibilities that remain after removing dependencies. Manak made that responsibility concrete at a different level: every stage can follow its local rules while the event as a whole is wrong.&lt;/p&gt;

&lt;p&gt;The opening report had already demonstrated it. The server accepted a timestamp inside the stored window. The checker completed. The failed probe revealed that the window no longer represented the closed event. The repair was only a separate SQL binding, but understanding why it mattered required keeping all three facts together.&lt;/p&gt;

&lt;p&gt;The score is the compact output of this work. What I want to outlive the leaderboard is the explanation: what the judges saw, what the model did with it and exactly which result the organizer approved. Building the portal meant making those answers survive each transition, including the ones introduced by my own setup code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ewwhardik/manak" rel="noopener noreferrer"&gt;Source code&lt;/a&gt; · &lt;a href="https://manak.up.railway.app" rel="noopener noreferrer"&gt;Demo&lt;/a&gt; · &lt;a href="https://youtu.be/Wev9sf-WCa4" rel="noopener noreferrer"&gt;Demo video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sai Ram Dash&lt;/em&gt; (Hardik), Nastik AI. Built for the Hackathon Raptors;&lt;/p&gt;

</description>
      <category>dogfoodhack</category>
      <category>sairamdash</category>
      <category>hardikdash</category>
      <category>hackathonraptors</category>
    </item>
    <item>
      <title>856,168 differential checks later: what it actually takes to delete your dependencies</title>
      <dc:creator>Sai Ram Dash</dc:creator>
      <pubDate>Fri, 04 Sep 2026 11:39:48 +0000</pubDate>
      <link>https://dev.to/ewwhardik/856168-differential-checks-later-what-it-actually-takes-to-delete-your-dependencies-4763</link>
      <guid>https://dev.to/ewwhardik/856168-differential-checks-later-what-it-actually-takes-to-delete-your-dependencies-4763</guid>
      <description>&lt;p&gt;Somewhere around check number three hundred thousand, my test harness stopped testing my code and started testing the code I was replacing.&lt;/p&gt;

&lt;p&gt;The check was &lt;code&gt;intersects('1.2.3-beta', '*')&lt;/code&gt;. Mine said false. &lt;code&gt;semver@7.8.5&lt;/code&gt; said false. Then the harness swapped the arguments, because a harness does not know that no reasonable person swaps the arguments, and the package said true.&lt;/p&gt;

&lt;p&gt;Same function, same two strings, opposite order, opposite answer. Intersection is symmetric in every definition of the word anybody has written down. One hundred and eighty-eight million weekly downloads disagree.&lt;/p&gt;

&lt;p&gt;I had built the harness to find my bugs. It found one of theirs, and then handed me a problem that no amount of testing solves: I had to decide which of us was right, and there is no authority to appeal to. That turned out to be the actual work. Not the typing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;nirdep&lt;/code&gt;. &lt;strong&gt;nir&lt;/strong&gt; (Sanskrit निर्, "without") plus &lt;strong&gt;dep&lt;/strong&gt;. Say it "near-dep". It deletes your dependencies.&lt;/p&gt;

&lt;p&gt;It is two halves that only make sense together. The first is a runtime: five modules written against the Node standard library and nothing else, standing in for eleven packages people install without thinking about it, which is chalk, strip-ansi, supports-color, ansi-styles, semver, minimatch, glob, lodash, minimist, commander and yargs. The second is a codemod: a hand-written JavaScript lexer, a scope-aware binding resolver and a byte-range patcher, so that removing a dependency is a diff you read rather than a weekend you lose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F53mtn8eesx3b8kpqry3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F53mtn8eesx3b8kpqry3m.png" alt=" " width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tool runs on its own runtime. Its help text is generated by the module that replaces commander, its colours come from the module that replaces chalk, and its version comparisons come from the module that replaces semver. That is the correctness argument, and it is a cheap one to check: if the replacements were bad, the tool would not start.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you would normally install, and what it actually took
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Normally installed&lt;/th&gt;
&lt;th&gt;What replaced it&lt;/th&gt;
&lt;th&gt;What it cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;chalk, strip-ansi, ansi-styles, supports-color&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;runtime/colour&lt;/code&gt;, 552 lines&lt;/td&gt;
&lt;td&gt;the escape codes are the easy part; capability detection is the work, and &lt;code&gt;FORCE_COLOR&lt;/code&gt; beating &lt;code&gt;NO_COLOR&lt;/code&gt; is a decision rather than a fact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;semver&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;runtime/semver&lt;/code&gt;, 1,760 lines, no regular expressions&lt;/td&gt;
&lt;td&gt;507,316 differential checks, 72 audited disagreements, and 0.26 times the reference speed on &lt;code&gt;satisfies&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;minimatch, and the matching half of glob&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;runtime/glob&lt;/code&gt;, 1,149 lines, no regular expressions&lt;/td&gt;
&lt;td&gt;228,852 checks, 697 disagreements, every one bucketed by cause and pinned by count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;the seventeen lodash functions people actually reach for&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;runtime/collect&lt;/code&gt;, 994 lines&lt;/td&gt;
&lt;td&gt;120,000 comparisons over 8,000 seeded rounds, eleven pinned divergences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;minimist, commander, yargs&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;runtime/args&lt;/code&gt;, 990 lines&lt;/td&gt;
&lt;td&gt;rewritten by hand at every call site on purpose, which I will come back to&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The four reference packages I could measure on disk install 2,085,975 bytes across 1,164 files. The five modules that replace them are 223,069 bytes in five files. That number is the good half of the trade. The bad half is that those five files are now mine to maintain forever, and the README says so in the same paragraph, because a write-up that reports only the good half is an advertisement.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule that shaped everything
&lt;/h2&gt;

&lt;p&gt;CVE-2022-25883 was a ReDoS in node-semver's range parser: hand it a range from an untrusted source and it hangs. CVE-2022-3517 was the same bug class in minimatch's brace expansion, inside the package semver itself depends on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwvj239jnql6v4z97mzwv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwvj239jnql6v4z97mzwv.png" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Replace either one with my own regular expression and I would have shipped the same bug class with my name on it and called it progress. So the rule for both modules was: no regular expressions at all. Every scanner is a loop over character codes, and the matcher is two nested state-set simulations, one over path segments and one over the characters inside a segment. Work is positions times tokens. Backtracking is absent rather than patched.&lt;/p&gt;

&lt;p&gt;Claims like that rot, so the test does not trust me. &lt;code&gt;tests/repo/no-regex.test.mjs&lt;/code&gt; lexes both files with the project's own lexer, because &lt;code&gt;/&lt;/code&gt; is division, a comment and a regular expression, and only a tokeniser knows which one it is looking at. It fails if a single regexp literal survives, and it enforces a token floor, so a refactor that quietly deletes the matcher cannot pass by having nothing left to check.&lt;/p&gt;

&lt;p&gt;The price is on the invoice. &lt;code&gt;satisfies&lt;/code&gt; runs at 0.26 times the reference, it is in &lt;code&gt;bench.json&lt;/code&gt;, and I am not going to pretend a state machine beats a compiled regex at its own game. Two of the five went the other way and I did not plan either: the no-regex matcher runs at 1.37 times minimatch, and &lt;code&gt;cloneDeep&lt;/code&gt; at 1.40 times lodash. I would not have believed either claim without the numbers file, which is roughly why the numbers file exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  The difficulties, in the order they hurt
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The divergence audit was the project.&lt;/strong&gt; 507,316 checks against semver: 507,244 agreed and 72 did not. Every one of the 72 was then re-checked against the reference package's own &lt;code&gt;satisfies&lt;/code&gt;, and every one came back the same way, which is that the package contradicts itself. Fifty-six were &lt;code&gt;intersects&lt;/code&gt; cells and sixteen were &lt;code&gt;subset&lt;/code&gt;. Two more were crashes there and answers here.&lt;/p&gt;

&lt;p&gt;glob was 697 disagreements out of 228,852, and not one of them is a shrug. &lt;code&gt;print&lt;/code&gt; accounts for 576 of them, because their &lt;code&gt;[[:print:]]&lt;/code&gt; compiles as though it were &lt;code&gt;[[:cntrl:]]&lt;/code&gt;. &lt;code&gt;nonascii&lt;/code&gt; accounts for 91, because my POSIX classes are ASCII tables, which is a stated limit: &lt;code&gt;中&lt;/code&gt; is not &lt;code&gt;[[:alpha:]]&lt;/code&gt; here. &lt;code&gt;partial&lt;/code&gt; is 18 and &lt;code&gt;brace&lt;/code&gt; is 12. The counts are pinned, so a new disagreement lands in a bucket called &lt;code&gt;unknown&lt;/code&gt; and turns the suite red.&lt;/p&gt;

&lt;p&gt;The goal was never "it agrees with the package". The goal is that every place it does not agree is either a repaired bug or a decision somebody wrote down. A difference you cannot name is a gap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;lodash taught &lt;code&gt;{}&lt;/code&gt; a new trick.&lt;/strong&gt; Try &lt;code&gt;_.set({}, 'toString.polluted', 'yes')&lt;/code&gt;. A blocklist of &lt;code&gt;__proto__&lt;/code&gt;, &lt;code&gt;constructor&lt;/code&gt; and &lt;code&gt;prototype&lt;/code&gt; does not save you, because &lt;code&gt;toString&lt;/code&gt; is not on the list. The walk follows an inherited property, materialises it on the object, and writes there. From then on every object in the program carries it, and &lt;code&gt;_.pick({}, 'toString')&lt;/code&gt; on a completely unrelated empty object hands the value straight back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toString.polluted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// no error, nothing on the blocklist&lt;/span&gt;

&lt;span class="p"&gt;({}).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;polluted&lt;/span&gt;                   &lt;span class="c1"&gt;// 'yes', on every object in the program&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toString&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                   &lt;span class="c1"&gt;// hands it back from an unrelated empty object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix is not a longer list, it is a rule: a deep write never follows a property the object does not own. Which means my module behaves differently from the package it replaces, which means it belongs in the documented divergence list rather than being quietly described as compatible.&lt;/p&gt;

&lt;p&gt;lodash's dist runs in sloppy mode and an ESM module does not, so writes to frozen slots that silently did nothing there throw here. Every write now goes through &lt;code&gt;Reflect.set&lt;/code&gt; and every delete through &lt;code&gt;Reflect.deleteProperty&lt;/code&gt;: an impossible operation declines quietly with a lodash-compatible return value, and a dangerous one still throws. My first attempt swallowed the coercion complaints as well, which felt tidy and took the divergence count from three to eighty-seven. When the count goes up, put the change back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node ships no parser, and the honest door costs five hundred times the cheap one.&lt;/strong&gt; A codemod that writes a file it has not proved parses is a tool you use exactly once. There are three ways to reach a JavaScript parser without installing anything: &lt;code&gt;vm.Script&lt;/code&gt;, which rejects the word export and so cannot see modules at all; &lt;code&gt;vm.SourceTextModule&lt;/code&gt;, which needs a flag, and whose SyntaxError carries no position, so a failure has to be re-run through &lt;code&gt;node --check&lt;/code&gt; purely to learn which line broke; and spawning &lt;code&gt;process.execPath&lt;/code&gt; with &lt;code&gt;--check --input-type=module&lt;/code&gt;. The vm door costs 0.025ms and a function call. The spawn costs a process. Only the expensive one can see a module and tell you which line broke.&lt;/p&gt;

&lt;p&gt;Measured over 300 files: 8ms through the lexer pre-gate, 4,095ms through Node's real parser, one process per file. I kept the 4,095ms. The lexer is a free pre-filter that catches the obvious failures, and the spawn is the verdict. &lt;code&gt;bench.json&lt;/code&gt; prints both numbers side by side, so the price of being careful is visible rather than argued about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;const of = f(x)&lt;/code&gt; cost me an afternoon.&lt;/strong&gt; My binding resolver ends a declarator's pattern at &lt;code&gt;of&lt;/code&gt; or &lt;code&gt;in&lt;/code&gt;, because that is the shape of a for-of head. So &lt;code&gt;const of = f(x)&lt;/code&gt; ended before it began, no binding was recorded, and every later call to &lt;code&gt;of(item)&lt;/code&gt; was filed as a global. A rename would have missed every one of those sites and the diff would have looked fine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// pattern ends at `of`, so no binding is recorded&lt;/span&gt;
&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// filed as a global, and a rename never touches it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What caught it was not a unit test of the resolver. It was a property test over the whole repository: every name the resolver leaves unresolved must be a real global in the running Node. Three leaked names, and the suite pointed straight at them. If I keep one habit from this project it is that one, because example-based tests only check the cases you already thought of.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The proof had to stay too blunt to fool.&lt;/strong&gt; &lt;code&gt;tools/verify.mjs&lt;/code&gt; reads every &lt;code&gt;.mjs&lt;/code&gt; file in the repository, extracts import specifiers by six different syntaxes, and fails unless every single one resolves to a relative path or to something &lt;code&gt;module.isBuiltin&lt;/code&gt; recognises. It deliberately does not read &lt;code&gt;package.json&lt;/code&gt;. An empty manifest says nobody declared a dependency; this says nobody imported one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;node tools/verify.mjs
&lt;span class="go"&gt;nirdep -- zero-dependency proof
generated by: node tools/verify.mjs
node: v22.23.2   platform: linux

1. Manifest
PASS  package.json dependencies is empty (0 entries)
PASS  package.json devDependencies is empty (0 entries)
PASS  package.json peerDependencies is empty (0 entries)
PASS  package.json optionalDependencies is empty (0 entries)
PASS  no node_modules directory in the repository
PASS  no lockfile entries beyond the root package

2. Every import in the artifact resolves to a Node builtin or a relative path
PASS  540 import specifiers checked across 105 files

3. The standard library we actually use
      node:assert/strict   node:child_process   node:crypto   node:fs
      node:module          node:os              node:path     node:test
      node:url             node:util            node:vm       node:zlib
      12 builtin modules, 0 packages

RESULT: zero third-party runtime dependencies.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is also stupid on purpose, so it flags import-shaped text inside comments, strings and regular expression literals. The cost is real and slightly ridiculous: test fixtures live in JSON rather than in source, doc comments never write the word import followed by a quote, and one test builds its quote with &lt;code&gt;String.fromCharCode(39)&lt;/code&gt;. Adding an ignore pragma would have taken thirty seconds and destroyed the only thing the file is for. A blunt instrument nobody can fool is worth more than a clever one that can be.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faycku38qk5np9x4b0phl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faycku38qk5np9x4b0phl.png" alt=" " width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I am proudest of is a refusal
&lt;/h2&gt;

&lt;p&gt;Of the eleven packages, five are rewritable and six are advise-only, and a test asserts that the rewritable list stays shorter than the replaceable one, so the flattering ratio cannot quietly improve.&lt;/p&gt;

&lt;p&gt;minimist is advise-only even though &lt;code&gt;runtime/args&lt;/code&gt; replaces it outright. minimist hands back a flat bag of whatever it happened to find; &lt;code&gt;parse&lt;/code&gt; wants a declared spec. A codemod that treated those two as the same shape would print green and ship a broken program. supports-color, ansi-styles, commander, yargs and glob are advise-only for the same reason: the replacement exists, the shape differs, and no machine should be guessing at a call site.&lt;/p&gt;

&lt;p&gt;You can watch this land. The worked example declares six dependencies and installs twenty-three. &lt;code&gt;nirdep apply&lt;/code&gt; rewrites four files, and then the project will not start, because &lt;code&gt;Cannot find package 'minimist'&lt;/code&gt; is the correct output at that point rather than a bug. The walkthrough shows that error instead of cutting to the working version.&lt;/p&gt;

&lt;p&gt;One more refusal, and it is the one people ask about: nirdep never edits your &lt;code&gt;package.json&lt;/code&gt;. A tool that rewrites your manifest on your behalf is a tool you cannot trust with your imports.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one number that changed how I read tooling
&lt;/h2&gt;

&lt;p&gt;Removing glob from the example takes seven packages out of the tree. chalk takes six, semver takes three, lodash one, minimist one, and minimatch takes zero, because glob keeps minimatch alive.&lt;/p&gt;

&lt;p&gt;Add those up and you have accounted for eighteen of the twenty-two installed names. Remove all six together and all twenty-two go. The four that appear in nobody's column are minimatch and its own three children, shared by two dependencies, so owned alone by neither.&lt;/p&gt;

&lt;p&gt;Blast radius is a subtraction, not a sum: everything reachable from every root, minus everything still reachable from the roots that are staying. Any tool that reports it as a sum is overselling, and the honest version of that report is a worse-looking number.&lt;/p&gt;

&lt;p&gt;That minimatch row saying "removing it takes 0 packages out of the tree" is my favourite line in the whole output. It is the tool declining to round in its own favour.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Number&lt;/th&gt;
&lt;th&gt;What it counts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;third-party packages in the import graph, proved by reading imports rather than the manifest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;Node builtins the entire project resolves to&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;634&lt;/td&gt;
&lt;td&gt;tests in 55 files, on &lt;code&gt;node:test&lt;/code&gt;, with no test dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3,593&lt;/td&gt;
&lt;td&gt;conformance cases across the eleven packages replaced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;856,168&lt;/td&gt;
&lt;td&gt;differential checks against the packages being replaced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;769&lt;/td&gt;
&lt;td&gt;disagreements found on semver and glob, every one audited and given a cause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14,287&lt;/td&gt;
&lt;td&gt;lines in 42 files under &lt;code&gt;src/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;builds, byte for byte identical, both hashes published&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What seventy-two hours felt like
&lt;/h2&gt;

&lt;p&gt;Writing the modules was maybe a third of it. The rest went on the harnesses, and on the arguments the harnesses started.&lt;/p&gt;

&lt;p&gt;That ratio is the thing I did not expect. You do not get a replacement by writing a replacement. You get one by writing something whose job is to prove your replacement wrong, running it a few hundred thousand times, and then sitting with the disagreements one at a time until each has a name and a reason. Most of them will be your fault. A few will not be.&lt;/p&gt;

&lt;p&gt;A dependency is a promise about a stranger's future behaviour, and you cannot audit a promise. That is not a moral failing on anybody's part, it is just what the arrangement is. What you can audit is code you are able to read. Replacing a package does not delete the work, it moves the work somewhere your name is on it, and the only honest reason to do that is if you would rather own the bug than wait for the advisory.&lt;/p&gt;

&lt;p&gt;The 72 disagreements are the part I keep thinking about. Correctness is not really a property of code. It is a property of an argument somebody is prepared to make out loud. A package with 188 million weekly downloads has never had to make that argument about &lt;code&gt;intersects&lt;/code&gt;, because nobody swaps the arguments. I had to make it seventy-two times in one afternoon, and writing those arguments down turned out to be worth more than any of the code they were about.&lt;/p&gt;




&lt;p&gt;Repository: &lt;a href="https://github.com/ewwhardik/nirdep" rel="noopener noreferrer"&gt;https://github.com/ewwhardik/nirdep&lt;/a&gt;&lt;br&gt;
Playground, one HTML file, no network requests: &lt;a href="https://ewwhardik.github.io/nirdep/" rel="noopener noreferrer"&gt;https://ewwhardik.github.io/nirdep/&lt;/a&gt;&lt;br&gt;
Worked example, before and after: &lt;a href="https://github.com/ewwhardik/nirdep-example" rel="noopener noreferrer"&gt;https://github.com/ewwhardik/nirdep-example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Published by Nastik AI. Developed by Sai Ram Dash (Hardik).&lt;/p&gt;

</description>
      <category>hackathonraptors</category>
      <category>opensource</category>
      <category>security</category>
      <category>hardikdash</category>
    </item>
  </channel>
</rss>
